Skip to content

fix(sqlite): run multi-statement batches in source order - #470

Merged
tianzhou merged 1 commit into
bytebase:mainfrom
vishalhabib99:fix/sqlite-statement-order
Oct 10, 2026
Merged

tianzhou merged 1 commit into
bytebase:mainfrom
vishalhabib99:fix/sqlite-statement-order

Conversation

@vishalhabib99

Copy link
Copy Markdown
Contributor

Summary

The SQLite connector splits a multi-statement batch into writes and reads and runs all writes before any reads. A read that comes before a write in the batch therefore sees the write's effects:

SELECT a AS before_delete FROM t;   -- t has 3 rows
DELETE FROM t;
SELECT count(*) AS after_delete FROM t;

returns DELETE (3), then before_delete: [], then after_delete: 0. The first SELECT comes back empty and the result sets are reordered. PostgreSQL (and MySQL/MariaDB via native multi-statement) run in source order.

The split dates from when writes were batched through .exec() for speed (16e870b). Writes now run one at a time via prepare().run(), so it no longer buys anything. This PR runs each statement in the order written and branches on returnsRows() per statement. The per-statement PRAGMA query_only = ON re-assert and the maxRows truncation probe are unchanged.

I updated should handle maxRows in multi-statement execution, which asserted the writes-first order. If that order is intended, happy to close this and keep the behavior documented instead.

Test plan

  • New should execute multi-statement batches in source order (fails on main, passes here)
  • Updated should handle maxRows in multi-statement execution, which asserted the writes-first order
  • pnpm test:unit: 1201/1201
  • sqlite, multi-sqlite, execute-sql and json-rpc integration tests pass
  • Read-only mode still rejects SELECT ...; PRAGMA query_only = OFF; DELETE ...

The SQLite connector split a batch into writes and reads and ran all
writes before any reads, so `SELECT ...; DELETE ...; SELECT ...` read
the table after the DELETE and returned an empty first result. Run each
statement in the order written instead, matching the PostgreSQL
connector. The per-statement read-only backstop and maxRows probe are
unchanged.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The implementation is focused, preserves existing safeguards, and includes appropriate integration coverage.

0 open findings

What changed in this PR

Runs SQLite multi-statement batches in source order, aligning results with statement order.

Changes:

  • Executes each SQLite statement sequentially.
  • Adds and updates integration coverage for ordering and row limits.
File Description
src/​connectors/​sqlite/​index.ts Preserves source execution order.
src/​connectors/​__tests__/​sqlite.integration.test.ts Verifies ordering and updated semantics.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@tianzhou tianzhou left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks for the contribution.

@tianzhou
tianzhou merged commit f7b3146 into bytebase:main Oct 10, 2026
2 checks passed
@vishalhabib99

Copy link
Copy Markdown
Contributor Author

Thanks @tianzhou for the quick review and merge.

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.

3 participants