Skip to content

Commit

Permalink
Merge #71396
Browse files Browse the repository at this point in the history
71396: opt: fix implicit lateral for SRFs when using JOIN syntax r=RaduBerinde a=RaduBerinde

When SRFs are used as a table, they imply that the join is lateral.
This works for the multiple table syntax, but not for the JOIN syntax.
This commit addresses this omission.

Fixes #70342.

Release note (bug fix): Fixes an incorrect "no data source matches
prefix" error for queries that use a set-returning function on the
right-hand side of a `JOIN` (unless `LATERAL` is explicitly
specified).

Co-authored-by: Radu Berinde <[email protected]>
  • Loading branch information
craig[bot] and RaduBerinde committed Oct 12, 2021
2 parents 6159a73 + 9e8d9be commit 48b3793
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 9 deletions.
12 changes: 5 additions & 7 deletions pkg/sql/opt/optbuilder/join.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,12 @@ func (b *Builder) buildJoin(
) (outScope *scope) {
leftScope := b.buildDataSource(join.Left, nil /* indexFlags */, locking, inScope)

isLateral := false
inScopeRight := inScope
// If this is a lateral join, use leftScope as inScope for the right side.
// The right side scope of a LATERAL join includes the columns produced by
// the left side.
if t, ok := join.Right.(*tree.AliasedTableExpr); ok && t.Lateral {
telemetry.Inc(sqltelemetry.LateralJoinUseCounter)
isLateral = true
isLateral := b.exprIsLateral(join.Right)
if isLateral {
// If this is a lateral join, use leftScope as inScope for the right side.
// The right side scope of a LATERAL join includes the columns produced by
// the left side.
inScopeRight = leftScope
inScopeRight.context = exprKindLateralJoin
}
Expand Down
1 change: 1 addition & 0 deletions pkg/sql/opt/optbuilder/select.go
Original file line number Diff line number Diff line change
Expand Up @@ -1205,6 +1205,7 @@ func (b *Builder) exprIsLateral(t tree.TableExpr) bool {
}
// Expressions which explicitly use the LATERAL keyword are lateral.
if ate.Lateral {
telemetry.Inc(sqltelemetry.LateralJoinUseCounter)
return true
}
// SRFs are always lateral.
Expand Down
75 changes: 73 additions & 2 deletions pkg/sql/opt/optbuilder/testdata/srfs
Original file line number Diff line number Diff line change
Expand Up @@ -672,9 +672,9 @@ SELECT a.*, b.*, c.* FROM upper('abc') a
JOIN ROWS FROM (upper('def'), generate_series(1, 3)) b ON true
JOIN generate_series(1, 4) c ON true
----
inner-join (cross)
inner-join-apply
├── columns: a:1 upper:2 generate_series:3 c:4
├── inner-join (cross)
├── inner-join-apply
│ ├── columns: upper:1 upper:2 generate_series:3
│ ├── project-set
│ │ ├── columns: upper:1
Expand Down Expand Up @@ -894,3 +894,74 @@ project-set
│ ├── columns: tab31755.a:1 rowid:2!null crdb_internal_mvcc_timestamp:3 tableoid:4
│ └── limit hint: 1.00
└── 1

# Regression test for #70342.
exec-ddl
CREATE TABLE t70342 (i INT PRIMARY KEY);
----

# Verify that an SRF is implicitly lateral.
build
WITH data AS (SELECT row_to_json(t70342) AS row FROM t70342)
SELECT count(*)
FROM data, json_each_text(data.row);
----
with &1 (data)
├── columns: count:8!null
├── project
│ ├── columns: row:4
│ ├── scan t70342
│ │ └── columns: i:1!null crdb_internal_mvcc_timestamp:2 tableoid:3
│ └── projections
│ └── row_to_json(((i:1,) AS i)) [as=row:4]
└── scalar-group-by
├── columns: count_rows:8!null
├── project
│ └── inner-join-apply
│ ├── columns: row:5 key:6 value:7
│ ├── with-scan &1 (data)
│ │ ├── columns: row:5
│ │ └── mapping:
│ │ └── row:4 => row:5
│ ├── project-set
│ │ ├── columns: key:6 value:7
│ │ ├── values
│ │ │ └── ()
│ │ └── zip
│ │ └── json_each_text(row:5)
│ └── filters (true)
└── aggregations
└── count-rows [as=count_rows:8]

# Verify that an SRF is implicitly lateral when using the JOIN syntax.
build
WITH data AS (SELECT row_to_json(t70342) AS row FROM t70342)
SELECT count(*)
FROM data CROSS JOIN json_each_text(data.row);
----
with &1 (data)
├── columns: count:8!null
├── project
│ ├── columns: row:4
│ ├── scan t70342
│ │ └── columns: i:1!null crdb_internal_mvcc_timestamp:2 tableoid:3
│ └── projections
│ └── row_to_json(((i:1,) AS i)) [as=row:4]
└── scalar-group-by
├── columns: count_rows:8!null
├── project
│ └── inner-join-apply
│ ├── columns: row:5 key:6 value:7
│ ├── with-scan &1 (data)
│ │ ├── columns: row:5
│ │ └── mapping:
│ │ └── row:4 => row:5
│ ├── project-set
│ │ ├── columns: key:6 value:7
│ │ ├── values
│ │ │ └── ()
│ │ └── zip
│ │ └── json_each_text(row:5)
│ └── filters (true)
└── aggregations
└── count-rows [as=count_rows:8]

0 comments on commit 48b3793

Please sign in to comment.