Skip to content

fix(jdbc): stop caching a failed product-version lookup - #133

Merged
magnusp merged 1 commit into
mainfrom
fix/i112-version-cache
Oct 22, 2026
Merged

magnusp merged 1 commit into
mainfrom
fix/i112-version-cache

Conversation

@magnusp

@magnusp magnusp commented Oct 22, 2026

Copy link
Copy Markdown
Owner

Summary

resolveDatabaseProductVersion no longer swallows a failed SELECT sqlite_version(). The "3.0" fallback is gone, the failure surfaces as a SQLException, and the next call retries. A closed connection now throws instead of returning a version, including when a version is already cached.

Fixes #112

Contract

Hrana 3 governs select sqlite_version() through execute; java.sql governs DatabaseMetaData; xerial/sqlite-jdbc is a behavioral reference only.

Change

  • resolveDatabaseProductVersion calls connection.checkClosed() before returning a cached value, so a closed connection throws even after a successful lookup.
  • The catch (SQLException) that wrote "3.0" into cachedDatabaseProductVersion is removed. Only a real version from the server is cached.
  • An empty result now throws SQLException("SELECT sqlite_version() returned no row") instead of falling back to "3.0".

Divergences

  • Empty result throws instead of returning "3.0". sqlite_version() always returns one row, so an empty result is a broken server response, not a legitimate default. Keeping the fallback, cached or not, would reintroduce the lie this issue reports.
  • cachedDatabaseProductVersion stays unsynchronized. Two concurrent first calls can each run the lookup; the last write wins and both values are real versions, so no fallback can be pinned. This is recorded for LibsqlConnection state is not synchronized #105, which owns connection-level concurrency.

Evidence

Red at trunk 4725e83, tests only, fix not applied (/tmp/xerial-parity-i112/lane-1-regression.log): Tests run: 27, Failures: 2 — both new cases fail with "Expecting code to raise a throwable."

Green at head c924c4b4c7bb:

  • Lane 1/2 (LibsqlDatabaseMetaDataTest): Tests run: 27, Failures: 0, Errors: 0. The failed lookup throws, the retry returns 3.45.1.
  • Lane 3: major/minor derive from the recovered value (3, 45).
  • Lane 4 (-pl libsql-jdbc test): Tests run: 235, Failures: 0, Errors: 0, BUILD SUCCESS.
  • Lane 5 (-pl libsql-conformance -am verify): Tests run: 115, Failures: 0, Errors: 0, Skipped: 1, BUILD SUCCESS, no new divergence.
  • Lane 6 (-Pxerial-control verify): Tests run: 100, Failures: 0, Errors: 0, Skipped: 1, BUILD SUCCESS; no new reference difference.
  • Lane 7 (spotless:check): BUILD SUCCESS.
  • Lane 8 (./mvnw test): BUILD SUCCESS.
  • Lane 10 (-pl libsql-jdbc -am package -DskipTests): jar built.

Lane 9: the diff keeps cachedDatabaseProductVersion unsynchronized; the #105 note above is the handoff.

Files touched: libsql-jdbc/src/main/java/com/github/magnusp/libsql/jdbc/LibsqlDatabaseMetaData.java, libsql-jdbc/src/test/java/com/github/magnusp/libsql/jdbc/LibsqlDatabaseMetaDataTest.java.

Base 4725e83 · Head c924c4b4c7bb.

Surface the SQLException instead of caching the 3.0 fallback, retry on
the next call, and throw on a closed connection even when a version is
already cached. Fixes #112.
@magnusp
magnusp merged commit 0e83a57 into main Oct 22, 2026
5 checks passed
@magnusp
magnusp deleted the fix/i112-version-cache branch October 22, 2026 22: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.

A failed product version lookup is cached for the whole connection

1 participant