Skip to content

Reset the statement when a step fails - #116

Open
ninjapanzer wants to merge 2 commits into
crystal-lang:masterfrom
ninjapanzer:reset-statement-on-step-failure
Open

ninjapanzer wants to merge 2 commits into
crystal-lang:masterfrom
ninjapanzer:reset-statement-on-step-failure

Conversation

@ninjapanzer

@ninjapanzer ninjapanzer commented Sep 3, 2026

Copy link
Copy Markdown

perform_exec raises when a step does not return SQLITE_DONE without calling sqlite3_reset first, so the statement is left active on the connection, which blocks COMMIT and holds the connection's implicit read transaction open until something happens to reset it. This resets on the failure path, building the exception first because it reads errmsg/errcode off the connection handle.

Fixes #115, where there is a standalone reproduction and the measurements behind the two things that make this awkward to reproduce by hand.

Testing:

  • spec/statement_reset_spec.cr against current master: 3 examples, 2 failures, 1 errors.
  • Full suite with the change: 334 examples, 0 failures, up from a 331 examples, 0 failures baseline, and crystal tool format is clean.
  • Standalone reproduction run against v0.23.0, master and the branch: the first two are identical, the third shows 0 active statements, three transactions committing, and the reader tracking a peer writer at data_version 3, 4, 5, 6 instead of holding 2.
  • A 26 MB application database driven through plain crystal-db: on master the reader shows one body across four peer commits and the peer's wal_checkpoint(TRUNCATE) returns busy=1 and copies nothing, on the branch both track correctly and the WAL truncates to 0 bytes.
  • The application this came from, with the patched shard vendored in: 834 examples, 0 failures, including its own specs written around the un-patched behaviour.

Crystal 1.19.1, SQLite 3.53.3, crystal-db 0.14.0, Linux.

Comment thread spec/statement_reset_spec.cr Outdated
Agreed, thanks.

Co-authored-by: Johannes Müller <straightshoota@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

perform_exec leaves a statement active when a step fails, poisoning COMMIT and silently freezing reads on that connection

2 participants