Skip to content

Fix unqualified columns of joined subqueries in expressions to close #832 - #2579

Open
joshuablac wants to merge 2 commits into
AlaSQL:developfrom
joshuablac:fix/join-subselect-832
Open

joshuablac wants to merge 2 commits into
AlaSQL:developfrom
joshuablac:fix/join-subselect-832

Conversation

@joshuablac

@joshuablac joshuablac commented Oct 12, 2026 •

Copy link
Copy Markdown

Closes #832

Problem

An unqualified column that comes from a subquery in FROM or JOIN resolves to the wrong source when it is used inside an expression:

CREATE TABLE one (a INT, b INT); INSERT INTO one VALUES (1,10),(2,20);
CREATE TABLE two (a INT, c INT); INSERT INTO two VALUES (1,100),(2,200);

SELECT t0.a AS a, c - b AS bc
FROM (SELECT a,b FROM one) t0 JOIN (SELECT a,c FROM two) t1 ON t0.a = t1.a
develop With this PR
Issue query [{a:1, bc:undefined}, {a:2, bc:undefined}] [{a:1, bc:90}, {a:2, bc:180}]
one t0 JOIN (SELECT a,c FROM two) t1 ... c - b bc: undefined bc: 90 / 180
... JOIN (SELECT a, c * 2 AS dbl FROM two) t1 ... WHERE dbl + b > 300 throws Column does not exist: dbl [{a:2, dbl:400}]

Plain column references like SELECT c, b already worked, because the SELECT list searches all sources at runtime. Expressions (c - b, WHERE, ORDER BY) rely on defcols instead.

Cause

compileDefCols registers the columns of tables in FROM / JOIN, but does nothing for subquery sources (fr instanceof yy.Select, jn.select). An unqualified column from a subquery therefore isn't in defcols. It is compiled as a lookup on the default (first) source: p['t0']['c'], which is undefined. When the first source is a table, the result is the Column does not exist error.

Fix

After the existing table handling, compileDefCols registers the named columns of each subquery's SELECT list (col.as, or the column name) for the subquery's alias. Two limits keep today's results intact:

  • Only when every source's columns are known. That means tables with column definitions and subqueries without *. A schemaless source (FROM ?, CSV(), a table created without columns, SELECT *) could also hold an unqualified name, so the previous resolution is kept. For example, in FROM ? t0 JOIN (SELECT id, x FROM ?) t1, x still resolves to t0. This means FROM ? JOIN (subquery) isn't fixed by this PR.
  • Only names not already defined. Columns from tables resolve exactly as before, including the existing ambiguity ('-') rules, and a name two sources share keeps today's resolution. No query that works today starts throwing an "ambiguous column" error.

Tests

  • Added test/test832.js:
    • the issue's query
    • a table joined with a subquery
    • an aliased subquery column used in WHERE and ORDER BY
    • a check that table columns keep their resolution
    • a check that a name shared with a schemaless source (FROM ?, SELECT * subquery) keeps resolving to the first source
  • The first three fail on develop and pass with this change.
  • I also checked that ambiguous unqualified columns resolve the same as on develop: a shared by two subqueries, by a subquery and a table, by FROM ? and a subquery, and by a column-less table and a subquery.
  • Full suite (bun test, same command as yarn test-only): 2254 pass, 213 skip. The only failures are the 2 CLI tests in test2149.js, which fail the same way on unmodified develop in my local setup (a space in my checkout path, and the version-injection step of build.sh not running).

This fix was written with AI assistance (Claude Code) and verified locally as described above.

🤖 Generated with Claude Code

…laSQL#832

compileDefCols only registered columns of tables, so a column coming from a
subquery in FROM or JOIN was unknown when compiling an expression. In
SELECT c - b FROM (SELECT a,b FROM one) t0 JOIN (SELECT a,c FROM two) t1 ...
"c" was looked up in the first source and the result was undefined.

The named columns of a subquery's SELECT list are now registered for its
alias. They only fill names that are not defined yet, so table columns and
the existing ambiguity rules are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 12, 2026 16:14

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

With a schemaless source (FROM ?, CSV(), a table without column
definitions, SELECT *) an unqualified name may belong to that source.
Registering the subquery's columns changed which source such a name
resolved to, e.g. x in FROM ? t0 JOIN (SELECT id, x FROM ?) t1 moved from
t0 to t1. Keep the previous resolution in that case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

Incorrect result when JOINing a subselect

2 participants