Skip to content

Close a compound SQL statement when its END is lowercase - #15046

Merged
alsuren merged 3 commits into
cloudflare:mainfrom
erwinzhang7:fix-d1-splitter-lowercase-end
Aug 14, 2026
Merged

alsuren merged 3 commits into
cloudflare:mainfrom
erwinzhang7:fix-d1-splitter-lowercase-end

Conversation

@erwinzhang7

@erwinzhang7 erwinzhang7 commented Aug 5, 2026 •

Copy link
Copy Markdown
Contributor

Spotted while investigating #14991. Independent of that issue and of any fix for it.

The bug

splitSqlQuery() matches the two ends of a compound statement asymmetrically:

function isCompoundStatementStart(str: string) { return /\s(BEGIN|CASE)\s$/i.test(str); }  // case insensitive
function isCompoundStatementEnd(str: string)   { return /\sEND[;\s]$/.test(str); }         // case sensitive

SQLite accepts either case. With a lowercase end, the compound statement never closes, so compoundStatementStack stays non-empty and every subsequent ; is treated as being inside the trigger body. Everything after the trigger is folded into it instead of being split out and executed.

CREATE TRIGGER IF NOT EXISTS update_trigger AFTER UPDATE ON items
begin
	DELETE FROM updates WHERE item_id=old.id;
end;
CREATE TABLE after_the_trigger (id TEXT PRIMARY KEY);

Before, 2 statements, with the CREATE TABLE swallowed:

[0] "CREATE TABLE t (id TEXT)"
[1] "CREATE TRIGGER g BEFORE DELETE ON t\nbegin\n  SELECT RAISE(ABORT,'no');\n..."

After, 3 statements, matching the uppercase behaviour exactly. CASE ... end inside a trigger body is affected the same way, collapsing 3 statements into 1.

Why it was not caught

should handle compound statements for BEGINs already exercises a lowercase begin, so case insensitivity was clearly intended. But every case in that test pairs it with an uppercase END, so only the start predicate was ever exercised in lowercase.

Change

One character: add the i flag to isCompoundStatementEnd, so both predicates agree.

This does not widen what counts as an end marker beyond the existing behaviour. \sEND still requires whitespace immediately before, so an identifier such as weekend; does not match, exactly as it did not before.


  • Tests
    • Tests included/updated
    • Automated tests not possible - manual testing has been completed as follows:
    • Additional testing not necessary because:
  • Public documentation
    • Cloudflare docs PR(s):
    • Documentation not necessary because: this restores the documented and already intended behaviour of statement splitting. DISTINCT/BEGIN/END case handling is not described anywhere in the public docs, and nothing about the supported SQL surface changes.

Added should handle a lowercase end closing a compound statement, placed next to the existing lowercase-begin coverage. Verified it is a real regression test rather than a passing assertion: with the i flag reverted the suite reports 1 failed of 16, and with the fix 16 of 16 pass. oxfmt --check is clean on both changed files.

@changeset-bot

changeset-bot Bot commented Aug 5, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2585d69

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
wrangler Patch
@cloudflare/vite-plugin Patch
@cloudflare/vitest-pool-workers Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@workers-devprod
workers-devprod requested review from a team and dario-piotrowicz and removed request for a team August 5, 2026 17:10
@workers-devprod

workers-devprod commented Aug 5, 2026 •

Copy link
Copy Markdown
Contributor

Codeowners approval required for this PR:

  • ✅ @cloudflare/d1
  • ✅ @cloudflare/wrangler
Show detailed file reviewers

devin-ai-integration[bot]

This comment was marked as resolved.

@alsuren alsuren 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.

approve once changeset is fixed

@erwinzhang7

Copy link
Copy Markdown
Contributor Author

Good catch, and correct on both counts. I had not read REVIEW.md before writing that changeset.

Rewritten in user-facing terms: it now says which commands are affected, what a user actually sees (statements after the block silently skipped), and keeps a short example. Dropped the reference to the internal helper and the paragraph about existing test coverage.

I also confirmed the CASE half of your suggestion before putting it in the changelog rather than taking it on faith. Without the fix, a trigger whose body contains a CASE ... end collapses from 3 statements to 1, so CASE blocks are affected the same way as BEGIN blocks and the changeset now mentions both.

@dario-piotrowicz dario-piotrowicz 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.

Looks good to me! 😄

Thanks for the fix @erwinzhang7 😄

Comment thread packages/wrangler/src/__tests__/d1/splitter.test.ts Outdated
Comment thread .changeset/d1-splitter-lowercase-end.md Outdated

@workers-devprod workers-devprod 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.

Codeowners reviews satisfied

@github-project-automation github-project-automation Bot moved this from Untriaged to Approved in workers-sdk Aug 5, 2026
@pkg-pr-new

pkg-pr-new Bot commented Aug 5, 2026 •

Copy link
Copy Markdown
@cloudflare/autoconfig

npm i https://pkg.pr.new/@cloudflare/autoconfig@15046

@cloudflare/build-output-utils

npm i https://pkg.pr.new/@cloudflare/build-output-utils@15046

@cloudflare/config

npm i https://pkg.pr.new/@cloudflare/config@15046

create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@15046

@cloudflare/deploy-helpers

npm i https://pkg.pr.new/@cloudflare/deploy-helpers@15046

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@15046

miniflare

npm i https://pkg.pr.new/miniflare@15046

@cloudflare/pages-functions

npm i https://pkg.pr.new/@cloudflare/pages-functions@15046

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@15046

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@15046

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@15046

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@15046

@cloudflare/workers-auth

npm i https://pkg.pr.new/@cloudflare/workers-auth@15046

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@15046

@cloudflare/workers-utils

npm i https://pkg.pr.new/@cloudflare/workers-utils@15046

wrangler

npm i https://pkg.pr.new/wrangler@15046

commit: 2585d69

@erwinzhang7

Copy link
Copy Markdown
Contributor Author

Both taken, thank you.

Dropped the comment: the test name already says what it checks, and the history of why it broke belongs in the changeset rather than the test body.

Took the changelog title too, with the typo corrected: "Fixes D1 SQL statements not handling lowercase ends correctly".

Also filled in the description checkboxes, which is what the Check job was failing on rather than anything in the code.

The two Windows test failures look unrelated to this change. The suite passes on Linux and macOS, the failing jobs are fixtures and packages-and-tools rather than anything under d1, and this PR only touches a regex flag in the SQL splitter plus its test. Per REVIEW.md that pattern reads as a flake, so a rerun is probably all that is needed, but say the word if you would like me to dig into either job.

@erwinzhang7

Copy link
Copy Markdown
Contributor Author

The checks on this one are still pending workflow approval, could someone kick them off when you get a chance?

@erwinzhang7
erwinzhang7 force-pushed the fix-d1-splitter-lowercase-end branch from d2dc2e8 to 3acbc9b Compare August 8, 2026 02:26
@erwinzhang7

Copy link
Copy Markdown
Contributor Author

Hi! The CI failure was miniflare#test:ci (dev-registry tests), which is unrelated to this change since it only touches packages/wrangler/src/d1/. I've rebased onto main to pick up the recent dev-registry fixes. Could someone approve the workflow runs? Thanks!

@erwinzhang7

Copy link
Copy Markdown
Contributor Author

Both failures look unrelated to this change. Tests (Windows, fixtures) fails in @fixture/worker-with-unsafe-external-plugin, and Vite Plugin Playground fails pulling the proxy-everything container. This PR only touches packages/wrangler/src/d1/splitter.ts and its test.

@alsuren
alsuren enabled auto-merge (squash) August 10, 2026 16:48
@alsuren

alsuren commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

I think the main branch is locked while the wrangler team do a release. I've set it to auto-merge. Hopefully it will go in once the release is out.

Thanks for your contribution.

@petebacondarwin
petebacondarwin force-pushed the fix-d1-splitter-lowercase-end branch from 3acbc9b to afbb076 Compare August 11, 2026 20:17
@workers-devprod

Copy link
Copy Markdown
Contributor

Codeowners approval required for this PR:

  • ✅ @cloudflare/d1
  • ✅ @cloudflare/wrangler
Show detailed file reviewers

splitSqlQuery matched the opening BEGIN/CASE of a compound statement case
insensitively but matched the closing END case sensitively. SQLite accepts
either case, so a trigger written with a lowercase end never closed and
every following statement was folded into the trigger body instead of
being split out.

The existing tests already covered a lowercase begin, but always paired it
with an uppercase END, so the asymmetry went unnoticed.
@petebacondarwin
petebacondarwin force-pushed the fix-d1-splitter-lowercase-end branch from 0baae01 to 2585d69 Compare August 12, 2026 13:03
@alsuren
alsuren merged commit 186339c into cloudflare:main Aug 14, 2026
73 of 78 checks passed
@github-project-automation github-project-automation Bot moved this from Approved to Done in workers-sdk Aug 14, 2026
atiqrahmanx added a commit to atiqrahmanx/workers-sdk that referenced this pull request Aug 14, 2026
Resolves a conflict in packages/wrangler/src/d1/splitter.ts with cloudflare#15046,
which added the case-insensitive flag to the compound-statement END
marker. This branch's pattern already carries that flag and additionally
treats punctuation as a token boundary, so the branch's version is kept.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants