Skip to content

Commit

Permalink
use sql path in subquery planning
Browse files Browse the repository at this point in the history
Signed-off-by: Harshit Gangal <harshit@planetscale.com>
  • Loading branch information
harshit-gangal committed Feb 11, 2025
1 parent bf96f0e commit 05b8188
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 8 deletions.
2 changes: 1 addition & 1 deletion go/vt/vtgate/planbuilder/operators/join.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func createLeftOuterJoin(ctx *plancontext.PlanningContext, join *sqlparser.JoinT

// for outer joins we have to be careful with the predicates we use
var op Operator
subq, _ := getSubQuery(join.Condition.On)
subq, _, _ := getSubQuery(join.Condition.On)
if subq != nil {
panic(vterrors.VT12001("subquery in outer join predicate"))
}
Expand Down
55 changes: 48 additions & 7 deletions go/vt/vtgate/planbuilder/operators/subquery_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,22 +53,23 @@ func (sqb *SubQueryBuilder) handleSubquery(
expr sqlparser.Expr,
outerID semantics.TableSet,
) *SubQuery {
subq, parentExpr := getSubQuery(expr)
subq, parentExpr, path := getSubQuery(expr)
if subq == nil {
return nil
}
argName := ctx.GetReservedArgumentFor(subq)
sqInner := createSubqueryOp(ctx, parentExpr, expr, subq, outerID, argName)
sqInner := createSubqueryOp(ctx, parentExpr, expr, subq, outerID, argName, path)
sqb.Inner = append(sqb.Inner, sqInner)

return sqInner
}

func getSubQuery(expr sqlparser.Expr) (subqueryExprExists *sqlparser.Subquery, parentExpr sqlparser.Expr) {
func getSubQuery(expr sqlparser.Expr) (subqueryExprExists *sqlparser.Subquery, parentExpr sqlparser.Expr, path sqlparser.ASTPath) {
flipped := false
_ = sqlparser.Rewrite(expr, func(cursor *sqlparser.Cursor) bool {
_ = sqlparser.RewriteWithPath(expr, func(cursor *sqlparser.Cursor) bool {
if subq, ok := cursor.Node().(*sqlparser.Subquery); ok {
subqueryExprExists = subq
path = cursor.Path()
parentExpr = subq
if expr, ok := cursor.Parent().(sqlparser.Expr); ok {
parentExpr = expr
Expand All @@ -95,6 +96,7 @@ func createSubqueryOp(
subq *sqlparser.Subquery,
outerID semantics.TableSet,
name string,
path sqlparser.ASTPath,
) *SubQuery {
switch parent := parent.(type) {
case *sqlparser.NotExpr:
Expand All @@ -105,9 +107,9 @@ func createSubqueryOp(
panic("should have been rewritten")
}
case *sqlparser.ExistsExpr:
return createSubquery(ctx, original, subq, outerID, parent, name, opcode.PulloutExists, false)
return createSubqueryFromPath(ctx, original, subq, path, outerID, parent, name, opcode.PulloutExists, false)
case *sqlparser.ComparisonExpr:
return createComparisonSubQuery(ctx, parent, original, subq, outerID, name)
return createComparisonSubQuery(ctx, parent, original, subq, path, outerID, name)
}
return createSubquery(ctx, original, subq, outerID, parent, name, opcode.PulloutValue, false)
}
Expand Down Expand Up @@ -188,6 +190,44 @@ func createSubquery(
}
}

func createSubqueryFromPath(
ctx *plancontext.PlanningContext,
original sqlparser.Expr,
subq *sqlparser.Subquery,
path sqlparser.ASTPath,
outerID semantics.TableSet,
parent sqlparser.Expr,
argName string,
filterType opcode.PulloutOpcode,
isArg bool,
) *SubQuery {
topLevel := ctx.SemTable.EqualsExpr(original, parent)
original = cloneASTAndSemState(ctx, original)
originalSq := sqlparser.GetNodeFromPath(original, path).(*sqlparser.Subquery)
subqID := findTablesContained(ctx, originalSq.Select)
totalID := subqID.Merge(outerID)
sqc := &SubQueryBuilder{totalID: totalID, subqID: subqID, outerID: outerID}

predicates, joinCols := sqc.inspectStatement(ctx, subq.Select)
correlated := !ctx.SemTable.RecursiveDeps(subq).IsEmpty()

opInner := translateQueryToOp(ctx, subq.Select)

opInner = sqc.getRootOperator(opInner, nil)
return &SubQuery{
FilterType: filterType,
Subquery: opInner,
Predicates: predicates,
Original: original,
ArgName: argName,
originalSubquery: originalSq,
IsArgument: isArg,
TopLevel: topLevel,
JoinColumns: joinCols,
correlated: correlated,
}
}

func (sqb *SubQueryBuilder) inspectWhere(
ctx *plancontext.PlanningContext,
in *sqlparser.Where,
Expand Down Expand Up @@ -260,6 +300,7 @@ func createComparisonSubQuery(
parent *sqlparser.ComparisonExpr,
original sqlparser.Expr,
subFromOutside *sqlparser.Subquery,
path sqlparser.ASTPath,
outerID semantics.TableSet,
name string,
) *SubQuery {
Expand All @@ -276,7 +317,7 @@ func createComparisonSubQuery(
filterType = opcode.PulloutNotIn
}

subquery := createSubquery(ctx, original, subq, outerID, parent, name, filterType, false)
subquery := createSubqueryFromPath(ctx, original, subq, path, outerID, parent, name, filterType, false)

// if we are comparing with a column from the inner subquery,
// we add this extra predicate to check if the two sides are mergable or not
Expand Down

0 comments on commit 05b8188

Please sign in to comment.