Skip to content

fix(parse): check JOIN ON inside UPDATE FROM and DELETE USING - #348

Merged
tiagolauer merged 1 commit into
masterfrom
fix/281-dml-join-on
Aug 2, 2026
Merged

fix(parse): check JOIN ON inside UPDATE FROM and DELETE USING#348
tiagolauer merged 1 commit into
masterfrom
fix/281-dml-join-on

Conversation

@tiagolauer

Copy link
Copy Markdown
Owner

Fixes #281.

The bug

StrictRow<DB, 'update users set name = $1 from orders o join refunds r on r.nope = o.id where users.id = o.user_id'>
// Record<string, never> - r.nope accepted silently

Same with delete from users using orders o join refunds r on r.nope = o.id .... The joined sources themselves are registered — returning r.id from the valid variant works — so it is only the ON expressions that go unchecked. The README says strict mode checks JOIN ... ON conditions and makes no carve-out for write statements.

The fix

The UPDATE and DELETE branches hardcoded fromText: '', so ApplyWhereCheck's ExtractJoinOnText never saw their join text.

Both now pass the real FROM/USING clause text, taken with the same TakeFromClause a SELECT uses, and kept as raw text for the same reason the SELECT branch documents: the JOIN ON scan only runs in strict mode.

Verification

tests/dml-join-on-strict.test-d.ts, eight cases. Three red on master:

tests/dml-join-on-strict.test-d.ts(21,3): error TS2344: Type 'false' does not satisfy the constraint 'true'.
tests/dml-join-on-strict.test-d.ts(31,3): ... (41,3)
  • an unknown column in the ON of an UPDATE ... FROM and of a DELETE ... USING
  • an unknown alias in the ON of an UPDATE ... FROM

Controls: the valid versions of both statements still pass, an UPDATE without a FROM is unchanged, UPDATE ... FROM ... RETURNING still types its row, and loose mode still reports nothing.

tsc --noEmit clean, 192 runtime tests pass, budget 192,596 (+110).

    StrictRow<DB, 'update users set name = $1 from orders o join refunds r on r.nope = o.id where users.id = o.user_id'>
    // was Record<string, never> - r.nope accepted silently

The joined sources were registered - returning `r.id` from the valid variant
worked - so only the ON expressions went unchecked. Both write branches
hardcoded `fromText: ''`, so ApplyWhereCheck's ExtractJoinOnText never saw
their join text. The README says strict mode checks JOIN ... ON conditions
and makes no carve-out for write statements.

Both now pass the real FROM/USING clause text, taken with the same
TakeFromClause a SELECT uses, and kept as raw text for the same reason: the
scan only runs in strict mode.

Fixes #281

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tiagolauer
tiagolauer force-pushed the fix/281-dml-join-on branch from 7e66892 to 89fd55a Compare August 2, 2026 13:04
@tiagolauer
tiagolauer merged commit be7bdeb 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.

JOIN ON inside UPDATE ... FROM and DELETE ... USING is not validated in strict mode

1 participant