Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
32443: opt: Fix panic when hoisting expr with correlated subquery r=andy-kimball a=andy-kimball

Fixes cockroachdb#32270.

The panic occurs when hoisting an expression that has both a correlated
and an uncorrelated subquery. The current code panics when calling
Reconstruct on the relational input to the uncorrelated subquery. The
fix is to test for relational inputs and skip over them. They are not
correlated, and so no hoisting needs to be done within their subtree.

Release note (sql change): Fix panic when expression contains both a
correlated and uncorrelated subquery.

Co-authored-by: Andrew Kimball <[email protected]>
  • Loading branch information
craig[bot] and andy-kimball committed Nov 29, 2018
2 parents d033b2a + f429b55 commit 22379f3
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 2 deletions.
16 changes: 14 additions & 2 deletions pkg/sql/opt/norm/decorrelate.go
Original file line number Diff line number Diff line change
Expand Up @@ -793,8 +793,20 @@ func (r *subqueryHoister) hoistAll(scalar opt.ScalarExpr) opt.ScalarExpr {
}

return r.f.Reconstruct(scalar, func(nd opt.Expr) opt.Expr {
// Recursively hoist subqueries in each child that contains them.
return r.hoistAll(nd.(opt.ScalarExpr))
// Recursively hoist subqueries in each scalar child that contains them.
// Skip relational children, since only subquery scalar operators have a
// relational child, and either:
//
// 1. The child is correlated, and therefore was handled above by hoisting
// and rewriting (and therefore won't ever get here),
//
// 2. Or the child is uncorrelated, and therefore should be skipped, since
// uncorrelated subqueries are not hoisted.
//
if scalarChild, ok := nd.(opt.ScalarExpr); ok {
return r.hoistAll(scalarChild)
}
return nd
}).(opt.ScalarExpr)
}

Expand Down
63 changes: 63 additions & 0 deletions pkg/sql/opt/norm/testdata/rules/decorrelate
Original file line number Diff line number Diff line change
Expand Up @@ -3235,6 +3235,69 @@ project
└── projections
└── NOT CASE WHEN bool_or AND (scalar IS NOT NULL) THEN true WHEN bool_or IS NULL THEN false END [type=bool, outer=(9,11)]

# Regress issue #32270: Panic when expression contains both correlated and
# uncorrelated subquery.
opt expect=HoistSelectSubquery
SELECT * FROM a WHERE EXISTS(SELECT * FROM xy) OR EXISTS(SELECT * FROM xy WHERE x=k)
----
project
├── columns: k:1(int!null) i:2(int) f:3(float) s:4(string) j:5(jsonb)
├── key: (1)
├── fd: (1)-->(2-5)
└── select
├── columns: k:1(int!null) i:2(int) f:3(float) s:4(string) j:5(jsonb) true_agg:11(bool)
├── key: (1)
├── fd: (1)-->(2-5,11)
├── group-by
│ ├── columns: k:1(int!null) i:2(int) f:3(float) s:4(string) j:5(jsonb) true_agg:11(bool)
│ ├── grouping columns: k:1(int!null)
│ ├── internal-ordering: +1
│ ├── key: (1)
│ ├── fd: (1)-->(2-5,11)
│ ├── left-join (merge)
│ │ ├── columns: k:1(int!null) i:2(int) f:3(float) s:4(string) j:5(jsonb) xy.x:8(int) true:10(bool)
│ │ ├── left ordering: +1
│ │ ├── right ordering: +8
│ │ ├── key: (1,8)
│ │ ├── fd: (1)-->(2-5), ()~~>(10), (1,8)-->(10)
│ │ ├── ordering: +1
│ │ ├── scan a
│ │ │ ├── columns: k:1(int!null) i:2(int) f:3(float) s:4(string) j:5(jsonb)
│ │ │ ├── key: (1)
│ │ │ ├── fd: (1)-->(2-5)
│ │ │ └── ordering: +1
│ │ ├── project
│ │ │ ├── columns: true:10(bool!null) xy.x:8(int!null)
│ │ │ ├── key: (8)
│ │ │ ├── fd: ()-->(10)
│ │ │ ├── ordering: +8 opt(10) [provided: +8]
│ │ │ ├── scan xy
│ │ │ │ ├── columns: xy.x:8(int!null)
│ │ │ │ ├── key: (8)
│ │ │ │ └── ordering: +8
│ │ │ └── projections
│ │ │ └── true [type=bool]
│ │ └── filters (true)
│ └── aggregations
│ ├── const-not-null-agg [type=bool, outer=(10)]
│ │ └── variable: true [type=bool]
│ ├── const-agg [type=int, outer=(2)]
│ │ └── variable: i [type=int]
│ ├── const-agg [type=float, outer=(3)]
│ │ └── variable: f [type=float]
│ ├── const-agg [type=string, outer=(4)]
│ │ └── variable: s [type=string]
│ └── const-agg [type=jsonb, outer=(5)]
│ └── variable: j [type=jsonb]
└── filters
└── or [type=bool, outer=(11)]
├── exists [type=bool]
│ └── scan xy
│ ├── columns: xy.x:6(int!null) xy.y:7(int)
│ ├── key: (6)
│ └── fd: (6)-->(7)
└── true_agg IS NOT NULL [type=bool]

# --------------------------------------------------
# HoistProjectSubquery
# --------------------------------------------------
Expand Down

0 comments on commit 22379f3

Please sign in to comment.