Skip to content

[wrangler] Fix D1 SQL splitter under-splitting migrations with a CASE...END followed by a comma - #15234

Open
mittalpk wants to merge 4 commits into
cloudflare:mainfrom
mittalpk:fix/d1-splitter-case-end-comma
Open

[wrangler] Fix D1 SQL splitter under-splitting migrations with a CASE...END followed by a comma#15234
mittalpk wants to merge 4 commits into
cloudflare:mainfrom
mittalpk:fix/d1-splitter-case-end-comma

Conversation

@mittalpk

@mittalpk mittalpk commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Fixes #15162

splitSqlIntoStatements() tracks nested BEGIN/CASE blocks so it doesn't split a semicolon that's inside a trigger body or a CASE expression. It detected the end of a block by checking whether END was followed by ; or whitespace — but a CASE used as a value expression (e.g. SET x = CASE ... END, y = 1, which is exactly what the reporter's real migration file does) is legitimately followed directly by a comma. When that happened, the block's END went undetected, leaving the splitter's internal nesting tracker permanently one level too deep for the rest of the file — every remaining statement got silently merged into one giant blob instead of being split correctly.

Reproduced with the reporter's linked repro repo: the 5th migration file (667 lines, ~193 real statements) was being collapsed into 2. Passing that single oversized "statement" through D1's local batch() execution is what produced the reported database table is locked: SQLITE_LOCKED error — confirmed by rebuilding wrangler both with and without the fix and running the exact repro both ways, live.

Fix: broaden the single trailing-character check from [;\s] to any non-identifier character, so END, and END) are recognized the same way END; and END already were.

  • Tests
    • Tests included/updated
  • Public documentation
    • Documentation not necessary because: internal fix to existing SQL-splitting logic; no new command, flag, or user-facing behavior to document beyond the changeset

…...END followed by a comma

isCompoundStatementEnd() only recognized END as closing a compound
statement when the next character was ';' or whitespace. A CASE used
as a value expression (SET x = CASE ... END, y = 1) is legitimately
followed directly by a comma, so that END went undetected, leaving the
splitter's nesting tracker permanently one level too deep for the rest
of the file -- every remaining statement got silently merged into one
oversized blob.

Broadened the check to any non-identifier character, matching what
already worked for ';' and whitespace.

Fixes cloudflare#15162.
@changeset-bot

changeset-bot Bot commented Aug 17, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: d33fed6

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-plugin 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

@github-project-automation github-project-automation Bot moved this to Untriaged in workers-sdk Aug 17, 2026
@workers-devprod
workers-devprod requested review from a team and jamesopstad and removed request for a team August 17, 2026 09:09
@workers-devprod

Copy link
Copy Markdown
Contributor

Codeowners approval required for this PR:

  • @cloudflare/d1
  • @cloudflare/wrangler
Show detailed file reviewers
  • .changeset/d1-splitter-case-end-comma.md: [@cloudflare/wrangler]
  • packages/wrangler/src/tests/d1/splitter.test.ts: [@cloudflare/d1 @cloudflare/wrangler]
  • packages/wrangler/src/d1/splitter.ts: [@cloudflare/d1 @cloudflare/wrangler]

@pkg-pr-new

pkg-pr-new Bot commented Aug 17, 2026

Copy link
Copy Markdown
@cloudflare/autoconfig

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

@cloudflare/build-output-utils

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

@cloudflare/codemods

npm i https://pkg.pr.new/@cloudflare/codemods@15234

@cloudflare/config

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

create-cloudflare

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

@cloudflare/deploy-helpers

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

@cloudflare/kv-asset-handler

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

miniflare

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

@cloudflare/pages-functions

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

@cloudflare/pages-shared

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

@cloudflare/unenv-preset

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

@cloudflare/vite-plugin

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

@cloudflare/vitest-plugin

npm i https://pkg.pr.new/@cloudflare/vitest-plugin@15234

@cloudflare/workers-auth

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

@cloudflare/workers-editor-shared

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

@cloudflare/workers-utils

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

wrangler

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

commit: d33fed6

devin-ai-integration[bot]

This comment was marked as resolved.

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

…ed CASE

isCompoundStatementEnd() was broadened to accept any non-identifier
character after END (to fix cloudflare#15162's comma case), but
isCompoundStatementStart() still required whitespace immediately
before CASE/BEGIN. A parenthesised CASE used as a value expression,
e.g. (CASE ... END), is preceded by '(' with no space -- its start was
never detected, but its END now was. That let an inner CASE's END)
prematurely close an unrelated, already-open compound statement (e.g.
an enclosing trigger's BEGIN ... END), corrupting the split.

Broadened isCompoundStatementStart() the same way, so detection is
symmetric on both sides.

Thanks to Devin Review for catching this.
@workers-devprod

Copy link
Copy Markdown
Contributor

Codeowners approval required for this PR:

  • @cloudflare/d1
  • @cloudflare/wrangler
Show detailed file reviewers
  • .changeset/d1-splitter-case-end-comma.md: [@cloudflare/wrangler]
  • packages/wrangler/src/tests/d1/splitter.test.ts: [@cloudflare/d1 @cloudflare/wrangler]
  • packages/wrangler/src/d1/splitter.ts: [@cloudflare/d1 @cloudflare/wrangler]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Untriaged

Development

Successfully merging this pull request may close these issues.

wrangler d1 migrations apply --local fails with SQLITE_LOCKED while remote D1 succeeds

2 participants