Skip to content

refactor(jdbc): move parameter metadata behind a view - #234

Merged
magnusp merged 2 commits into
mainfrom
refactor/i212-parameter-metadata-view
Oct 24, 2026
Merged

magnusp merged 2 commits into
mainfrom
refactor/i212-parameter-metadata-view

Conversation

@magnusp

@magnusp magnusp commented Oct 24, 2026 •

Copy link
Copy Markdown
Owner

Fixes #212

What changed

LibsqlPreparedStatement now holds one cached ParameterMetaDataView (package-private, new file) that owns the parameter count and the closed and index checks. getParameterMetaData() returns that view. The statement keeps implements ParameterMetaData and delegates the nine interface methods, so instanceof ParameterMetaData still holds for a prepared statement. The parameter-metadata paragraph moved from the statement's javadoc to the view.

Behavior preserved

  • getParameterMetaData() still throws after close, and metadata calls on a view taken before close still throw after close, because the view checks the owning statement.
  • Index message unchanged: Parameter index out of range: N.
  • Count still comes from SqlTokenizer.placeholderCount.
  • ParameterMetaData extends Wrapper, so the view delegates unwrap/isWrapperFor to the statement; unwrapping still reaches the statement.
  • No existing test edited, no message changed, pom.xml untouched.

Pins added

A follow-up commit, test(jdbc): pin parameter metadata invariants, adds seven characterization tests so the invariants above are enforced rather than asserted in prose. The class goes from 22 to 29 tests; the additions are pure insertions, with no existing assertion edited.

# Test Pinned behavior
1 getParameterMetaDataReturnsAViewWithThePlaceholderCount View is non-null and getParameterCount() equals the placeholder count (2 for two ?).
2 getParameterMetaDataAfterCloseThrows getParameterMetaData() after close() throws SQLException: Statement is closed.
3 parameterMetadataViewTakenBeforeCloseStillThrowsAfterClose A view obtained before close() throws from both getParameterCount() and getParameterType(1) afterwards.
4 parameterMetadataRejectsAnOutOfRangeIndex Index 0 throws SQLException with the exact message Parameter index out of range: 0.
5 preparedStatementRemainsAParameterMetaData statement instanceof ParameterMetaData holds.
6 getParameterMetaDataReturnsTheSameCachedView Two calls return the same instance, proving the view is cached.
7 parameterMetadataUnwrapReachesTheStatement Today's behavior pinned: isWrapperFor(ParameterMetaData.class) is true and unwrap(ParameterMetaData.class) returns the statement itself, because the view delegates to the statement's wrapper surface.

Mutant kills

Each mutation was made as a scratch edit, the test class was run, and the edit was reverted to a clean tree before committing.

Scratch mutation Result
Index message changed to Parameter index out of range [N] parameterMetadataRejectsAnOutOfRangeIndex failed: expected Parameter index out of range: 0, got Parameter index out of range [0].
Closed checks removed from getParameterMetaData() and from the view's getParameterCount()/checkParameterIndex() getParameterMetaDataAfterCloseThrows and parameterMetadataViewTakenBeforeCloseStillThrowsAfterClose both failed.

Diff

 .../jdbc/LibsqlPreparedStatement.java              | 87 ++++--------------------
 .../jdbc/ParameterMetaDataView.java                | 98 +++++++++++++++++++++++
 .../jdbc/LibsqlPreparedStatementTest.java          | 86 ++++++++++++++++++++++
 3 files changed, 200 insertions(+), 71 deletions(-)

Line counts

  • LibsqlPreparedStatement.java: 614 -> 559 lines (limit: under 560).
  • ParameterMetaDataView.java: 98 lines (new).

Probe

Inverted the closed check in ParameterMetaDataView.getParameterCount() so it threw while the statement was open. LibsqlPreparedStatementTest.parameterCountComesFromThePlaceholders failed at LibsqlPreparedStatementTest.java:265 with java.sql.SQLException: Statement is closed. Reverted; the same class then ran 22/22 green.

Lanes

Lane Command Result
unit ./mvnw -pl libsql-jdbc -am test 405 tests, 0 failures (baseline 398; +7 pins)
spotless apply ./mvnw spotless:apply BUILD SUCCESS (no reformat)
spotless ./mvnw spotless:check BUILD SUCCESS
conformance ./mvnw -pl libsql-conformance -am verify 272 tests, 0 failures, 7 skipped (baseline 272)
itests DOCKER_CONFIG="$PWD/libsql-conformance/src/test/docker-config" ./mvnw -pl libsql-itests -am verify 43 tests, 0 failures (baseline 43)

@magnusp
magnusp merged commit 6f0505e into main Oct 24, 2026
6 checks passed
@magnusp
magnusp deleted the refactor/i212-parameter-metadata-view branch October 24, 2026 18:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Move parameter metadata behind a view in LibsqlPreparedStatement

1 participant