diff --git a/pkg/sql/opt/exec/execbuilder/relational.go b/pkg/sql/opt/exec/execbuilder/relational.go index ed1b879a84af..31a94b4971c7 100644 --- a/pkg/sql/opt/exec/execbuilder/relational.go +++ b/pkg/sql/opt/exec/execbuilder/relational.go @@ -67,7 +67,13 @@ type execPlan struct { // if the node outputs the same optimizer ColumnID multiple times. // TODO(justin): we should keep track of this instead of computing it each time. func (ep *execPlan) numOutputCols() int { - max, ok := ep.outputCols.MaxValue() + return numOutputColsInMap(ep.outputCols) +} + +// numOutputColsInMap returns the number of slots required to fill in all of +// the columns referred to by this ColMap. +func numOutputColsInMap(m opt.ColMap) int { + max, ok := m.MaxValue() if !ok { return 0 } @@ -512,6 +518,7 @@ func (b *Builder) buildProject(prj *memo.ProjectExpr) (execPlan, error) { if err != nil { return execPlan{}, err } + projections := prj.Projections if len(projections) == 0 { // We have only pass-through columns. @@ -633,7 +640,7 @@ func (b *Builder) buildApplyJoin(join memo.RelExpr) (execPlan, error) { allCols := joinOutputMap(left.outputCols, fakeRight.outputCols) ctx := buildScalarCtx{ - ivh: tree.MakeIndexedVarHelper(nil /* container */, allCols.Len()), + ivh: tree.MakeIndexedVarHelper(nil /* container */, numOutputColsInMap(allCols)), ivarMap: allCols, } @@ -771,7 +778,7 @@ func (b *Builder) initJoinBuild( allCols := joinOutputMap(leftPlan.outputCols, rightPlan.outputCols) ctx := buildScalarCtx{ - ivh: tree.MakeIndexedVarHelper(nil /* container */, allCols.Len()), + ivh: tree.MakeIndexedVarHelper(nil /* container */, numOutputColsInMap(allCols)), ivarMap: allCols, } @@ -792,7 +799,8 @@ func (b *Builder) initJoinBuild( // joinOutputMap determines the outputCols map for a (non-semi/anti) join, given // the outputCols maps for its inputs. func joinOutputMap(left, right opt.ColMap) opt.ColMap { - numLeftCols := left.Len() + numLeftCols := numOutputColsInMap(left) + res := left.Copy() right.ForEach(func(colIdx, rightIdx int) { res.Set(colIdx, rightIdx+numLeftCols) diff --git a/pkg/sql/opt/exec/execbuilder/testdata/with b/pkg/sql/opt/exec/execbuilder/testdata/with index f601cd13fef5..b7041ed8ed56 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/with +++ b/pkg/sql/opt/exec/execbuilder/testdata/with @@ -68,3 +68,42 @@ root · · (a · size 2 columns, 1 row · · · row 0, expr 0 1 · · · row 0, expr 1 unique_rowid() · · + +# Regression test for #39010. + +statement ok +CREATE TABLE table39010 (col NAME) + +query TTTTT +EXPLAIN (VERBOSE) + WITH + w AS (SELECT NULL, NULL FROM table39010) + SELECT + col + FROM + w, table39010 +---- +root · · (col) · + ├── render · · (col) · + │ │ render 0 col · · + │ └── hash-join · · ("?column?", "?column?", col) · + │ │ type cross · · + │ ├── render · · ("?column?", "?column?") · + │ │ │ render 0 "?column?" · · + │ │ │ render 1 "?column?" · · + │ │ └── scan buffer node · · ("?column?") · + │ │ label buffer 1 (w) · · + │ └── scan · · (col) · + │ table table39010@primary · · + │ spans ALL · · + └── subquery · · (col) · + │ id @S1 · · + │ original sql SELECT NULL, NULL FROM table39010 · · + │ exec mode all rows · · + └── buffer node · · ("?column?") · + │ label buffer 1 (w) · · + └── render · · ("?column?") · + │ render 0 NULL · · + └── scan · · () · +· table table39010@primary · · +· spans ALL · ·