SQLITE_ENABLE_UPDATE_DELETE_LIMIT selects two extra grammar rules, giving
UPDATE and DELETE the orderby_opt limit_opt tail that SELECT has. The
pinned build defines neither it nor SQLITE_UDL_CAPABLE_PARSER, so meyer
rejected those clauses outright -- correct for that build, and wrong for
anyone pointing sqlc at a database compiled with the option, whose valid
SQL meyer could not read.
parser.Options carries the fork. Its zero value is the pinned build, so
the corpus still defines the default behaviour (wherelimit.test expects
the rejection, byte offset included), and the same entry points hang off
Options as methods for a caller that needs the other side. Only top-level
statements grow the clauses: trigger_cmd has no orderby_opt or limit_opt
to gate, in either build.
The expectations in parser/options_test.go come from a SQLite built with
the option, which takes a Lemon run over src/parse.y rather than a -D on
the amalgamation -- the released amalgamation ships a parse.c generated
without the rules, so defining the macro against it changes nothing. The
recipe is at the top of that file. cmd/difftest, pointed at that build
with the option on, agreed with meyer on 228,652 mutations of the whole
corpus.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019kZMPnsTWywB5icVh1wJrA
SQLITE_ENABLE_UPDATE_DELETE_LIMIT selects two extra grammar rules, giving UPDATE and DELETE the orderby_opt limit_opt tail that SELECT has. The pinned build defines neither it nor SQLITE_UDL_CAPABLE_PARSER, so meyer rejected those clauses outright — correct for that build, and wrong for anyone pointing sqlc at a database compiled with the option, whose valid SQL meyer could not read.
The shape
parser.Options carries the fork. Its zero value is the pinned build, so the corpus still defines the default behaviour (wherelimit.test expects the rejection, byte offset included), and the same entry points hang off Options as methods for a caller that needs the other side:
Only top-level statements grow the clauses: trigger_cmd has no orderby_opt or limit_opt to gate, in either build.
Verification
The expectations in parser/options_test.go come from a SQLite built with the option, which takes a Lemon run over src/parse.y rather than a -D on the amalgamation — the released amalgamation ships a parse.c generated without the rules, so defining the macro against it changes nothing (confirmed: no call to updateDeleteLimitError survives in it). The recipe is at the top of that file: build tool/lemon.c, regenerate parse.c with the define, splice it into sqlite3.c over the region marked Begin file parse.c, compile with the define. Lemon assigns the same token numbers either way — the generated parse.h is byte-identical — so the splice is sound.
Against that build:
go test ./..., gofmt and go vet are clean; the corpus is untouched.
Note for follow-up
SQLITE_ENABLE_ORDERED_SET_AGGREGATES is the only other gate in parse.y that adds grammar (f(x) WITHIN GROUP (ORDER BY y)), so it is the only other way meyer can reject SQL a real build accepts. WITHIN joins the %fallback ID set under the same gate, so it would need no keyword-table change, and percentile.test already carries the "off" side. SQLite's docs call it off by default and omitted from most builds, so it is not urgent. The SQLITE_OMIT_* family only ever subtracts, and is not worth an option each.
Generated by Claude Code