From 705deee00d34cfb0c045f4fe23ba93f4e03c4f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Taylor?= Date: Wed, 18 Oct 2023 07:17:37 +0200 Subject: [PATCH] refactor: move more code from logical plans to ops (#14287) --- go/vt/vtgate/planbuilder/concatenate.go | 43 ------ go/vt/vtgate/planbuilder/delete.go | 8 -- go/vt/vtgate/planbuilder/distinct.go | 15 -- go/vt/vtgate/planbuilder/dml_planner.go | 13 -- go/vt/vtgate/planbuilder/fk_cascade.go | 37 ----- go/vt/vtgate/planbuilder/fk_verify.go | 46 ------ go/vt/vtgate/planbuilder/insert.go | 32 +---- go/vt/vtgate/planbuilder/join.go | 51 ------- go/vt/vtgate/planbuilder/logical_plan.go | 87 ----------- go/vt/vtgate/planbuilder/memory_sort.go | 6 - go/vt/vtgate/planbuilder/merge_sort.go | 15 -- .../planbuilder/operator_transformers.go | 136 +++++++++++++----- .../vtgate/planbuilder/operators/ast_to_op.go | 2 +- go/vt/vtgate/planbuilder/operators/delete.go | 9 +- .../operators/horizon_expanding.go | 2 +- go/vt/vtgate/planbuilder/operators/insert.go | 14 +- .../planbuilder/operators/insert_selection.go | 18 ++- go/vt/vtgate/planbuilder/operators/join.go | 2 +- .../planbuilder/operators/query_planning.go | 2 +- .../planbuilder/operators/subquery_builder.go | 10 +- go/vt/vtgate/planbuilder/operators/update.go | 9 +- go/vt/vtgate/planbuilder/ordered_aggregate.go | 18 --- go/vt/vtgate/planbuilder/planner.go | 42 +++--- go/vt/vtgate/planbuilder/postprocess.go | 45 ------ go/vt/vtgate/planbuilder/primitive_wrapper.go | 24 ---- go/vt/vtgate/planbuilder/projection.go | 55 +------ go/vt/vtgate/planbuilder/route.go | 32 ----- go/vt/vtgate/planbuilder/select.go | 7 +- go/vt/vtgate/planbuilder/semi_join.go | 36 ----- go/vt/vtgate/planbuilder/simple_projection.go | 11 -- .../vtgate/planbuilder/sql_calc_found_rows.go | 40 ------ .../planbuilder/uncorrelated_subquery.go | 37 ----- go/vt/vtgate/planbuilder/update.go | 10 +- go/vt/vtgate/planbuilder/vindex_func.go | 34 ----- 34 files changed, 174 insertions(+), 774 deletions(-) delete mode 100644 go/vt/vtgate/planbuilder/postprocess.go diff --git a/go/vt/vtgate/planbuilder/concatenate.go b/go/vt/vtgate/planbuilder/concatenate.go index b6ece23d010..81cbe3d5b65 100644 --- a/go/vt/vtgate/planbuilder/concatenate.go +++ b/go/vt/vtgate/planbuilder/concatenate.go @@ -17,11 +17,7 @@ limitations under the License. package planbuilder import ( - "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" - "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" - "vitess.io/vitess/go/vt/vtgate/semantics" ) type concatenate struct { @@ -34,17 +30,6 @@ type concatenate struct { var _ logicalPlan = (*concatenate)(nil) -// Wireup implements the logicalPlan interface -func (c *concatenate) Wireup(ctx *plancontext.PlanningContext) error { - for _, source := range c.sources { - err := source.Wireup(ctx) - if err != nil { - return err - } - } - return nil -} - // Primitive implements the logicalPlan interface func (c *concatenate) Primitive() engine.Primitive { var sources []engine.Primitive @@ -54,31 +39,3 @@ func (c *concatenate) Primitive() engine.Primitive { return engine.NewConcatenate(sources, c.noNeedToTypeCheck) } - -// Rewrite implements the logicalPlan interface -func (c *concatenate) Rewrite(inputs ...logicalPlan) error { - if len(inputs) != len(c.sources) { - return vterrors.VT13001("concatenate: wrong number of inputs") - } - c.sources = inputs - return nil -} - -// ContainsTables implements the logicalPlan interface -func (c *concatenate) ContainsTables() semantics.TableSet { - var tableSet semantics.TableSet - for _, source := range c.sources { - tableSet = tableSet.Merge(source.ContainsTables()) - } - return tableSet -} - -// Inputs implements the logicalPlan interface -func (c *concatenate) Inputs() []logicalPlan { - return c.sources -} - -// OutputColumns implements the logicalPlan interface -func (c *concatenate) OutputColumns() []sqlparser.SelectExpr { - return c.sources[0].OutputColumns() -} diff --git a/go/vt/vtgate/planbuilder/delete.go b/go/vt/vtgate/planbuilder/delete.go index 385b8b7f924..188c1485d1d 100644 --- a/go/vt/vtgate/planbuilder/delete.go +++ b/go/vt/vtgate/planbuilder/delete.go @@ -87,14 +87,6 @@ func gen4DeleteStmtPlanner( return nil, err } - plan = pushCommentDirectivesOnPlan(plan, deleteStmt) - - setLockOnAllSelect(plan) - - if err := plan.Wireup(ctx); err != nil { - return nil, err - } - return newPlanResult(plan.Primitive(), operators.TablesUsed(op)...), nil } diff --git a/go/vt/vtgate/planbuilder/distinct.go b/go/vt/vtgate/planbuilder/distinct.go index 8b81fa4a8ce..2a9f58a9942 100644 --- a/go/vt/vtgate/planbuilder/distinct.go +++ b/go/vt/vtgate/planbuilder/distinct.go @@ -17,7 +17,6 @@ limitations under the License. package planbuilder import ( - "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" ) @@ -61,17 +60,3 @@ func (d *distinct) Primitive() engine.Primitive { Truncate: truncate, } } - -// Rewrite implements the logicalPlan interface -func (d *distinct) Rewrite(inputs ...logicalPlan) error { - if len(inputs) != 1 { - return vterrors.VT13001("distinct: wrong number of inputs") - } - d.input = inputs[0] - return nil -} - -// Inputs implements the logicalPlan interface -func (d *distinct) Inputs() []logicalPlan { - return []logicalPlan{d.input} -} diff --git a/go/vt/vtgate/planbuilder/dml_planner.go b/go/vt/vtgate/planbuilder/dml_planner.go index a85d10b742a..7ec616f7f36 100644 --- a/go/vt/vtgate/planbuilder/dml_planner.go +++ b/go/vt/vtgate/planbuilder/dml_planner.go @@ -56,19 +56,6 @@ func rewriteRoutedTables(stmt sqlparser.Statement, vschema plancontext.VSchema) }, stmt) } -func setLockOnAllSelect(plan logicalPlan) { - _, _ = visit(plan, func(plan logicalPlan) (bool, logicalPlan, error) { - switch node := plan.(type) { - case *route: - if node.Select.GetLock() == sqlparser.NoLock { - node.Select.SetLock(sqlparser.ShareModeLock) - } - return true, node, nil - } - return true, plan, nil - }) -} - func generateQuery(statement sqlparser.Statement) string { buf := sqlparser.NewTrackedBuffer(dmlFormatter) statement.Format(buf) diff --git a/go/vt/vtgate/planbuilder/fk_cascade.go b/go/vt/vtgate/planbuilder/fk_cascade.go index 5a709156955..f2ca67ef5d0 100644 --- a/go/vt/vtgate/planbuilder/fk_cascade.go +++ b/go/vt/vtgate/planbuilder/fk_cascade.go @@ -17,11 +17,7 @@ limitations under the License. package planbuilder import ( - "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" - "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" - "vitess.io/vitess/go/vt/vtgate/semantics" ) var _ logicalPlan = (*fkCascade)(nil) @@ -50,36 +46,3 @@ func (fkc *fkCascade) Primitive() engine.Primitive { Children: fkc.children, } } - -// Wireup implements the logicalPlan interface -func (fkc *fkCascade) Wireup(ctx *plancontext.PlanningContext) error { - if err := fkc.parent.Wireup(ctx); err != nil { - return err - } - return fkc.selection.Wireup(ctx) -} - -// Rewrite implements the logicalPlan interface -func (fkc *fkCascade) Rewrite(inputs ...logicalPlan) error { - if len(inputs) != 2 { - return vterrors.VT13001("fkCascade: wrong number of inputs") - } - fkc.parent = inputs[0] - fkc.selection = inputs[1] - return nil -} - -// ContainsTables implements the logicalPlan interface -func (fkc *fkCascade) ContainsTables() semantics.TableSet { - return fkc.parent.ContainsTables() -} - -// Inputs implements the logicalPlan interface -func (fkc *fkCascade) Inputs() []logicalPlan { - return []logicalPlan{fkc.parent, fkc.selection} -} - -// OutputColumns implements the logicalPlan interface -func (fkc *fkCascade) OutputColumns() []sqlparser.SelectExpr { - return nil -} diff --git a/go/vt/vtgate/planbuilder/fk_verify.go b/go/vt/vtgate/planbuilder/fk_verify.go index 71638f88b9b..206bad90fea 100644 --- a/go/vt/vtgate/planbuilder/fk_verify.go +++ b/go/vt/vtgate/planbuilder/fk_verify.go @@ -17,11 +17,7 @@ limitations under the License. package planbuilder import ( - "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" - "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" - "vitess.io/vitess/go/vt/vtgate/semantics" ) var _ logicalPlan = (*fkVerify)(nil) @@ -59,45 +55,3 @@ func (fkc *fkVerify) Primitive() engine.Primitive { Verify: verify, } } - -// Wireup implements the logicalPlan interface -func (fkc *fkVerify) Wireup(ctx *plancontext.PlanningContext) error { - for _, v := range fkc.verify { - err := v.verify.Wireup(ctx) - if err != nil { - return err - } - } - return fkc.input.Wireup(ctx) -} - -// Rewrite implements the logicalPlan interface -func (fkc *fkVerify) Rewrite(inputs ...logicalPlan) error { - if len(fkc.verify) != len(inputs)-1 { - return vterrors.VT13001("fkVerify: wrong number of inputs") - } - fkc.input = inputs[0] - for i := 1; i < len(inputs); i++ { - fkc.verify[i-1].verify = inputs[i] - } - return nil -} - -// ContainsTables implements the logicalPlan interface -func (fkc *fkVerify) ContainsTables() semantics.TableSet { - return fkc.input.ContainsTables() -} - -// Inputs implements the logicalPlan interface -func (fkc *fkVerify) Inputs() []logicalPlan { - inputs := []logicalPlan{fkc.input} - for _, v := range fkc.verify { - inputs = append(inputs, v.verify) - } - return inputs -} - -// OutputColumns implements the logicalPlan interface -func (fkc *fkVerify) OutputColumns() []sqlparser.SelectExpr { - return nil -} diff --git a/go/vt/vtgate/planbuilder/insert.go b/go/vt/vtgate/planbuilder/insert.go index 8eba43ce471..c187cd7efdc 100644 --- a/go/vt/vtgate/planbuilder/insert.go +++ b/go/vt/vtgate/planbuilder/insert.go @@ -52,7 +52,7 @@ func gen4InsertStmtPlanner(version querypb.ExecuteOptions_PlannerVersion, insStm if ks != nil { if tables[0].AutoIncrement == nil && !ctx.SemTable.ForeignKeysPresent() { plan := insertUnshardedShortcut(insStmt, ks, tables) - plan = pushCommentDirectivesOnPlan(plan, insStmt) + setCommentDirectivesOnPlan(plan, insStmt) return newPlanResult(plan.Primitive(), operators.QualifiedTables(ks, tables)...), nil } } @@ -81,14 +81,6 @@ func gen4InsertStmtPlanner(version querypb.ExecuteOptions_PlannerVersion, insStm return nil, err } - plan = pushCommentDirectivesOnPlan(plan, insStmt) - - setLockOnAllSelect(plan) - - if err := plan.Wireup(ctx); err != nil { - return nil, err - } - return newPlanResult(plan.Primitive(), operators.TablesUsed(op)...), nil } @@ -121,13 +113,6 @@ type insert struct { var _ logicalPlan = (*insert)(nil) -func (i *insert) Wireup(ctx *plancontext.PlanningContext) error { - if i.source == nil { - return nil - } - return i.source.Wireup(ctx) -} - func (i *insert) Primitive() engine.Primitive { if i.source != nil { i.eInsert.Input = i.source.Primitive() @@ -135,21 +120,6 @@ func (i *insert) Primitive() engine.Primitive { return i.eInsert } -func (i *insert) Inputs() []logicalPlan { - if i.source == nil { - return nil - } - return []logicalPlan{i.source} -} - -func (i *insert) Rewrite(inputs ...logicalPlan) error { - panic("does not expect insert to get rewrite call") -} - func (i *insert) ContainsTables() semantics.TableSet { panic("does not expect insert to get contains tables call") } - -func (i *insert) OutputColumns() []sqlparser.SelectExpr { - panic("does not expect insert to get output columns call") -} diff --git a/go/vt/vtgate/planbuilder/join.go b/go/vt/vtgate/planbuilder/join.go index 2b438ce56a0..02027a8b49e 100644 --- a/go/vt/vtgate/planbuilder/join.go +++ b/go/vt/vtgate/planbuilder/join.go @@ -17,13 +17,8 @@ limitations under the License. package planbuilder import ( - "fmt" - "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" - "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" - "vitess.io/vitess/go/vt/vtgate/semantics" ) var _ logicalPlan = (*join)(nil) @@ -50,15 +45,6 @@ type join struct { LHSColumns []*sqlparser.ColName } -// Wireup implements the logicalPlan interface -func (j *join) Wireup(ctx *plancontext.PlanningContext) error { - err := j.Left.Wireup(ctx) - if err != nil { - return err - } - return j.Right.Wireup(ctx) -} - // Primitive implements the logicalPlan interface func (j *join) Primitive() engine.Primitive { return &engine.Join{ @@ -69,40 +55,3 @@ func (j *join) Primitive() engine.Primitive { Opcode: j.Opcode, } } - -// Inputs implements the logicalPlan interface -func (j *join) Inputs() []logicalPlan { - return []logicalPlan{j.Left, j.Right} -} - -// Rewrite implements the logicalPlan interface -func (j *join) Rewrite(inputs ...logicalPlan) error { - if len(inputs) != 2 { - return vterrors.VT13001(fmt.Sprintf("wrong number of children in join rewrite, got: %d, expect: 2", len(inputs))) - } - j.Left = inputs[0] - j.Right = inputs[1] - return nil -} - -// ContainsTables implements the logicalPlan interface -func (j *join) ContainsTables() semantics.TableSet { - return j.Left.ContainsTables().Merge(j.Right.ContainsTables()) -} - -// OutputColumns implements the logicalPlan interface -func (j *join) OutputColumns() []sqlparser.SelectExpr { - return getOutputColumnsFromJoin(j.Cols, j.Left.OutputColumns(), j.Right.OutputColumns()) -} - -func getOutputColumnsFromJoin(ints []int, lhs []sqlparser.SelectExpr, rhs []sqlparser.SelectExpr) (cols []sqlparser.SelectExpr) { - for _, col := range ints { - if col < 0 { - col *= -1 - cols = append(cols, lhs[col-1]) - } else { - cols = append(cols, rhs[col-1]) - } - } - return -} diff --git a/go/vt/vtgate/planbuilder/logical_plan.go b/go/vt/vtgate/planbuilder/logical_plan.go index 51ed8e72b0e..fac0bb59b5f 100644 --- a/go/vt/vtgate/planbuilder/logical_plan.go +++ b/go/vt/vtgate/planbuilder/logical_plan.go @@ -17,73 +17,14 @@ limitations under the License. package planbuilder import ( - "fmt" - - "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" - "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" - "vitess.io/vitess/go/vt/vtgate/semantics" ) // logicalPlan defines the interface that a primitive must // satisfy. type logicalPlan interface { - - // Wireup does the wire up of primitive with the source. - Wireup(*plancontext.PlanningContext) error - // Primitive returns the underlying primitive. - // This function should only be called after Wireup is finished. Primitive() engine.Primitive - - // Inputs are the children of this plan - Inputs() []logicalPlan - - // Rewrite replaces the inputs of this plan with the ones provided - Rewrite(inputs ...logicalPlan) error - - // ContainsTables keeps track which query tables are being solved by this logical plan - // This is only applicable for plans that have been built with the Gen4 planner - ContainsTables() semantics.TableSet - - // OutputColumns shows the columns that this plan will produce - OutputColumns() []sqlparser.SelectExpr -} - -type planVisitor func(logicalPlan) (bool, logicalPlan, error) - -func visit(node logicalPlan, visitor planVisitor) (logicalPlan, error) { - if visitor != nil { - kontinue, newNode, err := visitor(node) - if err != nil { - return nil, err - } - if !kontinue { - return newNode, nil - } - node = newNode - } - inputs := node.Inputs() - rewrite := false - for i, input := range inputs { - newInput, err := visit(input, visitor) - if err != nil { - return nil, err - } - if newInput != input { - rewrite = true - } - inputs[i] = newInput - } - if rewrite { - err := node.Rewrite(inputs...) - if err != nil { - return nil, err - } - } - - return node, nil } // ------------------------------------------------------------------------- @@ -103,34 +44,6 @@ func (bc *logicalPlanCommon) Order() int { return bc.order } -func (bc *logicalPlanCommon) Wireup(ctx *plancontext.PlanningContext) error { - return bc.input.Wireup(ctx) -} - -// Rewrite implements the logicalPlan interface -func (bc *logicalPlanCommon) Rewrite(inputs ...logicalPlan) error { - if len(inputs) != 1 { - return vterrors.VT13001(fmt.Sprintf("builderCommon: wrong number of inputs, got: %d, expect: 1", len(inputs))) - } - bc.input = inputs[0] - return nil -} - -// Inputs implements the logicalPlan interface -func (bc *logicalPlanCommon) Inputs() []logicalPlan { - return []logicalPlan{bc.input} -} - -// ContainsTables implements the logicalPlan interface -func (bc *logicalPlanCommon) ContainsTables() semantics.TableSet { - return bc.input.ContainsTables() -} - -// OutputColumns implements the logicalPlan interface -func (bc *logicalPlanCommon) OutputColumns() []sqlparser.SelectExpr { - return bc.input.OutputColumns() -} - // ------------------------------------------------------------------------- // resultsBuilder is a superset of logicalPlanCommon. It also handles diff --git a/go/vt/vtgate/planbuilder/memory_sort.go b/go/vt/vtgate/planbuilder/memory_sort.go index d32777ac123..e1d3cf311dc 100644 --- a/go/vt/vtgate/planbuilder/memory_sort.go +++ b/go/vt/vtgate/planbuilder/memory_sort.go @@ -17,8 +17,6 @@ limitations under the License. package planbuilder import ( - "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" - "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/sqlparser" @@ -47,7 +45,3 @@ func (ms *memorySort) Primitive() engine.Primitive { func (ms *memorySort) SetLimit(limit *sqlparser.Limit) error { return vterrors.VT13001("memorySort.Limit: unreachable") } - -func (ms *memorySort) Wireup(ctx *plancontext.PlanningContext) error { - return ms.input.Wireup(ctx) -} diff --git a/go/vt/vtgate/planbuilder/merge_sort.go b/go/vt/vtgate/planbuilder/merge_sort.go index 0da5b5fc135..edca9194ccf 100644 --- a/go/vt/vtgate/planbuilder/merge_sort.go +++ b/go/vt/vtgate/planbuilder/merge_sort.go @@ -17,9 +17,7 @@ limitations under the License. package planbuilder import ( - "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/engine" - "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" ) var _ logicalPlan = (*mergeSort)(nil) @@ -47,16 +45,3 @@ func (ms *mergeSort) SetTruncateColumnCount(count int) { func (ms *mergeSort) Primitive() engine.Primitive { return ms.input.Primitive() } - -func (ms *mergeSort) Wireup(ctx *plancontext.PlanningContext) error { - return ms.input.Wireup(ctx) -} - -// OutputColumns implements the logicalPlan interface -func (ms *mergeSort) OutputColumns() []sqlparser.SelectExpr { - outputCols := ms.input.OutputColumns() - if ms.truncateColumnCount > 0 { - return outputCols[:ms.truncateColumnCount] - } - return outputCols -} diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index 5cfd07e8062..381aeb704c5 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -74,9 +74,9 @@ func transformToLogicalPlan(ctx *plancontext.PlanningContext, op ops.Operator) ( } func transformInsertionSelection(ctx *plancontext.PlanningContext, op *operators.InsertSelection) (logicalPlan, error) { - rb, isRoute := op.InsertionOp.(*operators.Route) + rb, isRoute := op.Insert.(*operators.Route) if !isRoute { - return nil, vterrors.VT13001(fmt.Sprintf("Incorrect type encountered: %T (transformInsertionSelection)", op.InsertionOp)) + return nil, vterrors.VT13001(fmt.Sprintf("Incorrect type encountered: %T (transformInsertionSelection)", op.Insert)) } stmt, dmlOp, err := operators.ToSQL(ctx, rb.Source) @@ -104,7 +104,7 @@ func transformInsertionSelection(ctx *plancontext.PlanningContext, op *operators eins.Prefix, eins.Mid, eins.Suffix = generateInsertShardedQuery(ins.AST) - selectionPlan, err := transformToLogicalPlan(ctx, op.SelectionOp) + selectionPlan, err := transformToLogicalPlan(ctx, op.Select) if err != nil { return nil, err } @@ -136,10 +136,7 @@ func transformFkCascade(ctx *plancontext.PlanningContext, fkc *operators.FkCasca if err != nil { return nil, err } - err = childLP.Wireup(ctx) - if err != nil { - return nil, err - } + childEngine := childLP.Primitive() children = append(children, &engine.FkChild{ BVName: child.BVName, @@ -303,7 +300,6 @@ func transformProjection(ctx *plancontext.PlanningContext, op *operators.Project return nil, err } - var exprs []sqlparser.Expr var evalengineExprs []evalengine.Expr var columnNames []string for _, pe := range ap { @@ -312,7 +308,6 @@ func transformProjection(ctx *plancontext.PlanningContext, op *operators.Project return nil, err } evalengineExprs = append(evalengineExprs, ee) - exprs = append(exprs, pe.EvalExpr) columnNames = append(columnNames, pe.Original.ColumnName()) } @@ -322,10 +317,8 @@ func transformProjection(ctx *plancontext.PlanningContext, op *operators.Project } return &projection{ - source: src, - columnNames: columnNames, - columns: exprs, - primitive: primitive, + source: src, + primitive: primitive, }, nil } @@ -416,7 +409,7 @@ func transformApplyJoinPlan(ctx *plancontext.PlanningContext, n *operators.Apply }, nil } -func routeToEngineRoute(ctx *plancontext.PlanningContext, op *operators.Route) (*engine.Route, error) { +func routeToEngineRoute(ctx *plancontext.PlanningContext, op *operators.Route, hints *queryHints) (*engine.Route, error) { tableNames, err := getAllTableNames(op) if err != nil { return nil, err @@ -428,11 +421,16 @@ func routeToEngineRoute(ctx *plancontext.PlanningContext, op *operators.Route) ( return nil, err } - return &engine.Route{ + e := &engine.Route{ TableName: strings.Join(tableNames, ", "), RoutingParameters: rp, TruncateColumnCount: op.ResultColumns, - }, nil + } + if hints != nil { + e.ScatterErrorsAsWarnings = hints.scatterErrorsAsWarnings + e.QueryTimeout = hints.queryTimeout + } + return e, nil } func newRoutingParams(ctx *plancontext.PlanningContext, opCode engine.Opcode) *engine.RoutingParameters { @@ -448,6 +446,27 @@ func newRoutingParams(ctx *plancontext.PlanningContext, opCode engine.Opcode) *e } } +type queryHints struct { + scatterErrorsAsWarnings, + multiShardAutocommit bool + queryTimeout int +} + +func getHints(cmt *sqlparser.ParsedComments) *queryHints { + if cmt == nil { + return nil + } + directives := cmt.Directives() + scatterAsWarns := directives.IsSet(sqlparser.DirectiveScatterErrorsAsWarnings) + timeout := queryTimeout(directives) + multiShardAutoCommit := directives.IsSet(sqlparser.DirectiveMultiShardAutocommit) + return &queryHints{ + scatterErrorsAsWarnings: scatterAsWarns, + multiShardAutocommit: multiShardAutoCommit, + queryTimeout: timeout, + } +} + func transformRoutePlan(ctx *plancontext.PlanningContext, op *operators.Route) (logicalPlan, error) { stmt, dmlOp, err := operators.ToSQL(ctx, op.Source) if err != nil { @@ -455,29 +474,32 @@ func transformRoutePlan(ctx *plancontext.PlanningContext, op *operators.Route) ( } if stmtWithComments, ok := stmt.(sqlparser.Commented); ok && op.Comments != nil { - stmtWithComments.SetComments(op.Comments.GetComments()) + comments := op.Comments.GetComments() + stmtWithComments.SetComments(comments) } + hints := getHints(op.Comments) switch stmt := stmt.(type) { case sqlparser.SelectStatement: if op.Lock != sqlparser.NoLock { stmt.SetLock(op.Lock) } - return buildRouteLogicalPlan(ctx, op, stmt) + return buildRouteLogicalPlan(ctx, op, stmt, hints) case *sqlparser.Update: - return buildUpdateLogicalPlan(ctx, op, dmlOp, stmt) + return buildUpdateLogicalPlan(ctx, op, dmlOp, stmt, hints) case *sqlparser.Delete: - return buildDeleteLogicalPlan(ctx, op, dmlOp) + return buildDeleteLogicalPlan(ctx, op, dmlOp, hints) case *sqlparser.Insert: - return buildInsertLogicalPlan(ctx, op, dmlOp, stmt) + return buildInsertLogicalPlan(op, dmlOp, stmt, hints) default: return nil, vterrors.VT13001(fmt.Sprintf("dont know how to %T", stmt)) } } -func buildRouteLogicalPlan(ctx *plancontext.PlanningContext, op *operators.Route, stmt sqlparser.SelectStatement) (logicalPlan, error) { - condition := getVindexPredicate(op) - eroute, err := routeToEngineRoute(ctx, op) +func buildRouteLogicalPlan(ctx *plancontext.PlanningContext, op *operators.Route, stmt sqlparser.SelectStatement, hints *queryHints) (logicalPlan, error) { + _ = updateSelectedVindexPredicate(op) + + eroute, err := routeToEngineRoute(ctx, op, hints) for _, order := range op.Ordering { typ, collation, _ := ctx.SemTable.TypeForExpr(order.AST) eroute.OrderBy = append(eroute.OrderBy, engine.OrderByParams{ @@ -491,15 +513,24 @@ func buildRouteLogicalPlan(ctx *plancontext.PlanningContext, op *operators.Route if err != nil { return nil, err } - return &route{ - eroute: eroute, - Select: stmt, - tables: operators.TableID(op), - condition: condition, - }, nil + r := &route{ + eroute: eroute, + Select: stmt, + tables: operators.TableID(op), + } + + if err = r.Wireup(ctx); err != nil { + return nil, err + } + return r, nil } -func buildInsertLogicalPlan(ctx *plancontext.PlanningContext, rb *operators.Route, op ops.Operator, stmt *sqlparser.Insert) (logicalPlan, error) { +func buildInsertLogicalPlan( + rb *operators.Route, + op ops.Operator, + stmt *sqlparser.Insert, + hints *queryHints, +) (logicalPlan, error) { ins := op.(*operators.Insert) eins := &engine.Insert{ Opcode: mapToInsertOpCode(rb.Routing.OpCode(), false), @@ -519,6 +550,11 @@ func buildInsertLogicalPlan(ctx *plancontext.PlanningContext, rb *operators.Rout eins.Prefix, eins.Mid, eins.Suffix = generateInsertShardedQuery(ins.AST) } + if hints != nil { + eins.MultiShardAutocommit = hints.multiShardAutocommit + eins.QueryTimeout = hints.queryTimeout + } + eins.Query = generateQuery(stmt) return lp, nil } @@ -585,6 +621,7 @@ func buildUpdateLogicalPlan( rb *operators.Route, dmlOp ops.Operator, stmt *sqlparser.Update, + hints *queryHints, ) (logicalPlan, error) { upd := dmlOp.(*operators.Update) rp := newRoutingParams(ctx, rb.Routing.OpCode()) @@ -606,6 +643,10 @@ func buildUpdateLogicalPlan( ChangedVindexValues: upd.ChangedVindexValues, DML: edml, } + if hints != nil { + e.MultiShardAutocommit = hints.multiShardAutocommit + e.QueryTimeout = hints.queryTimeout + } return &primitiveWrapper{prim: e}, nil } @@ -614,6 +655,7 @@ func buildDeleteLogicalPlan( ctx *plancontext.PlanningContext, rb *operators.Route, dmlOp ops.Operator, + hints *queryHints, ) (logicalPlan, error) { del := dmlOp.(*operators.Delete) rp := newRoutingParams(ctx, rb.Routing.OpCode()) @@ -634,6 +676,10 @@ func buildDeleteLogicalPlan( e := &engine.Delete{ DML: edml, } + if hints != nil { + e.MultiShardAutocommit = hints.multiShardAutocommit + e.QueryTimeout = hints.queryTimeout + } return &primitiveWrapper{prim: e}, nil } @@ -646,15 +692,12 @@ func transformDMLPlan(vtable *vindexes.Table, edml *engine.DML, routing operator } } -func getVindexPredicate(op *operators.Route) sqlparser.Expr { +func updateSelectedVindexPredicate(op *operators.Route) sqlparser.Expr { tr, ok := op.Routing.(*operators.ShardedRouting) if !ok || tr.Selected == nil { return nil } - var condition sqlparser.Expr - if len(tr.Selected.ValueExprs) > 0 { - condition = tr.Selected.ValueExprs[0] - } + _, isMultiColumn := tr.Selected.FoundVindex.(vindexes.MultiColumn) for idx, expr := range tr.Selected.Predicates { cmp, ok := expr.(*sqlparser.ComparisonExpr) @@ -675,7 +718,7 @@ func getVindexPredicate(op *operators.Route) sqlparser.Expr { cmp.Right = sqlparser.ListArg(argName) } - return condition + return nil } func getAllTableNames(op *operators.Route) ([]string, error) { @@ -734,3 +777,22 @@ func transformLimit(ctx *plancontext.PlanningContext, op *operators.Limit) (logi return createLimit(plan, op.AST) } + +func createLimit(input logicalPlan, limit *sqlparser.Limit) (logicalPlan, error) { + plan := newLimit(input) + pv, err := evalengine.Translate(limit.Rowcount, nil) + if err != nil { + return nil, vterrors.Wrap(err, "unexpected expression in LIMIT") + } + plan.elimit.Count = pv + + if limit.Offset != nil { + pv, err = evalengine.Translate(limit.Offset, nil) + if err != nil { + return nil, vterrors.Wrap(err, "unexpected expression in OFFSET") + } + plan.elimit.Offset = pv + } + + return plan, nil +} diff --git a/go/vt/vtgate/planbuilder/operators/ast_to_op.go b/go/vt/vtgate/planbuilder/operators/ast_to_op.go index 83f5d268094..bc4aaf8a4e6 100644 --- a/go/vt/vtgate/planbuilder/operators/ast_to_op.go +++ b/go/vt/vtgate/planbuilder/operators/ast_to_op.go @@ -94,7 +94,7 @@ func addWherePredicates(ctx *plancontext.PlanningContext, expr sqlparser.Expr, o op = op.AddPredicate(ctx, expr) addColumnEquality(ctx, expr) } - return sqc.getRootOperator(op), nil + return sqc.getRootOperator(op, nil), nil } // cloneASTAndSemState clones the AST and the semantic state of the input node. diff --git a/go/vt/vtgate/planbuilder/operators/delete.go b/go/vt/vtgate/planbuilder/operators/delete.go index 128c625c428..f02444671c1 100644 --- a/go/vt/vtgate/planbuilder/operators/delete.go +++ b/go/vt/vtgate/planbuilder/operators/delete.go @@ -91,6 +91,13 @@ func createOperatorFromDelete(ctx *plancontext.PlanningContext, deleteStmt *sqlp return nil, err } + if deleteStmt.Comments != nil { + delOp = &LockAndComment{ + Source: delOp, + Comments: deleteStmt.Comments, + } + } + childFks := ctx.SemTable.GetChildForeignKeysList() // If there are no foreign key constraints, then we don't need to do anything. if len(childFks) == 0 { @@ -160,7 +167,7 @@ func createDeleteOperator( return nil, vterrors.VT12001("multi shard DELETE with LIMIT") } - return sqc.getRootOperator(route), nil + return sqc.getRootOperator(route, nil), nil } func createFkCascadeOpForDelete(ctx *plancontext.PlanningContext, parentOp ops.Operator, delStmt *sqlparser.Delete, childFks []vindexes.ChildFKInfo) (ops.Operator, error) { diff --git a/go/vt/vtgate/planbuilder/operators/horizon_expanding.go b/go/vt/vtgate/planbuilder/operators/horizon_expanding.go index 0616ec60c32..7ec141a1b8b 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_expanding.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_expanding.go @@ -269,7 +269,7 @@ func createProjectionWithoutAggr(ctx *plancontext.PlanningContext, qp *QueryProj } } } - proj.Source = sqc.getRootOperator(src) + proj.Source = sqc.getRootOperator(src, nil) return proj } diff --git a/go/vt/vtgate/planbuilder/operators/insert.go b/go/vt/vtgate/planbuilder/operators/insert.go index 95f85e11f75..819b5cfcbbc 100644 --- a/go/vt/vtgate/planbuilder/operators/insert.go +++ b/go/vt/vtgate/planbuilder/operators/insert.go @@ -121,6 +121,13 @@ func createOperatorFromInsert(ctx *plancontext.PlanningContext, ins *sqlparser.I return nil, err } + if ins.Comments != nil { + insOp = &LockAndComment{ + Source: insOp, + Comments: ins.Comments, + } + } + // Find the foreign key mode and for unmanaged foreign-key-mode, we don't need to do anything. ksMode, err := ctx.VSchema.ForeignKeyMode(vindexTable.Keyspace.Name) if err != nil { @@ -201,8 +208,11 @@ func insertSelectPlan(ctx *plancontext.PlanningContext, insOp *Insert, routeOp * // output of the select plan will be used to insert rows into the table. insertSelect := &InsertSelection{ - SelectionOp: selOp, - InsertionOp: routeOp, + Select: &LockAndComment{ + Source: selOp, + Lock: sqlparser.ShareModeLock, + }, + Insert: routeOp, } // When the table you are streaming data from and table you are inserting from are same. diff --git a/go/vt/vtgate/planbuilder/operators/insert_selection.go b/go/vt/vtgate/planbuilder/operators/insert_selection.go index 454052e0b61..5ae49ee2c55 100644 --- a/go/vt/vtgate/planbuilder/operators/insert_selection.go +++ b/go/vt/vtgate/planbuilder/operators/insert_selection.go @@ -24,8 +24,8 @@ import ( // InsertSelection operator represents an INSERT into SELECT FROM query. // It holds the operators for running the selection and insertion. type InsertSelection struct { - SelectionOp ops.Operator - InsertionOp ops.Operator + Select ops.Operator + Insert ops.Operator // ForceNonStreaming when true, select first then insert, this is to avoid locking rows by select for insert. ForceNonStreaming bool @@ -36,21 +36,25 @@ type InsertSelection struct { func (is *InsertSelection) Clone(inputs []ops.Operator) ops.Operator { return &InsertSelection{ - SelectionOp: inputs[0], - InsertionOp: inputs[1], + Select: inputs[0], + Insert: inputs[1], + ForceNonStreaming: is.ForceNonStreaming, } } func (is *InsertSelection) Inputs() []ops.Operator { - return []ops.Operator{is.SelectionOp, is.InsertionOp} + return []ops.Operator{is.Select, is.Insert} } func (is *InsertSelection) SetInputs(inputs []ops.Operator) { - is.SelectionOp = inputs[0] - is.InsertionOp = inputs[1] + is.Select = inputs[0] + is.Insert = inputs[1] } func (is *InsertSelection) ShortDescription() string { + if is.ForceNonStreaming { + return "NonStreaming" + } return "" } diff --git a/go/vt/vtgate/planbuilder/operators/join.go b/go/vt/vtgate/planbuilder/operators/join.go index 7cc29b42deb..828b15f5b79 100644 --- a/go/vt/vtgate/planbuilder/operators/join.go +++ b/go/vt/vtgate/planbuilder/operators/join.go @@ -129,7 +129,7 @@ func createInnerJoin(ctx *plancontext.PlanningContext, tableExpr *sqlparser.Join } op = op.AddPredicate(ctx, pred) } - return sqc.getRootOperator(op), nil + return sqc.getRootOperator(op, nil), nil } func (j *Join) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Expr) ops.Operator { diff --git a/go/vt/vtgate/planbuilder/operators/query_planning.go b/go/vt/vtgate/planbuilder/operators/query_planning.go index 4554b09fcb7..8f36107c46f 100644 --- a/go/vt/vtgate/planbuilder/operators/query_planning.go +++ b/go/vt/vtgate/planbuilder/operators/query_planning.go @@ -130,7 +130,7 @@ func pushLockAndComment(l *LockAndComment) (ops.Operator, *rewrite.ApplyResult, case *Horizon, *QueryGraph: // we want to wait until the horizons have been pushed under a route or expanded // that way we know that we've replaced the QueryGraphs with Routes - return src, rewrite.SameTree, nil + return l, rewrite.SameTree, nil case *Route: src.Comments = l.Comments src.Lock = l.Lock diff --git a/go/vt/vtgate/planbuilder/operators/subquery_builder.go b/go/vt/vtgate/planbuilder/operators/subquery_builder.go index a0897b5ad4b..1d1d12bbfe3 100644 --- a/go/vt/vtgate/planbuilder/operators/subquery_builder.go +++ b/go/vt/vtgate/planbuilder/operators/subquery_builder.go @@ -32,11 +32,17 @@ type SubQueryBuilder struct { outerID semantics.TableSet } -func (sqb *SubQueryBuilder) getRootOperator(op ops.Operator) ops.Operator { +func (sqb *SubQueryBuilder) getRootOperator(op ops.Operator, decorator func(operator ops.Operator) ops.Operator) ops.Operator { if len(sqb.Inner) == 0 { return op } + if decorator != nil { + for _, sq := range sqb.Inner { + sq.Subquery = decorator(sq.Subquery) + } + } + return &SubQueryContainer{ Outer: op, Inner: sqb.Inner, @@ -198,7 +204,7 @@ func createSubquery( return nil, err } - opInner = sqc.getRootOperator(opInner) + opInner = sqc.getRootOperator(opInner, nil) return &SubQuery{ FilterType: filterType, Subquery: opInner, diff --git a/go/vt/vtgate/planbuilder/operators/update.go b/go/vt/vtgate/planbuilder/operators/update.go index 252e5dd6195..52dae6bd9b5 100644 --- a/go/vt/vtgate/planbuilder/operators/update.go +++ b/go/vt/vtgate/planbuilder/operators/update.go @@ -192,7 +192,14 @@ func createUpdateOperator(ctx *plancontext.PlanningContext, updStmt *sqlparser.U Comments: updStmt.Comments, } - return sqc.getRootOperator(route), nil + decorator := func(op ops.Operator) ops.Operator { + return &LockAndComment{ + Source: op, + Lock: sqlparser.ShareModeLock, + } + } + + return sqc.getRootOperator(route, decorator), nil } func buildFkOperator(ctx *plancontext.PlanningContext, updOp ops.Operator, updClone *sqlparser.Update, parentFks []vindexes.ParentFKInfo, childFks []vindexes.ChildFKInfo, updatedTable *vindexes.Table) (ops.Operator, error) { diff --git a/go/vt/vtgate/planbuilder/ordered_aggregate.go b/go/vt/vtgate/planbuilder/ordered_aggregate.go index 6163900e674..34646fa3dea 100644 --- a/go/vt/vtgate/planbuilder/ordered_aggregate.go +++ b/go/vt/vtgate/planbuilder/ordered_aggregate.go @@ -17,9 +17,7 @@ limitations under the License. package planbuilder import ( - "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/engine" - "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" ) var _ logicalPlan = (*orderedAggregate)(nil) @@ -83,22 +81,6 @@ func (oa *orderedAggregate) Primitive() engine.Primitive { } } -func (oa *orderedAggregate) Wireup(ctx *plancontext.PlanningContext) error { - return oa.input.Wireup(ctx) -} - -// OutputColumns implements the logicalPlan interface -func (oa *orderedAggregate) OutputColumns() []sqlparser.SelectExpr { - outputCols := sqlparser.CloneSelectExprs(oa.input.OutputColumns()) - for _, aggr := range oa.aggregates { - outputCols[aggr.Col] = &sqlparser.AliasedExpr{Expr: aggr.Expr, As: sqlparser.NewIdentifierCI(aggr.Alias)} - } - if oa.truncateColumnCount > 0 { - return outputCols[:oa.truncateColumnCount] - } - return outputCols -} - // SetTruncateColumnCount sets the truncate column count. func (oa *orderedAggregate) SetTruncateColumnCount(count int) { oa.truncateColumnCount = count diff --git a/go/vt/vtgate/planbuilder/planner.go b/go/vt/vtgate/planbuilder/planner.go index 984fd83c4e0..b7a918260b7 100644 --- a/go/vt/vtgate/planbuilder/planner.go +++ b/go/vt/vtgate/planbuilder/planner.go @@ -44,34 +44,28 @@ func gen4Planner(query string, plannerVersion querypb.ExecuteOptions_PlannerVers } } -// pushCommentDirectivesOnPlan adds comments to queries -// TODO: this should move to the operator side of planning -func pushCommentDirectivesOnPlan(plan logicalPlan, stmt sqlparser.Statement) logicalPlan { +// setCommentDirectivesOnPlan adds comments to queries +func setCommentDirectivesOnPlan(plan logicalPlan, stmt sqlparser.Statement) { var directives *sqlparser.CommentDirectives cmt, ok := stmt.(sqlparser.Commented) - if ok { - directives = cmt.GetParsedComments().Directives() - scatterAsWarns := directives.IsSet(sqlparser.DirectiveScatterErrorsAsWarnings) - timeout := queryTimeout(directives) - multiShardAutoCommit := directives.IsSet(sqlparser.DirectiveMultiShardAutocommit) - - if scatterAsWarns || timeout > 0 || multiShardAutoCommit { - _, _ = visit(plan, func(logicalPlan logicalPlan) (bool, logicalPlan, error) { - switch plan := logicalPlan.(type) { - case *route: - plan.eroute.ScatterErrorsAsWarnings = scatterAsWarns - plan.eroute.QueryTimeout = timeout - case *primitiveWrapper: - setDirective(plan.prim, multiShardAutoCommit, timeout) - case *insert: - setDirective(plan.eInsert, multiShardAutoCommit, timeout) - } - return true, logicalPlan, nil - }) - } + if !ok { + return } - return plan + directives = cmt.GetParsedComments().Directives() + scatterAsWarns := directives.IsSet(sqlparser.DirectiveScatterErrorsAsWarnings) + timeout := queryTimeout(directives) + multiShardAutoCommit := directives.IsSet(sqlparser.DirectiveMultiShardAutocommit) + + switch plan := plan.(type) { + case *route: + plan.eroute.ScatterErrorsAsWarnings = scatterAsWarns + plan.eroute.QueryTimeout = timeout + case *primitiveWrapper: + setDirective(plan.prim, multiShardAutoCommit, timeout) + case *insert: + setDirective(plan.eInsert, multiShardAutoCommit, timeout) + } } func setDirective(prim engine.Primitive, msac bool, timeout int) { diff --git a/go/vt/vtgate/planbuilder/postprocess.go b/go/vt/vtgate/planbuilder/postprocess.go deleted file mode 100644 index 850c68701f8..00000000000 --- a/go/vt/vtgate/planbuilder/postprocess.go +++ /dev/null @@ -1,45 +0,0 @@ -/* -Copyright 2019 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package planbuilder - -import ( - "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vterrors" - "vitess.io/vitess/go/vt/vtgate/evalengine" -) - -// This file has functions to analyze postprocessing -// clauses like ORDER BY, etc. - -func createLimit(input logicalPlan, limit *sqlparser.Limit) (logicalPlan, error) { - plan := newLimit(input) - pv, err := evalengine.Translate(limit.Rowcount, nil) - if err != nil { - return nil, vterrors.Wrap(err, "unexpected expression in LIMIT") - } - plan.elimit.Count = pv - - if limit.Offset != nil { - pv, err = evalengine.Translate(limit.Offset, nil) - if err != nil { - return nil, vterrors.Wrap(err, "unexpected expression in OFFSET") - } - plan.elimit.Offset = pv - } - - return plan, nil -} diff --git a/go/vt/vtgate/planbuilder/primitive_wrapper.go b/go/vt/vtgate/planbuilder/primitive_wrapper.go index cb6a65aba04..a03c94ce850 100644 --- a/go/vt/vtgate/planbuilder/primitive_wrapper.go +++ b/go/vt/vtgate/planbuilder/primitive_wrapper.go @@ -17,11 +17,7 @@ limitations under the License. package planbuilder import ( - "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" - "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" - "vitess.io/vitess/go/vt/vtgate/semantics" ) // primitiveWrapper is used when only need a logical plan that supports plan.Primitive() and nothing else @@ -29,28 +25,8 @@ type primitiveWrapper struct { prim engine.Primitive } -func (p *primitiveWrapper) Wireup(*plancontext.PlanningContext) error { - return nil -} - func (p *primitiveWrapper) Primitive() engine.Primitive { return p.prim } -func (p *primitiveWrapper) Inputs() []logicalPlan { - return nil -} - -func (p *primitiveWrapper) Rewrite(...logicalPlan) error { - return vterrors.VT13001("cannot rewrite") -} - -func (p *primitiveWrapper) ContainsTables() semantics.TableSet { - return semantics.EmptyTableSet() -} - -func (p *primitiveWrapper) OutputColumns() []sqlparser.SelectExpr { - return nil -} - var _ logicalPlan = (*primitiveWrapper)(nil) diff --git a/go/vt/vtgate/planbuilder/projection.go b/go/vt/vtgate/planbuilder/projection.go index 70cb1979780..cb60c079c37 100644 --- a/go/vt/vtgate/planbuilder/projection.go +++ b/go/vt/vtgate/planbuilder/projection.go @@ -17,67 +17,16 @@ limitations under the License. package planbuilder import ( - "fmt" - - "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" - "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" - "vitess.io/vitess/go/vt/vtgate/semantics" ) type projection struct { - source logicalPlan - columnNames []string - columns []sqlparser.Expr - primitive *engine.Projection - // unorderedColumnIdx is used to find the index at which we should add any column output from projection - // we don't care for the ordering of. It should also be updated when such a column is added - unorderedColumnIdx int + source logicalPlan + primitive *engine.Projection } var _ logicalPlan = (*projection)(nil) -// Wireup implements the logicalPlan interface -func (p *projection) Wireup(ctx *plancontext.PlanningContext) error { - if p.primitive == nil { - return vterrors.VT13001("should already be done") - } - - return p.source.Wireup(ctx) -} - -// Inputs implements the logicalPlan interface -func (p *projection) Inputs() []logicalPlan { - return []logicalPlan{p.source} -} - -// Rewrite implements the logicalPlan interface -func (p *projection) Rewrite(inputs ...logicalPlan) error { - if len(inputs) != 1 { - return vterrors.VT13001(fmt.Sprintf("wrong number of inputs, got: %d; expected: %d", len(inputs), 1)) - } - p.source = inputs[0] - return nil -} - -// ContainsTables implements the logicalPlan interface -func (p *projection) ContainsTables() semantics.TableSet { - return p.source.ContainsTables() -} - -// OutputColumns implements the logicalPlan interface -func (p *projection) OutputColumns() []sqlparser.SelectExpr { - columns := make([]sqlparser.SelectExpr, 0, len(p.columns)) - for i, expr := range p.columns { - columns = append(columns, &sqlparser.AliasedExpr{ - Expr: expr, - As: sqlparser.NewIdentifierCI(p.columnNames[i]), - }) - } - return columns -} - // Primitive implements the logicalPlan interface func (p *projection) Primitive() engine.Primitive { if p.primitive == nil { diff --git a/go/vt/vtgate/planbuilder/route.go b/go/vt/vtgate/planbuilder/route.go index 3ad781f5235..63f6d0ea612 100644 --- a/go/vt/vtgate/planbuilder/route.go +++ b/go/vt/vtgate/planbuilder/route.go @@ -39,10 +39,6 @@ type route struct { // executed by this route. Select sqlparser.SelectStatement - // condition stores the AST condition that will be used - // to resolve the ERoute Values field. - condition sqlparser.Expr - // eroute is the primitive being built. eroute *engine.Route @@ -58,11 +54,6 @@ func (rb *route) Primitive() engine.Primitive { return rb.enginePrimitive } -// SetLimit adds a LIMIT clause to the route. -func (rb *route) SetLimit(limit *sqlparser.Limit) { - rb.Select.SetLimit(limit) -} - // Wireup implements the logicalPlan interface func (rb *route) Wireup(ctx *plancontext.PlanningContext) error { rb.prepareTheAST() @@ -110,16 +101,6 @@ func (rb *route) Wireup(ctx *plancontext.PlanningContext) error { return nil } -// ContainsTables implements the logicalPlan interface -func (rb *route) ContainsTables() semantics.TableSet { - return rb.tables -} - -// OutputColumns implements the logicalPlan interface -func (rb *route) OutputColumns() []sqlparser.SelectExpr { - return sqlparser.GetFirstSelect(rb.Select).SelectExprs -} - // prepareTheAST does minor fixups of the SELECT struct before producing the query string func (rb *route) prepareTheAST() { _ = sqlparser.Walk(func(node sqlparser.SQLNode) (bool, error) { @@ -147,19 +128,6 @@ func (rb *route) prepareTheAST() { }, rb.Select) } -// Rewrite implements the logicalPlan interface -func (rb *route) Rewrite(inputs ...logicalPlan) error { - if len(inputs) != 0 { - return vterrors.VT13001("route: wrong number of inputs") - } - return nil -} - -// Inputs implements the logicalPlan interface -func (rb *route) Inputs() []logicalPlan { - return []logicalPlan{} -} - func (rb *route) isSingleShard() bool { return rb.eroute.Opcode.IsSingleShard() } diff --git a/go/vt/vtgate/planbuilder/select.go b/go/vt/vtgate/planbuilder/select.go index a6ea8a7c8b1..20b4c914e63 100644 --- a/go/vt/vtgate/planbuilder/select.go +++ b/go/vt/vtgate/planbuilder/select.go @@ -214,7 +214,7 @@ func newBuildSelectPlan( if err != nil { return nil, nil, err } - plan = pushCommentDirectivesOnPlan(plan, selStmt) + setCommentDirectivesOnPlan(plan, selStmt) return plan, tablesUsed, err } @@ -233,10 +233,7 @@ func newBuildSelectPlan( return nil, nil, err } - if err = plan.Wireup(ctx); err != nil { - return nil, nil, err - } - return pushCommentDirectivesOnPlan(plan, selStmt), operators.TablesUsed(op), nil + return plan, operators.TablesUsed(op), nil } func createSelectOperator(ctx *plancontext.PlanningContext, selStmt sqlparser.SelectStatement, reservedVars *sqlparser.ReservedVars) (ops.Operator, error) { diff --git a/go/vt/vtgate/planbuilder/semi_join.go b/go/vt/vtgate/planbuilder/semi_join.go index 2f9f0537f0f..b12b04a1ed5 100644 --- a/go/vt/vtgate/planbuilder/semi_join.go +++ b/go/vt/vtgate/planbuilder/semi_join.go @@ -18,10 +18,7 @@ package planbuilder import ( "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" - "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" - "vitess.io/vitess/go/vt/vtgate/semantics" ) var _ logicalPlan = (*semiJoin)(nil) @@ -60,36 +57,3 @@ func (ps *semiJoin) Primitive() engine.Primitive { Cols: ps.cols, } } - -// Wireup implements the logicalPlan interface -func (ps *semiJoin) Wireup(ctx *plancontext.PlanningContext) error { - if err := ps.lhs.Wireup(ctx); err != nil { - return err - } - return ps.rhs.Wireup(ctx) -} - -// Rewrite implements the logicalPlan interface -func (ps *semiJoin) Rewrite(inputs ...logicalPlan) error { - if len(inputs) != 2 { - return vterrors.VT13001("semiJoin: wrong number of inputs") - } - ps.lhs = inputs[0] - ps.rhs = inputs[1] - return nil -} - -// ContainsTables implements the logicalPlan interface -func (ps *semiJoin) ContainsTables() semantics.TableSet { - return ps.lhs.ContainsTables().Merge(ps.rhs.ContainsTables()) -} - -// Inputs implements the logicalPlan interface -func (ps *semiJoin) Inputs() []logicalPlan { - return []logicalPlan{ps.lhs, ps.rhs} -} - -// OutputColumns implements the logicalPlan interface -func (ps *semiJoin) OutputColumns() []sqlparser.SelectExpr { - return ps.lhs.OutputColumns() -} diff --git a/go/vt/vtgate/planbuilder/simple_projection.go b/go/vt/vtgate/planbuilder/simple_projection.go index e9e8a146b59..4c29ef0ae9a 100644 --- a/go/vt/vtgate/planbuilder/simple_projection.go +++ b/go/vt/vtgate/planbuilder/simple_projection.go @@ -17,7 +17,6 @@ limitations under the License. package planbuilder import ( - "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/engine" ) @@ -42,13 +41,3 @@ func (sq *simpleProjection) Primitive() engine.Primitive { sq.eSimpleProj.Input = sq.input.Primitive() return sq.eSimpleProj } - -// OutputColumns implements the logicalPlan interface -func (sq *simpleProjection) OutputColumns() []sqlparser.SelectExpr { - exprs := make([]sqlparser.SelectExpr, 0, len(sq.eSimpleProj.Cols)) - outputCols := sq.input.OutputColumns() - for _, colID := range sq.eSimpleProj.Cols { - exprs = append(exprs, outputCols[colID]) - } - return exprs -} diff --git a/go/vt/vtgate/planbuilder/sql_calc_found_rows.go b/go/vt/vtgate/planbuilder/sql_calc_found_rows.go index 0657d6c2331..62823a8c10e 100644 --- a/go/vt/vtgate/planbuilder/sql_calc_found_rows.go +++ b/go/vt/vtgate/planbuilder/sql_calc_found_rows.go @@ -17,13 +17,7 @@ limitations under the License. package planbuilder import ( - "fmt" - - "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" - "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" - "vitess.io/vitess/go/vt/vtgate/semantics" ) var _ logicalPlan = (*sqlCalcFoundRows)(nil) @@ -32,20 +26,6 @@ type sqlCalcFoundRows struct { LimitQuery, CountQuery logicalPlan } -// Wireup implements the logicalPlan interface -func (s *sqlCalcFoundRows) Wireup(ctx *plancontext.PlanningContext) error { - err := s.LimitQuery.Wireup(ctx) - if err != nil { - return err - } - return s.CountQuery.Wireup(ctx) -} - -// ContainsTables implements the logicalPlan interface -func (s *sqlCalcFoundRows) ContainsTables() semantics.TableSet { - return s.LimitQuery.ContainsTables() -} - // Primitive implements the logicalPlan interface func (s *sqlCalcFoundRows) Primitive() engine.Primitive { countPrim := s.CountQuery.Primitive() @@ -59,23 +39,3 @@ func (s *sqlCalcFoundRows) Primitive() engine.Primitive { CountPrimitive: countPrim, } } - -// Rewrite implements the logicalPlan interface -func (s *sqlCalcFoundRows) Rewrite(inputs ...logicalPlan) error { - if len(inputs) != 2 { - return vterrors.VT13001(fmt.Sprintf("wrong number of inputs for SQL_CALC_FOUND_ROWS: %d", len(inputs))) - } - s.LimitQuery = inputs[0] - s.CountQuery = inputs[1] - return nil -} - -// Inputs implements the logicalPlan interface -func (s *sqlCalcFoundRows) Inputs() []logicalPlan { - return []logicalPlan{s.LimitQuery, s.CountQuery} -} - -// OutputColumns implements the logicalPlan interface -func (s *sqlCalcFoundRows) OutputColumns() []sqlparser.SelectExpr { - return s.LimitQuery.OutputColumns() -} diff --git a/go/vt/vtgate/planbuilder/uncorrelated_subquery.go b/go/vt/vtgate/planbuilder/uncorrelated_subquery.go index 451b89fc780..edb46e5b4fe 100644 --- a/go/vt/vtgate/planbuilder/uncorrelated_subquery.go +++ b/go/vt/vtgate/planbuilder/uncorrelated_subquery.go @@ -17,12 +17,8 @@ limitations under the License. package planbuilder import ( - "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" popcode "vitess.io/vitess/go/vt/vtgate/engine/opcode" - "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" - "vitess.io/vitess/go/vt/vtgate/semantics" ) var _ logicalPlan = (*uncorrelatedSubquery)(nil) @@ -55,36 +51,3 @@ func (ps *uncorrelatedSubquery) Primitive() engine.Primitive { ps.eSubquery.Outer = ps.outer.Primitive() return ps.eSubquery } - -// Wireup implements the logicalPlan interface -func (ps *uncorrelatedSubquery) Wireup(ctx *plancontext.PlanningContext) error { - if err := ps.outer.Wireup(ctx); err != nil { - return err - } - return ps.subquery.Wireup(ctx) -} - -// Rewrite implements the logicalPlan interface -func (ps *uncorrelatedSubquery) Rewrite(inputs ...logicalPlan) error { - if len(inputs) != 2 { - return vterrors.VT13001("uncorrelatedSubquery: wrong number of inputs") - } - ps.outer = inputs[0] - ps.subquery = inputs[1] - return nil -} - -// ContainsTables implements the logicalPlan interface -func (ps *uncorrelatedSubquery) ContainsTables() semantics.TableSet { - return ps.outer.ContainsTables().Merge(ps.subquery.ContainsTables()) -} - -// Inputs implements the logicalPlan interface -func (ps *uncorrelatedSubquery) Inputs() []logicalPlan { - return []logicalPlan{ps.outer, ps.subquery} -} - -// OutputColumns implements the logicalPlan interface -func (ps *uncorrelatedSubquery) OutputColumns() []sqlparser.SelectExpr { - return ps.outer.OutputColumns() -} diff --git a/go/vt/vtgate/planbuilder/update.go b/go/vt/vtgate/planbuilder/update.go index 6b2d492c1fa..eced4251ab3 100644 --- a/go/vt/vtgate/planbuilder/update.go +++ b/go/vt/vtgate/planbuilder/update.go @@ -54,7 +54,7 @@ func gen4UpdateStmtPlanner( if ks, tables := ctx.SemTable.SingleUnshardedKeyspace(); ks != nil { if !ctx.SemTable.ForeignKeysPresent() { plan := updateUnshardedShortcut(updStmt, ks, tables) - plan = pushCommentDirectivesOnPlan(plan, updStmt) + setCommentDirectivesOnPlan(plan, updStmt) return newPlanResult(plan.Primitive(), operators.QualifiedTables(ks, tables)...), nil } } @@ -78,14 +78,6 @@ func gen4UpdateStmtPlanner( return nil, err } - plan = pushCommentDirectivesOnPlan(plan, updStmt) - - setLockOnAllSelect(plan) - - if err := plan.Wireup(ctx); err != nil { - return nil, err - } - return newPlanResult(plan.Primitive(), operators.TablesUsed(op)...), nil } diff --git a/go/vt/vtgate/planbuilder/vindex_func.go b/go/vt/vtgate/planbuilder/vindex_func.go index 2708fb465cd..abfd2d1d9b3 100644 --- a/go/vt/vtgate/planbuilder/vindex_func.go +++ b/go/vt/vtgate/planbuilder/vindex_func.go @@ -20,8 +20,6 @@ import ( "fmt" "vitess.io/vitess/go/mysql/collations" - "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" - "vitess.io/vitess/go/vt/vtgate/semantics" "vitess.io/vitess/go/vt/vterrors" @@ -58,11 +56,6 @@ func (vf *vindexFunc) Primitive() engine.Primitive { return vf.eVindexFunc } -// Wireup implements the logicalPlan interface -func (vf *vindexFunc) Wireup(*plancontext.PlanningContext) error { - return nil -} - // SupplyProjection pushes the given aliased expression into the fields and cols slices of the // vindexFunc engine primitive. The method returns the offset of the new expression in the columns // list. @@ -105,24 +98,6 @@ func (err UnsupportedSupplyWeightString) Error() string { return fmt.Sprintf("cannot do collation on %s", err.Type) } -// Rewrite implements the logicalPlan interface -func (vf *vindexFunc) Rewrite(inputs ...logicalPlan) error { - if len(inputs) != 0 { - return vterrors.VT13001("vindexFunc: wrong number of inputs") - } - return nil -} - -// ContainsTables implements the logicalPlan interface -func (vf *vindexFunc) ContainsTables() semantics.TableSet { - return vf.tableID -} - -// Inputs implements the logicalPlan interface -func (vf *vindexFunc) Inputs() []logicalPlan { - return []logicalPlan{} -} - func vindexColumnToIndex(column *sqlparser.ColName) int { switch column.Name.String() { case "id": @@ -141,12 +116,3 @@ func vindexColumnToIndex(column *sqlparser.ColName) int { return -1 } } - -// OutputColumns implements the logicalPlan interface -func (vf *vindexFunc) OutputColumns() []sqlparser.SelectExpr { - exprs := make([]sqlparser.SelectExpr, 0, len(colnames)) - for _, field := range vf.eVindexFunc.Fields { - exprs = append(exprs, &sqlparser.AliasedExpr{Expr: sqlparser.NewColName(field.Name)}) - } - return exprs -}