Skip to content

fix(parse): validate the SELECT half of an INSERT ... SELECT - #350

Merged
tiagolauer merged 1 commit into
masterfrom
fix/272-insert-select-strict
Aug 2, 2026
Merged

fix(parse): validate the SELECT half of an INSERT ... SELECT#350
tiagolauer merged 1 commit into
masterfrom
fix/272-insert-select-strict

Conversation

@tiagolauer

Copy link
Copy Markdown
Owner

Fixes #272.

The bug

StrictRow<DB, 'insert into users (name) select naem from ghosts where nope = 1'>
// Record<string, never> - no error

Three mistakes ride through in one line: ghosts is not a table, naem is not a column, and nope is not one either. The README says strict mode checks the SELECT list and the WHERE clause; this statement has both.

The fix

The INSERT branch extracted the target and the RETURNING/OUTPUT clause and stopped. The parsed statement now carries the SELECT half as its own query text, and strict mode resolves it through the same entry point the outer query uses — so the nested statement's CTEs, joins, column resolution and clause checks all apply for free, and an error surfaces as the row, the way every other strict failure does.

When the SELECT half is clean, the INSERT's own RETURNING columns still decide the row shape.

Verification

tests/insert-select-strict.test-d.ts, nine cases. Three red on master:

tests/insert-select-strict.test-d.ts(19,3): error TS2344: Type 'false' does not satisfy the constraint 'true'.
tests/insert-select-strict.test-d.ts(26,3): ... (33,3)
  • an unknown table, an unknown column in the SELECT list, and an unknown column in the SELECT's WHERE

Controls: valid INSERT ... SELECT with and without a WHERE, one with RETURNING (still { id: number }), INSERT ... VALUES, a plain SELECT, and loose mode.

tsc --noEmit clean, 192 runtime tests pass, budget 194,103 (+1,617).

    StrictRow<DB, 'insert into users (name) select naem from ghosts where nope = 1'>
    // was Record<string, never> - three mistakes accepted in one line

The INSERT branch extracted the target and the RETURNING/OUTPUT clause and
stopped there, so the trailing SELECT was never parsed as a statement: its
sources, its columns and its WHERE did not exist as far as validation was
concerned. The README says strict mode checks the SELECT list and the WHERE
clause, and this statement has both.

The parsed statement now carries the SELECT half, and strict mode resolves
it through the same entry point the outer query uses - so its CTEs, joins
and clause checks all apply, and an error surfaces as the row the way every
other strict failure does. The INSERT's own RETURNING columns still decide
the row shape when the SELECT half is clean.

Fixes #272

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tiagolauer
tiagolauer force-pushed the fix/272-insert-select-strict branch from 4d94882 to 9acd4eb Compare August 2, 2026 13:04
@tiagolauer
tiagolauer merged commit e5b1519 into master Aug 2, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

INSERT ... SELECT: the SELECT half is invisible to strict mode

1 participant