Repository navigation
fix(jdbc): close the prepared-statement binding and metadata gaps - #161
Merged
Merged
Conversation
Derive the parameter count from the SQL placeholders and answer ParameterMetaData with Types.OTHER where Hrana has no describe. Bind SQL NULL for unset and cleared parameters on both statement paths. Convert the blob, clob, binary, ascii, unicode, and character stream setters locally. Encode surrogate pairs as one UTF-8 sequence in the direct Hrana JSON writer.
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.
Fixes #157
Hrana 3 is the source of truth for transport, values, metadata, batching, transactions, and error reporting.
java.sqlis 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.What changed
LibsqlPreparedStatementderives the parameter count from the SQL placeholders throughSqlTokenizer, and implementsParameterMetaData. The count is local; the type isTypes.OTHERbecause Hrana has no describe request.clearParameters(), bind SQL NULL. The prepared path pads to the placeholder count, and the plainStatementandaddBatch(String)paths pad too, because Hrana rejects a short argument list where SQLite reads an unbound parameter as NULL.setBlob,setClob,setBinaryStream,setAsciiStream,setUnicodeStream, andsetCharacterStream, with their length and no-length overloads, convert to a TEXT or BLOB value locally.setRef,setArray,setRowId, andsetSQLXMLnow throwSQLFeatureNotSupportedExceptioninstead of an unchecked exception.DirectHranaJsonCodec.writeStringencodes a surrogate pair as one UTF-8 sequence. It previously encoded each surrogate alone, which the UTF-8 encoder turned into two?bytes; this is the lossutfsaw. A codec test pins it.setDateis unchanged. It sends the normalizedjava.sql.Datetext. See the divergence section.Red
New cases at base
36c7201with only the test diff applied:Vendored
PrepStmtTestat the same base, with the triage copy selected temporarily:Green
At head
f098fc4:The 10 remaining cases are classified below. The fixed cases are
paramMetaData,clobRS,blobRS,clearParameters,utf, and the stream half ofset.Full lanes:
Perf, three interleaved runs of
./mvnw -pl libsql-jdbc test: base median 2.46 s, head median 2.50 s (+1.6%).Logs are in
/tmp/xerial-parity-i157/.Remaining failures and divergences
The control profile runs the same 43-case triage copy against xerial 3.53.4.0 and passes all 43, so each remaining case is behavior only the reference driver has.
date1anddate2are a reference divergence, consistent with StatementTest exposes statement lifecycle and conversion gaps #158. xerial storessetDateas epoch milliseconds, sogetLongandgetDateround-trip the original millis.java.sqldefines SQLDATEwithout a time, and thejava.sql.Date(long)constructor normalizes the time away before it reaches the database. The driver keeps the date-only value.getParameterTypeTestandgetParameterTypeTest_when_no_parameter_setare a protocol gap. Hrana has no describe statement, so a parameter type cannot be derived before execution. The expectedBIGINT/REALnames and theNo parameter has been set yetmessage are xerial's local bind-type inference. The driver returnsTypes.OTHERrather than faking the type.metaData,gh811_getMetadata_before_execution, andpreparedStatementShouldNotThrowIfNotAllParamsSetare a protocol gap.getMetaData()before execution needs a describe that Hrana does not have, so the driver returns null until a result set exists.noSuchTableandnoSuchColare a protocol gap.prepareStatementcannot validate SQL before execution for the same reason.setnow fails only at line 206, the reused result set after a later execute.java.sqlcloses the implicit result set when the statement executes again, so the vendored copy must reassignrs = prep.executeQuery(). The issue assigns that adjustment to the selection PR; this PR does not edit the vendored test.The later selection PR records these lines and adjusts the
setcopy.Triage method
PrepStmtTestis not in the vendored tree, so the run used a temporary copy underlibsql-conformance/src/test/java/org/sqlite/, removed before the commit. The copy drops four cases that drive sqlite-jdbc's own classes or configuration:pragmaGetGeneratedKeys,updateWithoutGeneratedKeys,constraintErrorCodeExecute, andconstraintErrorCodeExecuteUpdate. They useSQLiteConnection.getConnectionConfig(), thejdbc.get_generated_keysURL property,SQLiteException, andSQLiteErrorCode, none of which the libSQL driver exposes.Files
libsql-jdbc/src/main/java/com/github/magnusp/libsql/jdbc/LibsqlPreparedStatement.java,libsql-jdbc/src/main/java/com/github/magnusp/libsql/jdbc/LibsqlStatement.java,libsql-jdbc/src/main/java/com/github/magnusp/libsql/jdbc/SqlTokenizer.java,libsql-hrana-codec/src/main/java/com/github/magnusp/libsql/hrana/codec/DirectHranaJsonCodec.java,libsql-jdbc/src/test/java/com/github/magnusp/libsql/jdbc/LibsqlPreparedStatementTest.java,libsql-jdbc/src/test/java/com/github/magnusp/libsql/jdbc/LibsqlStatementTest.java,libsql-hrana-codec/src/test/java/com/github/magnusp/libsql/hrana/codec/DirectHranaJsonCodecTest.java.Base
36c7201062a6f1a3937713fd4b286db9c3f94da5, headf098fc4f8c49ef47ff5b644b3092f714bb6872ac.