Repository navigation
fix(jdbc): gate getObject numeric targets on storage class - #69
Merged
Merged
Conversation
Closes #34. Part of #54. Matches sqlite-jdbc 3.53.4.0: Integer, Long, Float, and Double convert only from INTEGER or FLOAT storage and throw 'Bad value for type X' otherwise, including NULL, TEXT, and BLOB. Short and Byte are no longer supported, and unsupported target types use SQLFeatureNotSupportedException. The target-type by storage-class matrix is documented on the method.
This was referenced Oct 22, 2026
magnusp
added a commit
that referenced
this pull request
Oct 22, 2026
Fixes #102 Contract: Hrana 3 carries only INTEGER, FLOAT, TEXT, and BLOB, so date/time meaning is a local SQLite convention; `java.sql` defines the getter surface; sqlite-jdbc is the behavioral reference, not the contract. Base: `168f69aff4cebe175699bf5b421decf6a49c3b09` Head: `fb993bd06de73bef417193faa803949cd24fe8e8` ## What changed `getDate`, `getTime`, and `getTimestamp` now switch on the `Value` storage class instead of parsing `getString()`: - INTEGER: milliseconds since the Unix epoch. - FLOAT: Julian day. - TEXT: SQLite date/time formats, including `yyyy-MM-dd HH:mm:ss.SSS`, bare dates, bare times, optional fractional digits, and an optional time-zone suffix. - BLOB: `Bad value for type <target>`; NULL: `null`. `LocalDate`, `LocalTime`, and `LocalDateTime` are built from the same storage-class result, so `getObject(column, X.class)` agrees with the corresponding `java.sql` getter. The #69 conversion table now documents these SQLite conventions instead of text parsing. ## Evidence - Red: `./mvnw -pl libsql-jdbc test -Dtest=LibsqlResultSetTest` at base + new tests -> 3 failures, all new cases (`/tmp/xerial-parity-i102/lane-1-regression.log`). - Green: same command at head -> 24 tests, 0 failures; with `LibsqlResultSetGetObjectTest` -> 43 tests, 0 failures (`/tmp/xerial-parity-i102/green-unit.log`). - Lane 2 exact inputs: TEXT `2024-01-02 10:00:00` and INTEGER `1700000000000` pass (`lane-2-specific.log`); xerial reference probe output recorded in `reference-probe.log` (TEXT -> 2024-01-02; INTEGER -> 2023-11-14 in Europe/Stockholm). - Lane 3: all valid datetime cases assert non-null across all six targets (`lane-3-specific.log`). - Lane 4 full module: BUILD SUCCESS, 238 tests (`lane-4-module-suite.log`). - Lane 5 conformance: BUILD SUCCESS, 123 tests, 1 pre-existing skip, no new divergence (`lane-5-conformance.log`). - Lane 6 xerial control: BUILD SUCCESS, 100 tests, 1 pre-existing skip (`lane-6-control.log`). - Lane 7 spotless:check: BUILD SUCCESS (`lane-7-spotless.log`). - Lane 8 full reactor: BUILD SUCCESS (`lane-8-reactor.log`). - Lane 9 `LibsqlResultSet*`: 116 tests, 0 failures (`lane-9-specific.log`). - Lane 10 package: BUILD SUCCESS (`lane-10-package.log`). - Perf: `./mvnw -pl libsql-jdbc test` 3x interleaved. Trunk median 2.12 s, head median 2.15 s, +1.4% (within 10%). ## Divergences - INTEGER is epoch milliseconds, not SQLite `unixepoch` seconds. sqlite-jdbc's default `date_precision` is MILLISECONDS, and the issue's `1700000000000` case requires it. - REAL Julian days convert as a UTC instant and are then rendered in the JVM default zone. xerial decomposes the Julian day into local calendar fields; SQLite Julian days are UTC-based, and no conformance test asserts REAL. - Bare-time TEXT uses SQLite's 2000-01-01 default date, so `getDate`/`LocalDate` return that date where xerial throws. This follows SQLite's time-value rule. - BLOB date/time targets throw `Bad value` instead of xerial's numeric fallback; BLOB is not a SQLite datetime storage class. - `getTime` returns a time-of-day, so `Time` does not carry the source date as xerial's TEXT path does. JDBC defines `getTime` as the time component. Co-authored-by: Magnus Persson <magnus@magnusp.github.com>
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 #34. Part of #54.
What changed
LibsqlResultSet.getObject(int, Class)now gatesInteger,Long,Float, andDoubleon the current value's SQLite storage class, matching xerial 3.53.4.0JDBC4ResultSet.getObject(int, Class)(JDBC4ResultSet.java:316-393). Only INTEGER and FLOAT storage convert; TEXT, BLOB, and NULL throwSQLException("Bad value for type <T>").ShortandBytebranches. They now throwSQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"), as do all other unsupported target types.requested type cannot be null.LibsqlResultSetGetObjectTestcovering INTEGER, FLOAT, numeric text, non-numeric text, blobs, NULL,Short,Byte, unsupported target types, and the null target type. Updated the old test that expected numeric text to convert throughgetObject.Contract decision
The xerial 3.53.4.0 gate wins, per #54's drop-in parity rule. Numeric wrapper targets convert only from INTEGER or FLOAT storage. This is a visible API reduction:
ShortandBytewere supported by this driver and are now rejected, and numeric text no longer converts to a numeric target throughgetObject(Class)(the plain numeric getters retain their SQLite coercion behavior).String,Boolean,BigDecimal,byte[], and the date/time targets keep their existing unrestricted conversions.Evidence
Failing before the fix (new tests against the old implementation):
Passing after the fix:
The conformance run includes the vendored xerial
ResultSetTestagainst live sqld, includinggetObjectWithRequestedType.Deviations
None. The
Short/Byteremoval and rejection of numeric text are xerial parity, not transport-driven deviations.