Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions pkg/sql/plan/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3275,3 +3275,11 @@ func TestReplaceCaptureDedupJoinDoesNotShuffle(t *testing.T) {

t.Fatal("expected REPLACE plan to contain a DEDUP JOIN with OldColCaptureList")
}

func TestCommaJoinWithExplicitJoin(t *testing.T) {
mock := NewMockOptimizer(false)
sqls := []string{
"select nation.n_name from nation, nation2 join region on nation2.r_regionkey = region.r_regionkey",
}
runTestShouldPass(mock, t, sqls, false, false)
}
44 changes: 42 additions & 2 deletions pkg/sql/plan/query_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -5042,7 +5042,7 @@ func (builder *QueryBuilder) buildTable(stmt tree.TableExpr, ctx *BindContext, p
if tbl.Right == nil {
return builder.buildTable(tbl.Left, ctx, preNodeId, leftCtx)
}
return builder.buildJoinTable(tbl, ctx)
return builder.buildJoinTable(tbl, ctx, leftCtx)

case *tree.ApplyTableExpr:
_, ok := tbl.Right.(*tree.TableFunction)
Expand Down Expand Up @@ -5327,7 +5327,7 @@ func (builder *QueryBuilder) addBinding(nodeID int32, alias tree.AliasClause, ct
return nil
}

func (builder *QueryBuilder) buildJoinTable(tbl *tree.JoinTableExpr, ctx *BindContext) (int32, error) {
func (builder *QueryBuilder) buildJoinTable(tbl *tree.JoinTableExpr, ctx *BindContext, extLeftCtx *BindContext) (int32, error) {
joinType := plan.Node_INNER

switch tbl.JoinType {
Expand Down Expand Up @@ -5375,6 +5375,43 @@ func (builder *QueryBuilder) buildJoinTable(tbl *tree.JoinTableExpr, ctx *BindCo
return 0, err
}

// Comma (CROSS) joins produce nested trees where the outer left context
// is not visible in the inner ON condition
// (e.g. FROM a, b JOIN c ON a.x = c.y). Temporarily add extLeftCtx
// bindings to ctx for the ON condition binding, then remove them so
// the outer mergeContexts doesn't see a duplicate.
var extBindingsRestore func()
if extLeftCtx != nil {
var addedTables []string
for _, binding := range extLeftCtx.bindings {
if _, ok := ctx.bindingByTable[binding.table]; !ok {
ctx.bindings = append(ctx.bindings, binding)
ctx.bindingByTag[binding.tag] = binding
ctx.bindingByTable[binding.table] = binding
addedTables = append(addedTables, binding.table)
}
}
var addedCols []string
for col, binding := range extLeftCtx.bindingByCol {
if _, ok := ctx.bindingByCol[col]; !ok {
ctx.bindingByCol[col] = binding
addedCols = append(addedCols, col)
}
}
extBindingsRestore = func() {
for _, table := range addedTables {
delete(ctx.bindingByTable, table)
}
for _, col := range addedCols {
delete(ctx.bindingByCol, col)
}
for _, binding := range extLeftCtx.bindings {
delete(ctx.bindingByTag, binding.tag)
}
ctx.bindings = ctx.bindings[:len(ctx.bindings)-len(addedTables)]
}
}

node := &plan.Node{
NodeType: plan.Node_JOIN,
Children: []int32{leftChildID, rightChildID},
Expand Down Expand Up @@ -5444,6 +5481,9 @@ func (builder *QueryBuilder) buildJoinTable(tbl *tree.JoinTableExpr, ctx *BindCo
}
}

if extBindingsRestore != nil {
extBindingsRestore()
}
return nodeID, nil
}

Expand Down
Loading
Loading