Skip to content

fix(jdbc): map in-transaction Hrana errors through the error mapper - #149

Merged
magnusp merged 1 commit into
mainfrom
fix/i109-error-mapping
Oct 23, 2026
Merged

magnusp merged 1 commit into
mainfrom
fix/i109-error-mapping

Conversation

@magnusp

@magnusp magnusp commented Oct 23, 2026

Copy link
Copy Markdown
Owner

Fixes #109

Contract: Hrana 3 is the source of truth for transport, values, metadata, batching, transactions, and error reporting. java.sql is the source of truth for the JDBC surface. xerial/sqlite-jdbc is a behavioral reference, never a copy target.

Inside a transaction, a StreamResult.Error was turned into a plain SQLException(message), so SQLState, vendor code, and the constraint category were lost. All four result sites now throw LibsqlErrorMapper.toSQLException(HranaError): executeStatement, beginTransaction, endTransaction, and extractBatchResults. BatchUpdateException now carries the mapped SQLState/vendor code and keeps the mapped exception as its cause.

Error.code is mapped when present. Because Hrana 3 says the codes are not yet stabilized, an unrecognized or absent code falls back to categorizing the SQLite message (UNIQUE constraint failed, FOREIGN KEY constraint failed, NOT NULL constraint failed, CHECK constraint failed), so a unique violation maps to SQLIntegrityConstraintViolationException / 23000 even when sqld sends no code.

Base: c3ef4de03b4188dfb98cc3e8d565b12ea41bec1b
Head: 2612b9e10a4ae23b673c9ef56e102e5d0ad3410d

Red: with the new LibsqlConnectionTest cases applied to trunk, 7 fail: the two transaction-mode halves of the unique-violation case and every explicit begin/execute/end/batch case; the auto-commit half passes on trunk (it already used the mapper). Log: /tmp/xerial-parity-i109/lane-1-regression.log.

Green: 36/36 LibsqlConnectionTest cases pass at the head (/tmp/xerial-parity-i109/green-unit.log).

Lanes (all at head 2612b9e, logs in /tmp/xerial-parity-i109/):

  1. Regression — red at trunk, green at head.
  2. Batch failure cases — pass; BatchUpdateException wraps the mapped cause.
  3. Four sites (begin, execute, end, batch) — pass; each maps 23000/19 where a constraint error is scripted.
  4. ./mvnw -pl libsql-jdbc test — 293 pass, BUILD SUCCESS.
  5. Conformance — 123 pass, 1 skipped, BUILD SUCCESS.
  6. xerial control — 100 pass, 1 skipped, BUILD SUCCESS.
  7. spotless:check — BUILD SUCCESS.
  8. Full reactor — BUILD SUCCESS.
  9. Live sqld (TransactionLifecycleIT#uniqueViolationKeepsItsMappedSqlStateInBothModes) — pass; real sqld error keeps 23000 in both modes.
  10. Package — jar builds.

Perf: three interleaved time ./mvnw -pl libsql-jdbc test runs per side, repeated once (six samples each). Trunk median 2.108 s, head median 2.111 s (+0.1%), within the 10% rule.

Files outside the plan's Files block:

  • LibsqlErrorMapper.java: required to add the HranaError overload and keep one mapping path, as the issue asks.
  • libsql-itests/.../TransactionLifecycleIT.java: lane 9 asks for a transaction-error itest; no existing case asserted SQLState against real sqld.

No other divergences.

@magnusp
magnusp merged commit de31dc6 into main Oct 23, 2026
6 checks passed
@magnusp
magnusp deleted the fix/i109-error-mapping branch October 23, 2026 01:50
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.

Errors inside a transaction lose SQLState and the vendor code

1 participant