fix: resolve comma-joined tables in nested explicit JOIN ON conditions#25353
fix: resolve comma-joined tables in nested explicit JOIN ON conditions#25353aunjgr wants to merge 7 commits into
Conversation
When comma (CROSS) join syntax is mixed with explicit JOIN (e.g. FROM a, b JOIN c ON a.x = c.y), the parser produces CROSS(a, INNER(b, c, ON a.x = c.y)). The outer left context containing 'a' was lost when buildTable dispatched to buildJoinTable for the nested INNER join. Fix: pass extLeftCtx through to buildJoinTable, temporarily add its bindings to ctx for ON condition resolution, then remove them so the outer mergeContexts doesn't see a duplicate. Co-Authored-By: Claude <noreply@anthropic.com>
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
The extBindingsRestore was only called inside OnJoinCond, but comma joins have no ON condition — extLeftCtx bindings leaked into ctx and collided at outer mergeContexts. Move restore after the switch so all join types clean up. Co-Authored-By: Claude <noreply@anthropic.com>
61ded83 to
33663a5
Compare
XuPeng-SH
left a comment
There was a problem hiding this comment.
Requesting changes. I found a correctness blocker in the current direction.
-
test/distributed/cases/join/join.sql:178-179/join.result:227-229shows the new predicate is not actually applied at the intended scope. The data hasrrows(1,100),(2,200)andsrows(1,'A'),(2,'B');where r.val = ld.vkeeps onlyr.id = 2, so ifON r.id = s.idis effective the only valid row is2/B. The committed result is2/Aand2/B, which means the binder now acceptsr.idbut the join predicate is placed on an inner join whose children do not includer, so it cannot enforce the condition correctly. -
This also conflicts with MySQL join-scope semantics. MySQL documents that
JOINhas higher precedence than comma, sot1, t2 JOIN t3 ON t1...is interpreted ast1, (t2 JOIN t3), and theONclause may refer only to the join operands (t2andt3), nott1: https://dev.mysql.com/doc/en/join.html. The current fix deliberately makes the outer comma-left context visible in the inner explicit JOIN ON clause, so it changes the language semantics instead of preserving MySQL compatibility.
Suggested direction:
- If MatrixOne wants MySQL-compatible behavior, keep the unparenthesized query as an error and update the issue/test to use either explicit
CROSS JOINor parentheses, e.g.(t_comma_join r, ... ld) JOIN t_comma_dim s ON .... - If MatrixOne intentionally wants this extension, do not bind external refs into the inner join
OnList. Rewrite/lift the predicate to a node whose child subtree actually contains all referenced tables, and add result-level regression coverage proving the expected output is only2/Bfor the current BVT data. - Add unhappy-path coverage for ambiguous/invalid cases: external left refs in
LEFT/RIGHT/FULL JOIN ON, duplicate table aliases, ambiguous unqualified columns, and an explicit MySQL-compatible negative test fort1, t2 JOIN t3 ON t1...if compatibility is the goal.
Local verification I ran:
go test -count=1 -timeout 180s ./pkg/sql/plan -run 'TestCommaJoinWithExplicitJoin|TestSubqueryInJoinOn|TestWrongCases'go test -count=1 -timeout 300s ./pkg/sql/plan
Both pass, but they do not cover the actual result correctness issue above.
What type of PR is this?
Which issue(s) this PR fixes:
issue #24411
What this PR does / why we need it:
FROM a, b JOIN c ON a.x = c.yfailed with "missing FROM-clause entry for table a". The comma-joined table was not visible in the explicit JOIN ON condition.Root cause
The parser produces
CROSS(a, INNER(b, c, ON a.x = c.y))for comma + explicit JOIN. The outer CROSS join left context (containinga) was dropped whenbuildTabledispatched the inner INNER join tobuildJoinTable—leftCtxwas never passed through.Fix
buildJoinTablenow acceptsextLeftCtx *BindContextbuildTablepassesleftCtxthroughbuildJoinTable, temporarily addextLeftCtxbindings to the ON condition binding context, then remove them so the outermergeContextsdoes not see a duplicate205/205 join BVT pass. Unit test covers the comma+explicit JOIN pattern.
pkg/sql/plan/query_builder.gopkg/sql/plan/build_test.gotest/.../join/join.sqltest/.../join/join.result🤖 Generated with Claude Code