cloudflare / cloudflare/workers-sdk
[wrangler] D1 SQL splitter does not treat bracket-quoted identifiers as quoted
- Dominant language
- TypeScript
- Stars
- 4.5k
- Forks
- 1.5k
- Avg merge
- 3d 8h
- Merged PRs (30d)
- 186
Description
### Which Cloudflare product(s) does this pertain to?
Wrangler core, D1
### What versions are you using?
`main` (reproduced at 898dc6e)
### Describe the Bug
`splitSqlIntoStatements()` in `packages/wrangler/src/d1/splitter.ts` scans for quotes so that SQL syntax inside them is not interpreted. It handles `'`, `"` and backticks, but not SQLite's bracket-quoted identifiers (`[name]`).
As a result a trigger body that references such an identifier is split apart. Given:
```sql
CREATE TRIGGER t AFTER INSERT ON items
BEGIN
UPDATE x SET [end] = 1;
UPDATE y SET z = 2;
END;
SELECT 1;
```
`splitSqlQuery()` returns four fragments instead of two:
```
CREATE TRIGGER t AFTER INSERT ON items\nBEGIN\n UPDATE x SET [end] = 1
UPDATE y SET z = 2
END
SELECT 1
```
Each fragment is then sent to D1 separately, so `wrangler d1 execute --file` and `wrangler d1 migrations apply` fail or apply a migration partially.
Notably `normalizeSqlLineEndings()`, in the same file, *does* treat `[` … `]` as a quote pair, so the two scanners disagree about the same syntax.
### Please provide a link to a minimal reproduction
The snippet above reproduces directly through `splitSqlQuery()`; no account or network access is needed.
### Additional context
Found while working on #15226, which fixes a different splitter issue (compound statement markers that are not padded with whitespace). This one is pre-existing and independent — it reproduces identically before and after that change — and needs a fix in the scanner rather than in the marker regexes, so it is filed separately. Happy to send a PR.
Contributor guide
Research direction
Start in packages/wrangler/src/d1/splitter.ts, reading splitSqlIntoStatements() alongside normalizeSqlLineEndings() to compare their quote handling. Reproduce the supplied trigger through splitSqlQuery() without network access, then add coverage showing bracket-quoted identifiers remain within one statement and the example yields two fragments.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, databases
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 84/100