Repository navigation
fix(jdbc): reject unsupported type maps and report holdability - #95
Merged
Merged
Conversation
This was referenced Oct 22, 2026
magnusp
added a commit
that referenced
this pull request
Oct 23, 2026
… getters (#146) Fixes #114 Closes #27 ## Contract Hrana 3 is the source of truth for transport, values, metadata, batching, transactions, and error reporting. `java.sql` is the source of truth for the JDBC surface. xerial/sqlite-jdbc is a behavioral reference and conformance foundation, never a copy target. Protocol basis: `Value.Blob` is base64 on the wire, so streams and blobs materialize locally from the decoded bytes. Unsupported optional features throw `SQLFeatureNotSupportedException` per JDBC. ## What changed - `LibsqlResultSet`: every remaining `UnsupportedOperationException` replaced with `SQLFeatureNotSupportedException` (all `update*`, `getRef`, `getArray`, `getURL`, `getRowId`, `getNClob`, `getSQLXML`, `getAsciiStream`, `getUnicodeStream`, `getNCharacterStream`). - `getBinaryStream(int/String)` over `getBytes` and `getCharacterStream(int/String)` over `getString`; SQL NULL returns null. - Read-only `getBlob(int/String)` and `getClob(int/String)` over the materialized value, with the full read side of `java.sql.Blob`/`Clob`; write methods throw `SQLFeatureNotSupportedException`. - `getObject(int, Map)` and `getObject(String, Map)` reject a non-empty map with `SQLFeatureNotSupportedException("Type maps are not supported")`; null and empty maps keep the existing behavior. - `findColumn(null)` throws `SQLException("column label cannot be null")` instead of `NullPointerException`. - `LibsqlDatabaseMetaData`: 14 unsupported metadata methods now throw `SQLFeatureNotSupportedException`. ## #27 answer Read side supported: `getBlob`/`getClob` and the full read surface of `Blob`/`Clob` (length, `getBytes`/`getSubString`, streams, position, free), plus `getBinaryStream` and `getCharacterStream`. Write side not supported: `PreparedStatement.setBlob`/`setClob` and the `Blob`/`Clob` mutators are outside this PR's Files block and still throw `SQLFeatureNotSupportedException`. `getAsciiStream`, `getUnicodeStream`, and `getNCharacterStream` also remain unsupported (see divergences). ## Divergences - xerial supports `getAsciiStream`, `getUnicodeStream`, and `getNCharacterStream`; this PR leaves them unsupported because the plan's Build limits stream implementation to `getBinaryStream` and `getCharacterStream`. They now throw the checked JDBC exception, so `catch (SQLException)` callers survive. - xerial returns unsupported for `getBlob`; this driver implements it because Hrana already carries the decoded blob bytes and #27 asks for blob support. It is read-only. - xerial throws unsupported for `getObject(Map)` unconditionally; this driver accepts null and empty maps and rejects only a non-empty map, matching #95's `setTypeMap` contract. ## Evidence Red (trunk `1c240cd` with these test files, `/tmp/xerial-parity-i114/lane-1-regression.log`): 67 tests, 4 failures and 4 errors. The new stream, blob, map, findColumn, and sweep cases fail on `UnsupportedOperationException`, the ignored type map, and the null-label NPE. Green (head `47ea3f2`, same log): 67 tests, 0 failures, BUILD SUCCESS. Lanes (logs under `/tmp/xerial-parity-i114/`): 1. Regression, trunk red to head green: pass. 2. Byte-for-byte stream content: 4 tests pass. 3. Unchecked-exception sweep over both classes: 2 tests pass, no `UnsupportedOperationException`. 4. `./mvnw -pl libsql-jdbc test`: 273 tests, BUILD SUCCESS. 5. `./mvnw -pl libsql-conformance -am verify`: 123 tests, 1 skipped, BUILD SUCCESS, no new divergence. 6. `./mvnw -pl libsql-conformance -am -Pxerial-control verify`: 100 tests, 1 skipped, BUILD SUCCESS. 7. `./mvnw spotless:check`: BUILD SUCCESS. 8. `./mvnw test`: BUILD SUCCESS. 9. #27 surface: recorded in `lane-9-specific.log`. 10. `./mvnw -pl libsql-jdbc -am package -DskipTests`: jar built. Perf: `./mvnw -pl libsql-jdbc test` medians over three interleaved runs, trunk 2.159 s versus head 2.167 s, +0.4 percent, within the 10 percent rule. Files touched: only the four files in the plan's Files block. Base `1c240cd`, head `47ea3f2`.
This was referenced Oct 23, 2026
magnusp
added a commit
that referenced
this pull request
Oct 23, 2026
…ocs (#159) Fixes #116 Closes #77 Closes #96 ## What changed - Re-triaged every rejected class against the current driver. Four classes changed state. - `TypeMapTest` keeps its upstream rejection, but the reason is now true: #95 rejects connection type maps with `SQLFeatureNotSupportedException` because java.sql makes them optional, and xerial stores a map it never applies. The control run executes the same vendored test as the libSQL run, so a single assertion cannot pass on both. The stale "accepts but ignores" text is gone (#96). - `DBMetaDataTest`, `StatementTest`, and `PrepStmtTest` still fail against the current driver. The plan's triage rule says a real driver gap becomes a new issue and an exclusion, never a protocol divergence, and the plan's Files block is manifest plus docs only. They stay upstream with the new issues as their reason: - #156 `DBMetaDataTest`: 45 of 56 pass. Seven metadata methods throw where xerial returns a java.sql-shaped empty result set; `getColumns`, `getCrossReference`, and `getPrimaryKeys` disagree on filtering and order; sqld rejects `CREATE TEMP TABLE`. - #158 `StatementTest`: 38 of 46 pass. `getDate('')`, `setDate` millis, `setFetchDirection(999)`, and `executeBatch` with a SELECT are driver gaps. Multi-statement SQL, `CREATE TEMP TABLE`, and the open-result-set DROP lock are remote-model cases that need divergences when the class selects. - #157 `PrepStmtTest`: `getParameterMetaData`, the CLOB/BLOB/stream setters, `clearParameters`, `setDate` millis, and supplementary-character round trips are driver gaps. Hrana has no describe statement, so pre-execution metadata and prepare-time validation are impossible-parity cases. - Regenerated `UPSTREAM.md` with the vendoring tool, so its `Paths` row now matches the vendored tree (#77). Added a Divergences section that names the four files with recorded edits. - Refreshed the stale `QueryTest` rationale found in the same triage. It imports sqlite-jdbc's `SQLiteConfig` and `FastDateFormat` classes. - Updated the #54 tracker: all 25 sub-issue boxes are checked, and the status note records the four re-triaged classes. No new divergence line is added. The four existing ones remain: - `CachedRowSetTest`: Hrana holds a namespace until its last connection closes, so the conformance copy closes the leaked connection. - `InsertQueryTest`: upstream misuses the connection factory, so the copy reuses the transaction connection and asserts rollback, commit visibility, and the final count (#51). - `JSON1Test`: Hrana holds a namespace until its last connection closes, so the copy closes the leaked per-test connections. - `PreparedStatementThreadTest`: upstream swallows every `ExecutionException`; Hrana serializes requests per stream, so the copy awaits both futures and fails on any runtime error (#51, #118). ## Contract Hrana 3 is the source of truth for transport, values, metadata, batching, transactions, and error reporting. `java.sql` is the source of truth for the JDBC surface. xerial/sqlite-jdbc 3.53.4.0 is the behavioral reference and conformance foundation, never a copy target. Every exclusion above cites the protocol, sqld, java.sql, or a tracked driver issue, with no bug recorded as a parity divergence. ## Red The four candidate suites at the PR base, fetched with `tools/export-upstream 3.53.4.0` and run against libSQL: ``` ./mvnw -pl libsql-conformance -am -Dit.test=DBMetaDataTest verify Tests run: 56, Failures: 3, Errors: 8, Skipped: 1 ./mvnw -pl libsql-conformance -am -Dit.test=StatementTest verify Tests run: 46, Failures: 4, Errors: 4, Skipped: 1 ./mvnw -pl libsql-conformance -am -Dit.test=PrepStmtTest verify Tests run: 43, Failures: 7, Errors: 8, Skipped: 0 ./mvnw -pl libsql-conformance -am -Dit.test=TypeMapTest verify Tests run: 2, Failures: 0, Errors: 2, Skipped: 0 ``` The failing method lists are in #156, #157, and #158. ## Green At `f36dcfcefc49545ef52cbe9608677380875c8dfb`: ``` tools/export-upstream --verify Verified upstream-xerial_sqlite-jdbc against upstream-xerial_sqlite-jdbc.manifest tools/export-upstream --verify-pinned Verified upstream hashes against cab7981c19ce04d691f0675f0b2586afc2bbf803 ./mvnw -pl libsql-conformance -am verify Tests run: 123, Failures: 0, Errors: 0, Skipped: 1, BUILD SUCCESS ./mvnw -pl libsql-conformance -am -Pxerial-control verify Tests run: 100, Failures: 0, Errors: 0, Skipped: 1, BUILD SUCCESS ./mvnw -pl libsql-conformance -am test BUILD SUCCESS ./mvnw -pl libsql-jdbc test BUILD SUCCESS ./mvnw test BUILD SUCCESS ./mvnw spotless:check BUILD SUCCESS ./mvnw -pl libsql-jdbc -am package -DskipTests BUILD SUCCESS ``` Trunk lane: `./mvnw -pl libsql-conformance -am verify` at `7c7d321` gives 123 run, 0 failures, 1 skipped. The head passes every test trunk passes. Perf, wall clock of `./mvnw -pl libsql-jdbc test`, interleaved three times per side: trunk median 2.45 s, head median 2.49 s, 1.6 percent over baseline. ## Files Only `upstream-xerial_sqlite-jdbc.manifest` and `upstream-xerial_sqlite-jdbc/UPSTREAM.md` change. No driver or test source changes. No files outside the plan's Files block. Base `7c7d32102e4b9e59b8e04d02ff095274ca76fbf2`, head `f36dcfcefc49545ef52cbe9608677380875c8dfb`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #48. Part of #54.
What changed
LibsqlConnection.getTypeMapandsetTypeMapnow throwSQLFeatureNotSupportedExceptioninstead of returning an immutable empty map or discarding the argument.LibsqlConnection.getHoldabilityreportsResultSet.CLOSE_CURSORS_AT_COMMIT;setHoldabilityrejects every other value. The three-argumentcreateStatement,prepareStatement, andprepareCalloverloads validate the holdability argument the same way.LibsqlStatement.getResultSetHoldability,LibsqlResultSet.getHoldability, andLibsqlDatabaseMetaData.getResultSetHoldabilityall reportCLOSE_CURSORS_AT_COMMIT;supportsResultSetHoldabilityaccepts only that value.LibsqlStatementandLibsqlResultSetnow store fetch size and reject negative values instead of returning a constant zero.LibsqlDriverSettingsTestcovering set-and-read for every setting, negative fetch size, rejected holdability, and metadata agreement.Contract decision
SQLFeatureNotSupportedException, per Steering.CLOSE_CURSORS_AT_COMMIT; other values rejected) in the connection, statement, result set, and metadata.Evidence
Failing before the fix
./mvnw -q -pl libsql-jdbc -am -Dtest=LibsqlDriverSettingsTest -Dsurefire.failIfNoSpecifiedTests=false testResult:
Tests run: 8, Failures: 8, Errors: 0, Skipped: 0. Holdability was1instead of2, type-map calls did not throw, and fetch size stayed0after being set.Passing after the fix
./mvnw -pl libsql-jdbc -am testResult:
Tests run: 178, Failures: 0, Errors: 0, Skipped: 0,BUILD SUCCESS.Result:
Tests run: 115, Failures: 0, Errors: 0, Skipped: 1,BUILD SUCCESS. This includes the selectedFetchSizeTestagainst a live sqld container.Result:
BUILD SUCCESS.libsql-itestswas not run because Steering does not ask for live-sqld integration tests for this issue; the conformance run was included because it exercises the fetch-size behavior changed here.Deviations
SQLFeatureNotSupportedExceptionwhere neither driver implements fetch size. The pinned xerial 3.53.4.0 does implement it (JDBC3ResultSet.getFetchSize/setFetchSizestore a row hint and reject negative values), and the vendored, selected conformance testorg.sqlite.FetchSizeTestcallsResultSet.setFetchSize(2)and requires it to succeed. Throwing would break the required conformance suite, so this PR matches the pinned driver instead. No silent no-op remains: the value round-trips and negative values are rejected.upstream-xerial_sqlite-jdbc.manifeststill saysTypeMapTestis removed because "libSQL accepts but ignores type maps". The driver now rejects type maps, so that reason is stale. The manifest belongs to the conformance lane, so it is left untouched.