Skip to content

Commit

Permalink
bugfix: support subqueries inside subqueries when merging (#17764)
Browse files Browse the repository at this point in the history
Signed-off-by: Andres Taylor <andres@planetscale.com>
  • Loading branch information
systay authored Feb 13, 2025
1 parent 01b3e02 commit d4e0f91
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 21 deletions.
50 changes: 29 additions & 21 deletions go/vt/vtgate/planbuilder/operators/subquery_planning.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,30 +148,38 @@ func mergeSubqueryExpr(ctx *plancontext.PlanningContext, pe *ProjExpr) {

func rewriteMergedSubqueryExpr(ctx *plancontext.PlanningContext, se SubQueryExpression, expr sqlparser.Expr) (sqlparser.Expr, bool) {
rewritten := false
for _, sq := range se {
for _, sq2 := range ctx.MergedSubqueries {
if sq.originalSubquery == sq2 {
expr = sqlparser.Rewrite(expr, nil, func(cursor *sqlparser.Cursor) bool {
switch expr := cursor.Node().(type) {
case *sqlparser.ColName:
if expr.Name.String() != sq.ArgName { // TODO systay 2023.09.15 - This is not safe enough. We should figure out a better way.

merged := true
for merged {
// we need to keep rewriting the expression until we can't find any more subqueries to merge
// this is because we might have subqueries inside subqueries, and we need to merge them all
merged = false
for _, sq := range se {
for _, sq2 := range ctx.MergedSubqueries {
if sq.originalSubquery == sq2 {
expr = sqlparser.Rewrite(expr, nil, func(cursor *sqlparser.Cursor) bool {
switch expr := cursor.Node().(type) {
case *sqlparser.ColName:
if expr.Name.String() != sq.ArgName { // TODO systay 2023.09.15 - This is not safe enough. We should figure out a better way.
return true
}
case *sqlparser.Argument:
if expr.Name != sq.ArgName {
return true
}
default:
return true
}
case *sqlparser.Argument:
if expr.Name != sq.ArgName {
return true
rewritten = true
if sq.FilterType == opcode.PulloutExists {
cursor.Replace(&sqlparser.ExistsExpr{Subquery: sq.originalSubquery})
} else {
cursor.Replace(sq.originalSubquery)
}
default:
return true
}
rewritten = true
if sq.FilterType == opcode.PulloutExists {
cursor.Replace(&sqlparser.ExistsExpr{Subquery: sq.originalSubquery})
} else {
cursor.Replace(sq.originalSubquery)
}
return false
}).(sqlparser.Expr)
merged = true
return false
}).(sqlparser.Expr)
}
}
}
}
Expand Down
52 changes: 52 additions & 0 deletions go/vt/vtgate/planbuilder/testdata/select_cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -1314,6 +1314,58 @@
},
"skip_e2e": true
},
{
"comment": "Subquery inside subquery #1",
"query": "select (select (select col from `user` where id = 1) from `user` where id = 1) from `user` where id = 1",
"plan": {
"QueryType": "SELECT",
"Original": "select (select (select col from `user` where id = 1) from `user` where id = 1) from `user` where id = 1",
"Instructions": {
"OperatorType": "Route",
"Variant": "EqualUnique",
"Keyspace": {
"Name": "user",
"Sharded": true
},
"FieldQuery": "select (select (select col from `user` where 1 != 1) from `user` where 1 != 1) from `user` where 1 != 1",
"Query": "select (select (select col from `user` where id = 1) from `user` where id = 1) from `user` where id = 1",
"Table": "`user`",
"Values": [
"1"
],
"Vindex": "user_index"
},
"TablesUsed": [
"user.user"
]
}
},
{
"comment": "Subquery inside subquery #2",
"query": "select 1 from `user` where id = 1 and 1 = (select (select intcol from `user` where id = 1) from `user` where id = 1)",
"plan": {
"QueryType": "SELECT",
"Original": "select 1 from `user` where id = 1 and 1 = (select (select intcol from `user` where id = 1) from `user` where id = 1)",
"Instructions": {
"OperatorType": "Route",
"Variant": "EqualUnique",
"Keyspace": {
"Name": "user",
"Sharded": true
},
"FieldQuery": "select 1 from `user` where 1 != 1",
"Query": "select 1 from `user` where id = 1 and 1 = (select (select intcol from `user` where id = 1) from `user` where id = 1)",
"Table": "`user`",
"Values": [
"1"
],
"Vindex": "user_index"
},
"TablesUsed": [
"user.user"
]
}
},
{
"comment": "Multiple parenthesized expressions",
"query": "select * from user where (id = 4 and name ='abc') limit 5",
Expand Down

0 comments on commit d4e0f91

Please sign in to comment.