Repository navigation
Conversation
The converter turns a Java value into the Hrana value for a target JDBC type per Appendix B Table B-5, and follows Table B-4 when no target is given. Unlisted pairs throw SQLFeatureNotSupportedException so the target is never ignored.
setObject(x, targetSqlType) now converts to the target type before binding, instead of ignoring the target and delegating to setObject(x).
Each Table B-4 and B-5 family asserts the Hrana value kind and the Boolean text format without a server.
|
Verdict: CLEAN at 0ea436c. Base Ten lanes PASS at the verdict head. Transcripts are under
Units are 1,497 tests, 476 failures, 0 errors. Every failure is an Appendix B read row owned by PR-3 or PR-5. The Appendix B setObject test is 33 of 33 green. Spotless is clean. The integration suite also improved from 63 to 45 failures at this head; the remaining rows are the wrapper and unsupported types owned by PR-3 and PR-5. Perf is PASS on the end-to-end rule. A 1,000-row insert loop across numeric, text, and temporal values runs at about 940 rows/s at trunk and 920 rows/s at head, inside 5 percent. The 100,000-row insert run named in the plan is not runnable on this setup. The server sync path caps inserts near 940 rows/s and the client's 10 second request timeout kills large batches, so 100,000 rows would take about two minutes per run. The conversion cost is measured instead with a 100,000-bind lane: trunk 16.0M binds/s, head 11.4M binds/s. That is a 29 percent conversion cost, dominated by CI is red only where Appendix B is red, by design. No review-bot comments to triage. STACK-READY. PR-3 branches from this head. |
|
Verdict correction, numbers. The 1,000-row insert means were about 923 rows/s at trunk and 906 at head, not 940 and 920. The 29 percent bind cost came from the runs 5 to 9 selection in the cited artifact; the runs vary between about 29 and 36 percent. "Dominated by BigDecimal" is an inference from the code path, not a measurement. The end-to-end conclusion is unchanged and inside 5 percent. Lane 2 in the original run used target INTEGER and |
## Why The driver mapped result values by storage class, so the declared type did not control metadata or `getObject`, and `setObject` ignored the target type. JDBC 4.3 Appendix B is the oracle. Seven stacked pull requests implement it. The stack cannot land link by link because the `main` ruleset requires the full build green at every head, and the Appendix B oracle is red until the last link. This PR lands the verified tip as one commit. ## What changed - Add the Appendix B oracle suite and the vendor table, then resolve one JDBC type per declared column for metadata and `getObject`. - Honor the `setObject` target type, add the missing getters and LOB wrappers, and support the offset temporal types. - Mark `ARRAY`, `STRUCT`, `REF`, `JAVA_OBJECT`, and `DISTINCT` N/A and reject unlisted Table B-6 conversions. - Publish the compliance profile, quarantine the four xerial tests that conflict with the spec, and record the policy. ## Scope The seven stacked PRs are #239, #240, #241, #242, #243, #244, and #245. No unrelated changes. `vendor/JDBC4-TYPE-MAPPING.md` is the oracle. ## Tradeoffs - The five unrepresentable types throw instead of emulating them. - The conformance quarantine is method-level. The lost checks are named in `libsql-conformance/README.md`. - An expression column with no `decltype` keeps the storage fallback, documented as a profile exception. ## Blast Radius Metadata and `getObject` now follow the declared type, so a `BIGINT` holding 42 returns `Long`, and an unlisted getter conversion throws. The default build was red from #239 through #245 by design and is green at this tip. ## Verification - `clean verify` at `0861960`: 2,006 tests, 0 failures, 7 skipped, about 63 seconds. - Appendix B unit 1,050 of 1,050, integration 148 of 148, conformance 270 of 270 with 7 skipped. - Clean clone at the same SHA: unit 1,510 of 1,510, integration 148 of 148. - Each link has a verdict and ten live lanes. The verdict comments are on #239 through #245.
Why
setObject(x, targetSqlType)ignored the target type and delegated tosetObject(x). A caller who asked forTypes.INTEGERcould store text, and the JDBC 4.3 Appendix B Table B-5 negative suite could not pass. PR-2 makes the target type part of the binding contract.What changed
JdbcValueConverterwithtoValue(Object)for the no-target Table B-4 path andtoValue(Object, int)for the Table B-5 target path. The converter is a pure function of the value and the target type.setObject(x, targetSqlType)and the four-argument overload now convert to the target type first, then to a HranaValue. The four-argument overload still ignoresscaleOrLength.SQLFeatureNotSupportedException.setNullstill accepts every target type.JdbcTypeMapping.sqlTypeName(int)so rejection messages name the JDBC type.Numeric targets use Java narrowing:
TINYINTtobyte,SMALLINTtoshort,INTEGERtoint,BIGINTtolong,REALtofloat,FLOATandDOUBLEtodouble,DECIMALandNUMERICtoBigDecimal.BITandBOOLEANbind integer0or1.BigIntegerbinds an integer, and boxedByteandShortbind integers.Clobcontent is read throughgetCharacterStreamandBlobcontent throughgetBinaryStream.Scope
libsql-jdbc/src/main/java/com/github/magnusp/libsql/jdbc/JdbcValueConverter.java(new)libsql-jdbc/src/main/java/com/github/magnusp/libsql/jdbc/LibsqlPreparedStatement.javalibsql-jdbc/src/main/java/com/github/magnusp/libsql/jdbc/JdbcTypeMapping.javalibsql-jdbc/src/test/java/com/github/magnusp/libsql/jdbc/LibsqlPreparedStatementTest.javaARRAY,STRUCT,REF,JAVA_OBJECT, andDISTINCTstill bindtoStringuntil PR-5, so their positive integration rows stay red on purpose. No read path changes.Tradeoffs
true/false, notTRUE/FALSE, so a text target round trips throughgetBoolean. Recorded here and in the converter Javadoc.DECIMALandNUMERICbind decimal text. Hrana has no decimal type, and this matches the existingsetBigDecimalbinding.Stringbound toDATE,TIME, orTIMESTAMPpasses through unchanged. That keeps the Table B-5 acceptance contract for any string and leaves malformed text to the getter.LocalDateandLocalTimeare rejected asTIMESTAMPtargets because Table B-5 does not list those pairs. The plan's prose bullet lists all seven temporal sources for all three temporal targets; the oracle table wins.Calendarandjava.util.DatetoARRAYis accepted as the table lists it, but still bindstoStringuntil PR-5.TIMEtoTIMESTAMPuses the epoch date because the date part is implementation defined.Blast Radius
Only the
setObjectbinding path changes.setBoolean,setInt,setBigDecimal, the date setters, and the stream setters keep their existing bindings. The no-target path changes deliberately: boxedByte,Short, andBigIntegernow bind integers;Calendar,java.util.Date, andLocalDateTimebind SQLite timestamp text;TimeandTimestampuse the same canonical SQLite text as the target path. No result-set or metadata behavior is touched.Verification
./mvnw -q -pl libsql-jdbc -Dtest='Jdbc4AppendixBSetObjectTest' -Dsurefire.failIfNoSpecifiedTests=false test— 33 tests, 0 failures, 0 errors (was 33 tests, 31 failures)../mvnw -q -pl libsql-jdbc -Dtest='LibsqlPreparedStatementTest' test— 39 tests, 0 failures, 0 errors../mvnw -q -pl libsql-jdbc test— 1,497 tests, 476 failures, 0 errors. Every failure is inJdbc4AppendixBReadTest: B-1 7, B-3 7, B-6 462 (461b6GetterHonoursSupportedJdbcTypes+ 1b6NumericGettersRejectNonNumericText). B-1, B-3, and B-6 are unchanged; there are no non-Appendix-B failures../mvnw -q spotless:check— clean.