Skip to content

test(jdbc): pin lazy-begin state after a failed BEGIN - #145

Merged
magnusp merged 1 commit into
mainfrom
fix/i108-lazy-begin-state
Oct 23, 2026
Merged

magnusp merged 1 commit into
mainfrom
fix/i108-lazy-begin-state

Conversation

@magnusp

@magnusp magnusp commented Oct 23, 2026

Copy link
Copy Markdown
Owner

Fixes #108

Contract

Hrana 3 is the source of truth for transport, transaction and stream state; java.sql is the source of truth for the JDBC surface; xerial/sqlite-jdbc is a behavioral reference, not a copy target.

What changed

setAutoCommit(false) already sends nothing under the lazy begin from #99, and beginPending is derived as !autoCommit && baton == null, so a failed BEGIN needs no separate state fix. This PR adds the missing state-pin case instead of production code:

  • aFailedBeginPinsTheLazyBeginStateUntilTheRetrySucceeds fails the first BEGIN during a statement and then asserts:
    • getAutoCommit() stays false,
    • the failed BEGIN closes its stream, so no phantom transaction is left,
    • commit() and rollback() with no work send nothing and succeed,
    • the next statement retries BEGIN with a null baton (new stream) and then runs on the stream that BEGIN opened.

Production code is untouched: the derived state does not drift.

Evidence

Red (pre-#99 commit 8c9381b, where setAutoCommit(false) began eagerly), /tmp/xerial-parity-i108/red-pre99.log:

[ERROR] LibsqlConnectionTest.aFailedBeginPinsTheLazyBeginStateUntilTheRetrySucceeds:148 » SQL transaction end failed on server
	at LibsqlConnection.beginTransaction(LibsqlConnection.java:223)
	at LibsqlConnection.setAutoCommit(LibsqlConnection.java:300)

Green at the PR head (4811c7d), /tmp/xerial-parity-i108/lane-3-specific.log:

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS

Lanes (all commands with bare ./mvnw, as the queue brief requires instead of the plan's mise exec -- prefix):

Lane Command Result
1 new cases at trunk (1bc66f9) and head pass at both; red at pre-#99 for the asserted reason (lane-1-regression.log, red-pre99.log)
2 commit/rollback with a pending begin pass, sends nothing (lane-2-specific.log)
3 statement after a failed BEGIN pass, retries BEGIN on a new stream (lane-3-specific.log)
4 -pl libsql-jdbc test 265 tests, BUILD SUCCESS (lane-4-module-suite.log)
5 -pl libsql-conformance -am verify 123 tests, BUILD SUCCESS (lane-5-conformance.log)
6 -Pxerial-control verify 100 tests, BUILD SUCCESS (lane-6-control.log)
7 spotless:check BUILD SUCCESS (lane-7-spotless.log)
8 ./mvnw test BUILD SUCCESS (lane-8-reactor.log)
9 -Dtest=LibsqlConnectionTest 28 tests, BUILD SUCCESS (lane-9-specific.log)
10 -pl libsql-jdbc -am package -DskipTests BUILD SUCCESS, jar built (lane-10-package.log)

Perf probe (perf.log), three interleaved runs of ./mvnw -pl libsql-jdbc test:

  • trunk: 2166, 2115, 2102 ms → median 2115 ms
  • head: 3450, 2110, 2094 ms → median 2110 ms

Head median is within the ten percent rule. The first head run is a compile/warm-up outlier after the package lane; the remaining two pairs differ by under 20 ms.

Divergences

  • No production change. The plan allows this: the Non-auto-commit connections hold an idle Hrana stream that sqld expires #99 derived beginPending state already satisfies the pinned behavior.
  • Lanes run as ./mvnw without the mise exec -- prefix, per the queue brief (mise attempts an unrelated tool install here).
  • New test method name differs from the plan's wording; it covers the plan's failing-BEGIN-then-successful-retry plus the no-op commit and rollback checks.

A failed BEGIN during a statement must leave auto-commit off with no
open Hrana stream, so the next statement retries BEGIN on a new stream.
commit and rollback with no work stay no-ops after the failure, and the
JDBC mode is unchanged.

The lazy-begin state derived from #99 already satisfies this, so only
the state-pin case is added.

Fixes #108
@magnusp
magnusp merged commit 1c240cd into main Oct 23, 2026
6 checks passed
@magnusp
magnusp deleted the fix/i108-lazy-begin-state branch October 23, 2026 01:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

setAutoCommit(false) sets the flag before BEGIN succeeds

1 participant