Skip to content

fix(jdbc): validate prepared statement kind before execution - #57

Merged
magnusp merged 1 commit into
mainfrom
fix/29-validate-statement-kind
Oct 21, 2026
Merged

magnusp merged 1 commit into
mainfrom
fix/29-validate-statement-kind

Conversation

@magnusp

@magnusp magnusp commented Oct 21, 2026

Copy link
Copy Markdown
Owner

Closes #29. Part of #54.

What changed

  • LibsqlPreparedStatement now classifies the statement kind once, at construction, and rejects wrong-kind calls before any execution:
    • executeQuery() on a non-result statement throws Query does not return results without calling the connection.
    • executeUpdate() on a result-producing statement throws Query returns results without calling the connection.
  • Added LibsqlPreparedStatementTest with behavior tests that record connection execution calls: wrong-kind calls assert zero calls, and right-kind calls still execute and return rows/update counts.
  • Covered INSERT, SELECT, INSERT ... RETURNING, and WITH ... SELECT.

Contract decision

Matched xerial 3.53.4.0 JDBC3PreparedStatement.java:73-78,110-116: validate the prepared statement kind before executing, using xerial's exact messages. execute() and the non-prepared LibsqlStatement paths are unchanged because xerial's Statement path still executes before reporting that the result kind is wrong.

Evidence

Failing before (production file reverted to HEAD, new tests kept):

./mvnw -pl libsql-jdbc -am -Dtest=LibsqlPreparedStatementTest -Dsurefire.failIfNoSpecifiedTests=false test
Tests run: 6, Failures: 3, Errors: 0, Skipped: 0
  executeQueryOnInsertThrowsWithoutExecuting       message was "PreparedStatement did not produce a ResultSet: ..."
  executeUpdateOnSelectThrowsWithoutExecuting      Expecting code to raise a throwable
  executeUpdateOnWithSelectThrowsWithoutExecuting  Expecting code to raise a throwable

Passing after:

./mvnw -pl libsql-jdbc -am test
Tests run: 9, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS

The prepared-statement test class runs 6/6 green. ./mvnw spotless:apply succeeds.

Deviations

Hrana does not expose SQLite's prepare-time column count without a server round trip, and the steering requires validation before any client call. The driver therefore classifies the kind lexically (comments, quoted literals, parenthesis depth, RETURNING, WITH bodies, and PRAGMA ... = ... assignments are handled). This is the only transport-forced deviation from xerial's columnCount approach; exotic SQL outside this classification could be treated as a non-result statement.

@magnusp
magnusp force-pushed the fix/29-validate-statement-kind branch from b5b13fd to f53b704 Compare October 21, 2026 21:37
@magnusp
magnusp merged commit 9588a09 into main Oct 21, 2026
5 checks passed
@magnusp
magnusp deleted the fix/29-validate-statement-kind branch October 21, 2026 21:41
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.

PreparedStatement executes SQL before validating result kind

1 participant