Repository navigation
fix(jdbc): stop batches at the first failure and throw BatchUpdateException (#104) - #124
Merged
Merged
Conversation
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 #104
Contract
Hrana 3 is the source of truth for transport, values, and metadata.
java.sqlis the source of truth for the JDBC surface. xerial/sqlite-jdbc is the behavioral reference and conformance foundation, never a copy target.Protocol basis: Hrana
Batch,BatchCond, andBatchResult. Each step after the first carries{"type":"ok","step":i-1}, so sqld skips every later step once one fails and reports the skipped steps as nulls. The driver readsstep_resultsandstep_errorsand throws the JDBC contract on top.What changed
LibsqlConnection.executeBatchgives every step after the first anokcondition on the previous step.extractBatchResultsthrowsBatchUpdateExceptionat the first step error instead of returningStatement.EXECUTE_FAILEDin the array.Partial-count semantics
BatchUpdateException.getUpdateCounts()is the prefix of counts for the steps that ran, so it has exactly one entry per successfully executed step before the failure. A failure in the first step yields an empty array, a failure in the middle yields the leading counts, and a failure in the last step yields all earlier counts. Later steps do not run. In auto-commit each step commits on its own, so the steps before the failure stay committed. In transaction mode the caller decides withcommit()orrollback().Evidence
Red at trunk (
cb1c609, new tests, oldLibsqlConnection):Tests run: 21, Failures: 7inLibsqlConnectionTest. Every new batch case failed with "Expecting code to raise a throwable", plus the protocol-error case. Log:/tmp/xerial-parity-i104/lane-1-regression.log.Green at head (
e2bc38c):Tests run: 21, Failures: 0inLibsqlConnectionTest; module suiteTests run: 205, Failures: 0; root./mvnw testBUILD SUCCESS;spotless:checkBUILD SUCCESS;libsql-itests -am verify22 tests BUILD SUCCESS;libsql-conformance -am verify115 tests (1 skipped) BUILD SUCCESS;-Pxerial-control verify100 tests (1 skipped) BUILD SUCCESS;package -DskipTestsbuilds the jar.Live replay against real sqld (throwaway itest, run then removed so the committed diff stays within the plan's file list): a batch of
1, 1 (duplicate), 2throwsBatchUpdateExceptionwith counts[1], and only row 1 exists afterwards in both auto-commit and transaction mode. Rollback in transaction mode leaves the table empty. Log:/tmp/xerial-parity-i104/lane-2-specific.log.Perf
In-memory 1000-statement
executeBatch, 200 warmup batches then 300 measured, three interleaved runs per side: trunk medians 53.823, 53.833, 55.005 us; head medians 49.845, 48.754, 49.725 us. Trunk median 53.833 us, head median 49.725 us, so head is 7.6 percent faster, inside the 10 percent rule. Round trips are unchanged at one pipeline request per batch on both sides (requests=500for 500 batches). The conditions add about 37 bytes of JSON per step after the first, so the encoded request grows from 67,971 to 104,824 bytes for 1000 steps in this probe.Divergence
None. The driver now matches the JDBC and sqlite-jdbc stop-at-first-failure behavior.
LibsqlErrorMapperstill has an unusedBatchUpdateExceptionimport from before this change; removing it is outside this PR's file list and is left as a follow-up.Base:
cb1c609d2c1a0b13c3b3e55cfeb66c7e94da9e7cHead:
e2bc38ce0cf3af4b7bdca70e21a30334da97d5e1