fix(parse): resolve correlated subqueries in strict mode - #351
Merged
Conversation
StrictQuery<DB, 'select (select count(*) from posts where posts.user_id = users.id) as post_count from users'>
// was QueryTypeError<'unknown alias: users'>[]
That is the README's own scalar-subquery example. ScalarSubqueryType and
BuildDerivedSourceMap ran the inner query through InferRowWith with only the
inner query's sources, so any correlated reference had nothing to resolve
against. The restriction is not in the documented limitations, and
CONTRIBUTING.md claimed the README documented it, which it never did.
The outer sources are a fallback, not an addition to the scope. SQL resolves
an inner name first and looks outward only when it is not there, so merging
the two lists would have invented an `ambiguous column` for every name the
two levels share. When the outer lookup fails too, the inner message is what
gets reported - the reference was meant for the inner query.
A derived table that fails to type now surfaces its own error as well. It
used to replace its row with the error object, and the outer query then
reported the alias's columns as unknown, pointing at the wrong line; the
existing lock in tests/where-strict.test-d.ts pinned that misdirection and
is updated to the real message.
Fixes #273
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
tiagolauer
force-pushed
the
fix/273-correlated-subquery
branch
from
August 2, 2026 13:04
61f55b9 to
97e6afa
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 #273.
The bug
That is the README's own scalar-subquery example. The lateral form was worse, because the inner error object replaced the derived row and the surfaced message pointed at the wrong thing:
Not in the documented limitations — and
CONTRIBUTING.md:68claimed the README documented it, which it never did.The fix
ScalarSubqueryTypeandBuildDerivedSourceMapran the inner query throughInferRowWithwith only the inner query's own sources. Both now pass the enclosing FROM list down, and the WHERE scan consults it.As a fallback, not as an addition to the scope. SQL resolves an inner name first and looks outward only when it is not there; merging the two lists would have invented an
ambiguous columnfor every name the two levels share (select (select max(id) from posts) from usershas anidon both sides). When the outer lookup fails too, the inner message is reported — the reference was meant for the inner query.The second half of the issue is fixed too: a derived table that fails to type now surfaces its own error, instead of the outer query reporting the alias's columns as unknown.
tests/where-strict.test-d.tshad that misdirection pinned (unknown column: idfor a typo namednaem); it now pins the real message.Verification
tests/correlated-subquery.test-d.ts, ten cases. Five red on master, plus the updated lock:noperather than the aliasselect ... where posts.user_id = u.idon its own is stillunknown alias: uControls: uncorrelated scalar subquery and uncorrelated lateral join unchanged, loose mode unchanged.
tsc --noEmitclean, 192 runtime tests pass, budget 199,660 (+7,174, 100% of the ceiling — it stays under).