fix(parse): check INSERT columns and UPDATE SET targets in strict mode - #349
Merged
Conversation
StrictRow<DB, 'insert into users (naem) values ($1)'> // was Record<string, never>
StrictRow<DB, 'update users set naem = $1 where id = 1'> // same
Both are guaranteed runtime errors on every engine. Nothing scanned either
list against the schema: the DML branches used them only to position
placeholders for params inference. The documented list of unchecked clauses
covers GROUP BY, HAVING and ORDER BY - column names in write statements were
never on it, and no test pinned the behaviour either way.
The statement record carries the write column text (the INSERT list, or the
SET assignment targets) and the row check resolves each name the same way
RETURNING columns are resolved, so the message reads identically. Shapes it
cannot read are left alone rather than guessed at: a row assignment
(`set (a, b) = (1, 2)`), an INSERT with no column list, and anything whose
target is not a plain name.
MAX_INSTANTIATIONS moves 200,000 -> 210,000. The fixture goes 192,486 ->
201,322: the check is gated on a non-empty column text, so a SELECT pays
only for carrying the empty string, and the cost is the two clause scans a
write statement now runs. Ordering that gate before the structural
`Row extends QueryTypeError` test was worth 2,500 on its own.
Fixes #282
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
tiagolauer
force-pushed
the
fix/282-write-column-check
branch
from
August 2, 2026 13:04
54704b1 to
4592c97
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #282.
The bug
Both are guaranteed runtime errors on every engine. The documented list of unchecked clauses covers GROUP BY, HAVING and ORDER BY; column names in write statements are not on it, and no test pinned this either way.
The fix
Nothing scanned the SET assignment targets or the INSERT column list against the schema — the DML branches used those lists only to position placeholders for params inference.
The parsed statement now carries the write column text (INSERT's list, or UPDATE's SET targets), and the row check resolves each name through the same
ResolveColumnTypethat RETURNING columns go through, so the message is identical to the one every other path produces.Shapes it cannot read are left alone rather than guessed at:
set (a, b) = (1, 2))Budget
MAX_INSTANTIATIONSmoves 200,000 → 210,000, raised in this commit as the script asks.A SELECT carries an empty string here and pays only for that; the ~4.5% is the two clause scans a write now runs (
SplitAtTopLevelKeywordfor VALUES/SELECT, and for SET) plus the extra field on the parsed statement.Verification
tests/write-column-check.test-d.ts, twelve cases. Five red on master:Controls: valid writes (with and without RETURNING), an INSERT with no column list, a subquery on the value side of a SET, a qualified SET target, and loose mode.
tsc --noEmitclean, 192 runtime tests pass.