From 05cb631fad25bb5c5ac84815605fd02103344de0 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 24 May 2024 07:42:08 +0200 Subject: [PATCH 01/18] refactor: clean up expression rewriting Signed-off-by: Andres Taylor --- go/vt/sqlparser/constants.go | 13 +++++++++++-- go/vt/vtgate/planbuilder/route.go | 9 +++------ go/vt/vtgate/semantics/early_rewriter.go | 2 +- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/go/vt/sqlparser/constants.go b/go/vt/sqlparser/constants.go index cba5f7823c1..b1f33184ec0 100644 --- a/go/vt/sqlparser/constants.go +++ b/go/vt/sqlparser/constants.go @@ -677,8 +677,8 @@ const ( NotRegexpOp ) -func Inverse(in ComparisonExprOperator) ComparisonExprOperator { - switch in { +func (op ComparisonExprOperator) Inverse() ComparisonExprOperator { + switch op { case EqualOp: return NotEqualOp case LessThanOp: @@ -709,6 +709,15 @@ func Inverse(in ComparisonExprOperator) ComparisonExprOperator { panic("unreachable") } +func (op ComparisonExprOperator) IsCommutative() bool { + switch op { + case EqualOp, NotEqualOp, NullSafeEqualOp: + return true + default: + return false + } +} + // Constant for Enum Type - IsExprOperator const ( IsNullOp IsExprOperator = iota diff --git a/go/vt/vtgate/planbuilder/route.go b/go/vt/vtgate/planbuilder/route.go index d4f72f0ff3a..415d678cae4 100644 --- a/go/vt/vtgate/planbuilder/route.go +++ b/go/vt/vtgate/planbuilder/route.go @@ -115,12 +115,9 @@ func (rb *route) prepareTheAST() { } case *sqlparser.ComparisonExpr: // 42 = colName -> colName = 42 - b := node.Operator == sqlparser.EqualOp - value := sqlparser.IsValue(node.Left) - name := sqlparser.IsColName(node.Right) - if b && - value && - name { + if node.Operator.IsCommutative() && + !sqlparser.IsColName(node.Left) && + sqlparser.IsColName(node.Right) { node.Left, node.Right = node.Right, node.Left } } diff --git a/go/vt/vtgate/semantics/early_rewriter.go b/go/vt/vtgate/semantics/early_rewriter.go index cb2d009f8cc..51ed110adf9 100644 --- a/go/vt/vtgate/semantics/early_rewriter.go +++ b/go/vt/vtgate/semantics/early_rewriter.go @@ -161,7 +161,7 @@ func rewriteNotExpr(cursor *sqlparser.Cursor, node *sqlparser.NotExpr) { if cmp.Operator == sqlparser.NullSafeEqualOp { return } - cmp.Operator = sqlparser.Inverse(cmp.Operator) + cmp.Operator = cmp.Operator.Inverse() cursor.Replace(cmp) } From a4a55c7c07ce79443b044b0944ce14405bf7ecd8 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 24 May 2024 08:18:21 +0200 Subject: [PATCH 02/18] refactor: stop using the Route logical plan in one context Signed-off-by: Andres Taylor --- .../planbuilder/operator_transformers.go | 18 ++--- go/vt/vtgate/planbuilder/route.go | 68 +++++++++++++++++++ go/vt/vtgate/planbuilder/select.go | 8 +++ 3 files changed, 85 insertions(+), 9 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index 31367d06b21..be8a002c28c 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -576,6 +576,10 @@ func buildRouteLogicalPlan(ctx *plancontext.PlanningContext, op *operators.Route _ = updateSelectedVindexPredicate(op.Routing) eroute, err := routeToEngineRoute(ctx, op, hints) + if err != nil { + return nil, err + } + for _, order := range op.Ordering { typ, _ := ctx.SemTable.TypeForExpr(order.AST) eroute.OrderBy = append(eroute.OrderBy, evalengine.OrderByParams{ @@ -586,19 +590,15 @@ func buildRouteLogicalPlan(ctx *plancontext.PlanningContext, op *operators.Route CollationEnv: ctx.VSchema.Environment().CollationEnv(), }) } + + prepareTheAST(stmt) + + res, err := WireupRoute(ctx, eroute, stmt) if err != nil { return nil, err } - r := &route{ - eroute: eroute, - Select: stmt, - tables: operators.TableID(op), - } - if err = r.Wireup(ctx); err != nil { - return nil, err - } - return r, nil + return &primitiveWrapper{prim: res}, nil } func buildInsertLogicalPlan( diff --git a/go/vt/vtgate/planbuilder/route.go b/go/vt/vtgate/planbuilder/route.go index 415d678cae4..513bb93370e 100644 --- a/go/vt/vtgate/planbuilder/route.go +++ b/go/vt/vtgate/planbuilder/route.go @@ -128,3 +128,71 @@ func (rb *route) prepareTheAST() { func (rb *route) isSingleShard() bool { return rb.eroute.Opcode.IsSingleShard() } + +// WireupRoute returns an engine primitive for the given route. +func WireupRoute(ctx *plancontext.PlanningContext, eroute *engine.Route, sel sqlparser.SelectStatement) (engine.Primitive, error) { + + // prepare the queries we will pass down + eroute.Query = sqlparser.String(sel) + buffer := sqlparser.NewTrackedBuffer(sqlparser.FormatImpossibleQuery) + node := buffer.WriteNode(sel) + eroute.FieldQuery = node.ParsedQuery().Query + + // if we have a planable vindex lookup, let's extract it into its own primitive + planableVindex, ok := eroute.RoutingParameters.Vindex.(vindexes.LookupPlanable) + if !ok { + return eroute, nil + } + + query, args := planableVindex.Query() + stmt, reserved, err := ctx.VSchema.Environment().Parser().Parse2(query) + if err != nil { + return nil, err + } + reservedVars := sqlparser.NewReservedVars("vtg", reserved) + + lookupPrimitive, err := gen4SelectStmtPlanner(query, querypb.ExecuteOptions_Gen4, stmt.(sqlparser.SelectStatement), reservedVars, ctx.VSchema) + if err != nil { + return nil, vterrors.Wrapf(err, "failed to plan the lookup query: [%s]", query) + } + + vdxLookup := &engine.VindexLookup{ + Opcode: eroute.Opcode, + Vindex: planableVindex, + Keyspace: eroute.Keyspace, + Values: eroute.Values, + SendTo: eroute, + Arguments: args, + Lookup: lookupPrimitive.primitive, + } + + eroute.RoutingParameters.Opcode = engine.ByDestination + eroute.RoutingParameters.Values = nil + eroute.RoutingParameters.Vindex = nil + + return vdxLookup, nil +} + +// prepareTheAST does minor fixups of the SELECT struct before producing the query string +func prepareTheAST(sel sqlparser.SelectStatement) { + _ = sqlparser.Walk(func(node sqlparser.SQLNode) (bool, error) { + switch node := node.(type) { + case *sqlparser.Select: + if len(node.SelectExprs) == 0 { + node.SelectExprs = []sqlparser.SelectExpr{ + &sqlparser.AliasedExpr{ + Expr: sqlparser.NewIntLiteral("1"), + }, + } + } + case *sqlparser.ComparisonExpr: + // 42 = colName -> colName = 42 + if node.Operator.IsCommutative() && + !sqlparser.IsColName(node.Left) && + sqlparser.IsColName(node.Right) { + node.Left, node.Right = node.Right, node.Left + } + } + return true, nil + }, sel) +} diff --git a/go/vt/vtgate/planbuilder/select.go b/go/vt/vtgate/planbuilder/select.go index d1ae02f0b86..8c18d79751b 100644 --- a/go/vt/vtgate/planbuilder/select.go +++ b/go/vt/vtgate/planbuilder/select.go @@ -262,6 +262,14 @@ func shouldRetryAfterPredicateRewriting(plan logicalPlan) bool { opcode = routePlan.eroute.Opcode sysTableTableName = routePlan.eroute.SysTableTableName sysTableTableSchema = routePlan.eroute.SysTableTableSchema + case *primitiveWrapper: + eroute, ok := routePlan.prim.(*engine.Route) + if !ok { + return false + } + opcode = eroute.Opcode + sysTableTableName = eroute.SysTableTableName + sysTableTableSchema = eroute.SysTableTableSchema default: return false } From 566372bc9c375c68d7209f0ec898e6f4eebbd597 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 24 May 2024 08:24:58 +0200 Subject: [PATCH 03/18] refactor: remove Route logical plan Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/planner.go | 26 ++--- go/vt/vtgate/planbuilder/route.go | 105 ------------------ go/vt/vtgate/planbuilder/select.go | 4 - .../planbuilder/single_sharded_shortcut.go | 19 ++-- 4 files changed, 21 insertions(+), 133 deletions(-) diff --git a/go/vt/vtgate/planbuilder/planner.go b/go/vt/vtgate/planbuilder/planner.go index b7a918260b7..e84e4d3180d 100644 --- a/go/vt/vtgate/planbuilder/planner.go +++ b/go/vt/vtgate/planbuilder/planner.go @@ -58,27 +58,27 @@ func setCommentDirectivesOnPlan(plan logicalPlan, stmt sqlparser.Statement) { 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) + setDirective(plan.prim, multiShardAutoCommit, timeout, scatterAsWarns) case *insert: - setDirective(plan.eInsert, multiShardAutoCommit, timeout) + setDirective(plan.eInsert, multiShardAutoCommit, timeout, scatterAsWarns) } } -func setDirective(prim engine.Primitive, msac bool, timeout int) { - switch edml := prim.(type) { +func setDirective(prim engine.Primitive, msac bool, timeout int, scatterAsWarns bool) { + switch prim := prim.(type) { case *engine.Insert: - edml.MultiShardAutocommit = msac - edml.QueryTimeout = timeout + prim.MultiShardAutocommit = msac + prim.QueryTimeout = timeout case *engine.Update: - edml.MultiShardAutocommit = msac - edml.QueryTimeout = timeout + prim.MultiShardAutocommit = msac + prim.QueryTimeout = timeout case *engine.Delete: - edml.MultiShardAutocommit = msac - edml.QueryTimeout = timeout + prim.MultiShardAutocommit = msac + prim.QueryTimeout = timeout + case *engine.Route: + prim.ScatterErrorsAsWarnings = scatterAsWarns + prim.QueryTimeout = timeout } } diff --git a/go/vt/vtgate/planbuilder/route.go b/go/vt/vtgate/planbuilder/route.go index 513bb93370e..e320df14416 100644 --- a/go/vt/vtgate/planbuilder/route.go +++ b/go/vt/vtgate/planbuilder/route.go @@ -22,116 +22,11 @@ import ( "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" "vitess.io/vitess/go/vt/vtgate/vindexes" ) -var _ logicalPlan = (*route)(nil) - -// route is used to build a Route primitive. -// It's used to build one of the Select routes like -// SelectScatter, etc. Portions of the original Select AST -// are moved into this node, which will be used to build -// the final SQL for this route. -type route struct { - - // Select is the AST for the query fragment that will be - // executed by this route. - Select sqlparser.SelectStatement - - // eroute is the primitive being built. - eroute *engine.Route - - // is the engine primitive we will return from the Primitive() method. Note that it could be different than eroute - enginePrimitive engine.Primitive - - // tables keeps track of which tables this route is covering - tables semantics.TableSet -} - -// Primitive implements the logicalPlan interface -func (rb *route) Primitive() engine.Primitive { - return rb.enginePrimitive -} - -// Wireup implements the logicalPlan interface -func (rb *route) Wireup(ctx *plancontext.PlanningContext) error { - rb.prepareTheAST() - - // prepare the queries we will pass down - rb.eroute.Query = sqlparser.String(rb.Select) - buffer := sqlparser.NewTrackedBuffer(sqlparser.FormatImpossibleQuery) - node := buffer.WriteNode(rb.Select) - parsedQuery := node.ParsedQuery() - rb.eroute.FieldQuery = parsedQuery.Query - - // if we have a planable vindex lookup, let's extract it into its own primitive - planableVindex, ok := rb.eroute.RoutingParameters.Vindex.(vindexes.LookupPlanable) - if !ok { - rb.enginePrimitive = rb.eroute - return nil - } - - query, args := planableVindex.Query() - stmt, reserved, err := ctx.VSchema.Environment().Parser().Parse2(query) - if err != nil { - return err - } - reservedVars := sqlparser.NewReservedVars("vtg", reserved) - - lookupPrimitive, err := gen4SelectStmtPlanner(query, querypb.ExecuteOptions_Gen4, stmt.(sqlparser.SelectStatement), reservedVars, ctx.VSchema) - if err != nil { - return vterrors.Wrapf(err, "failed to plan the lookup query: [%s]", query) - } - - rb.enginePrimitive = &engine.VindexLookup{ - Opcode: rb.eroute.Opcode, - Vindex: planableVindex, - Keyspace: rb.eroute.Keyspace, - Values: rb.eroute.Values, - SendTo: rb.eroute, - Arguments: args, - Lookup: lookupPrimitive.primitive, - } - - rb.eroute.RoutingParameters.Opcode = engine.ByDestination - rb.eroute.RoutingParameters.Values = nil - rb.eroute.RoutingParameters.Vindex = nil - - return nil -} - -// 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) { - switch node := node.(type) { - case *sqlparser.Select: - if len(node.SelectExprs) == 0 { - node.SelectExprs = []sqlparser.SelectExpr{ - &sqlparser.AliasedExpr{ - Expr: sqlparser.NewIntLiteral("1"), - }, - } - } - case *sqlparser.ComparisonExpr: - // 42 = colName -> colName = 42 - if node.Operator.IsCommutative() && - !sqlparser.IsColName(node.Left) && - sqlparser.IsColName(node.Right) { - node.Left, node.Right = node.Right, node.Left - } - } - return true, nil - }, rb.Select) -} - -func (rb *route) isSingleShard() bool { - return rb.eroute.Opcode.IsSingleShard() -} - // WireupRoute returns an engine primitive for the given route. func WireupRoute(ctx *plancontext.PlanningContext, eroute *engine.Route, sel sqlparser.SelectStatement) (engine.Primitive, error) { - // prepare the queries we will pass down eroute.Query = sqlparser.String(sel) buffer := sqlparser.NewTrackedBuffer(sqlparser.FormatImpossibleQuery) diff --git a/go/vt/vtgate/planbuilder/select.go b/go/vt/vtgate/planbuilder/select.go index 8c18d79751b..0b67620c489 100644 --- a/go/vt/vtgate/planbuilder/select.go +++ b/go/vt/vtgate/planbuilder/select.go @@ -258,10 +258,6 @@ func shouldRetryAfterPredicateRewriting(plan logicalPlan) bool { var sysTableTableSchema []evalengine.Expr switch routePlan := plan.(type) { - case *route: - opcode = routePlan.eroute.Opcode - sysTableTableName = routePlan.eroute.SysTableTableName - sysTableTableSchema = routePlan.eroute.SysTableTableSchema case *primitiveWrapper: eroute, ok := routePlan.prim.(*engine.Route) if !ok { diff --git a/go/vt/vtgate/planbuilder/single_sharded_shortcut.go b/go/vt/vtgate/planbuilder/single_sharded_shortcut.go index dea4e7bb595..b68defafe18 100644 --- a/go/vt/vtgate/planbuilder/single_sharded_shortcut.go +++ b/go/vt/vtgate/planbuilder/single_sharded_shortcut.go @@ -46,21 +46,18 @@ func selectUnshardedShortcut(ctx *plancontext.PlanningContext, stmt sqlparser.Se if err != nil { return nil, nil, err } - plan := &route{ - eroute: &engine.Route{ - RoutingParameters: &engine.RoutingParameters{ - Opcode: engine.Unsharded, - Keyspace: ks, - }, - TableName: strings.Join(escapedTableNames(tableNames), ", "), + eroute := &engine.Route{ + RoutingParameters: &engine.RoutingParameters{ + Opcode: engine.Unsharded, + Keyspace: ks, }, - Select: stmt, + TableName: strings.Join(escapedTableNames(tableNames), ", "), } - - if err := plan.Wireup(ctx); err != nil { + prim, err := WireupRoute(ctx, eroute, stmt) + if err != nil { return nil, nil, err } - return plan, operators.QualifiedTableNames(ks, tableNames), nil + return &primitiveWrapper{prim: prim}, operators.QualifiedTableNames(ks, tableNames), nil } func escapedTableNames(tableNames []sqlparser.TableName) []string { From 7a92d31d2115232c706787e0a9fecf6d35c51ac6 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 24 May 2024 08:32:58 +0200 Subject: [PATCH 04/18] refactor: remove concatenate logical plan Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/concatenate.go | 41 ------------------- .../planbuilder/operator_transformers.go | 13 +++--- 2 files changed, 6 insertions(+), 48 deletions(-) delete mode 100644 go/vt/vtgate/planbuilder/concatenate.go diff --git a/go/vt/vtgate/planbuilder/concatenate.go b/go/vt/vtgate/planbuilder/concatenate.go deleted file mode 100644 index 81cbe3d5b65..00000000000 --- a/go/vt/vtgate/planbuilder/concatenate.go +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright 2021 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/vtgate/engine" -) - -type concatenate struct { - sources []logicalPlan - - // These column offsets do not need to be typed checked - they usually contain weight_string() - // columns that are not going to be returned to the user - noNeedToTypeCheck []int -} - -var _ logicalPlan = (*concatenate)(nil) - -// Primitive implements the logicalPlan interface -func (c *concatenate) Primitive() engine.Primitive { - var sources []engine.Primitive - for _, source := range c.sources { - sources = append(sources, source.Primitive()) - } - - return engine.NewConcatenate(sources, c.noNeedToTypeCheck) -} diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index be8a002c28c..47bbaa00ecd 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -827,25 +827,24 @@ func getAllTableNames(op *operators.Route) ([]string, error) { } func transformUnionPlan(ctx *plancontext.PlanningContext, op *operators.Union) (logicalPlan, error) { - sources, err := slice.MapWithError(op.Sources, func(src operators.Operator) (logicalPlan, error) { + sources, err := slice.MapWithError(op.Sources, func(src operators.Operator) (engine.Primitive, error) { plan, err := transformToLogicalPlan(ctx, src) if err != nil { return nil, err } - return plan, nil + return plan.Primitive(), nil }) if err != nil { return nil, err } if len(sources) == 1 { - return sources[0], nil + return &primitiveWrapper{prim: sources[0]}, nil } - return &concatenate{ - sources: sources, - noNeedToTypeCheck: nil, - }, nil + return &primitiveWrapper{ + prim: engine.NewConcatenate(sources, nil), + }, nil } func transformLimit(ctx *plancontext.PlanningContext, op *operators.Limit) (logicalPlan, error) { From d09d7c5adc2260cf06d010a032206ed383f22f8a Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 24 May 2024 08:37:34 +0200 Subject: [PATCH 05/18] refactor: remove join logical plan Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/join.go | 70 ------------------- .../planbuilder/operator_transformers.go | 18 ++--- 2 files changed, 9 insertions(+), 79 deletions(-) delete mode 100644 go/vt/vtgate/planbuilder/join.go diff --git a/go/vt/vtgate/planbuilder/join.go b/go/vt/vtgate/planbuilder/join.go deleted file mode 100644 index 462b45fa00a..00000000000 --- a/go/vt/vtgate/planbuilder/join.go +++ /dev/null @@ -1,70 +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/vtgate/engine" -) - -var _ logicalPlan = (*join)(nil) - -// join is used to build a Join primitive. -// It's used to build an inner join and only used by the Gen4 planner -type join struct { - // Left and Right are the nodes for the join. - Left, Right logicalPlan - - // The Opcode tells us if this is an inner or outer join - Opcode engine.JoinOpcode - - // These are the columns that will be produced by this plan. - // Negative offsets come from the LHS, and positive from the RHS - Cols []int - - // Vars are the columns that will be sent from the LHS to the RHS - // the number is the offset on the LHS result, and the string is the bind variable name used in the RHS - Vars map[string]int - - // LHSColumns are the columns from the LHS used for the join. - // These are the same columns pushed on the LHS that are now used in the Vars field - LHSColumns []*sqlparser.ColName -} - -// Primitive implements the logicalPlan interface -func (j *join) Primitive() engine.Primitive { - return &engine.Join{ - Left: j.Left.Primitive(), - Right: j.Right.Primitive(), - Cols: j.Cols, - Vars: j.Vars, - Opcode: j.Opcode, - } -} - -type hashJoin struct { - lhs, rhs logicalPlan - inner *engine.HashJoin -} - -func (hj *hashJoin) Primitive() engine.Primitive { - lhs := hj.lhs.Primitive() - rhs := hj.rhs.Primitive() - hj.inner.Left = lhs - hj.inner.Right = rhs - return hj.inner -} diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index 47bbaa00ecd..c6a5178de70 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -479,13 +479,13 @@ func transformApplyJoinPlan(ctx *plancontext.PlanningContext, n *operators.Apply opCode = engine.LeftJoin } - return &join{ - Left: lhs, - Right: rhs, + return &primitiveWrapper{prim: &engine.Join{ + Opcode: opCode, + Left: lhs.Primitive(), + Right: rhs.Primitive(), Cols: n.Columns, Vars: n.Vars, - Opcode: opCode, - }, nil + }}, nil } func routeToEngineRoute(ctx *plancontext.PlanningContext, op *operators.Route, hints *queryHints) (*engine.Route, error) { @@ -919,10 +919,10 @@ func transformHashJoin(ctx *plancontext.PlanningContext, op *operators.HashJoin) return nil, err } - return &hashJoin{ - lhs: lhs, - rhs: rhs, - inner: &engine.HashJoin{ + return &primitiveWrapper{ + prim: &engine.HashJoin{ + Left: lhs.Primitive(), + Right: rhs.Primitive(), Opcode: joinOp, Cols: op.ColumnOffsets, LHSKey: op.LHSKeys[0], From 837d0f8c18548e914dbf899825cac8d5e43db713 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 24 May 2024 08:44:35 +0200 Subject: [PATCH 06/18] refactor: remove distinct logicalPlan Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/distinct.go | 62 ------------------- .../planbuilder/operator_transformers.go | 7 ++- 2 files changed, 6 insertions(+), 63 deletions(-) delete mode 100644 go/vt/vtgate/planbuilder/distinct.go diff --git a/go/vt/vtgate/planbuilder/distinct.go b/go/vt/vtgate/planbuilder/distinct.go deleted file mode 100644 index 2a9f58a9942..00000000000 --- a/go/vt/vtgate/planbuilder/distinct.go +++ /dev/null @@ -1,62 +0,0 @@ -/* -Copyright 2020 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/vtgate/engine" -) - -var _ logicalPlan = (*distinct)(nil) - -// distinct is the logicalPlan for engine.Distinct. -type distinct struct { - logicalPlanCommon - checkCols []engine.CheckCol - truncateColumn int - - // needToTruncate is the old way to check weight_string column and set truncation. - needToTruncate bool -} - -func newDistinct(source logicalPlan, checkCols []engine.CheckCol, truncateColumn int) logicalPlan { - return &distinct{ - logicalPlanCommon: newBuilderCommon(source), - checkCols: checkCols, - truncateColumn: truncateColumn, - } -} - -func (d *distinct) Primitive() engine.Primitive { - truncate := d.truncateColumn - if d.needToTruncate { - wsColFound := false - for _, col := range d.checkCols { - if col.WsCol != nil { - wsColFound = true - break - } - } - if wsColFound { - truncate = len(d.checkCols) - } - } - return &engine.Distinct{ - Source: d.input.Primitive(), - CheckCols: d.checkCols, - Truncate: truncate, - } -} diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index c6a5178de70..a1da72bb3da 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -319,7 +319,12 @@ func transformDistinct(ctx *plancontext.PlanningContext, op *operators.Distinct) if err != nil { return nil, err } - return newDistinct(src, op.Columns, op.Truncate), nil + + return &primitiveWrapper{prim: &engine.Distinct{ + Source: src.Primitive(), + CheckCols: op.Columns, + Truncate: op.Truncate, + }}, nil } func transformOrdering(ctx *plancontext.PlanningContext, op *operators.Ordering) (logicalPlan, error) { From f68910b2e1084f54a76d56c7e2e6402f5b66df5e Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 24 May 2024 08:47:20 +0200 Subject: [PATCH 07/18] refactor: remove dmlWithInput logicalPlan Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/dml_with_input.go | 46 ------------------- .../planbuilder/operator_transformers.go | 17 +++---- 2 files changed, 9 insertions(+), 54 deletions(-) delete mode 100644 go/vt/vtgate/planbuilder/dml_with_input.go diff --git a/go/vt/vtgate/planbuilder/dml_with_input.go b/go/vt/vtgate/planbuilder/dml_with_input.go deleted file mode 100644 index 1cf72e5ab17..00000000000 --- a/go/vt/vtgate/planbuilder/dml_with_input.go +++ /dev/null @@ -1,46 +0,0 @@ -/* -Copyright 2023 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/vtgate/engine" -) - -type dmlWithInput struct { - input logicalPlan - dmls []logicalPlan - - outputCols [][]int - bvList []map[string]int -} - -var _ logicalPlan = (*dmlWithInput)(nil) - -// Primitive implements the logicalPlan interface -func (d *dmlWithInput) Primitive() engine.Primitive { - inp := d.input.Primitive() - var dels []engine.Primitive - for _, dml := range d.dmls { - dels = append(dels, dml.Primitive()) - } - return &engine.DMLWithInput{ - DMLs: dels, - Input: inp, - OutputCols: d.outputCols, - BVList: d.bvList, - } -} diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index a1da72bb3da..a38d42a4dbe 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -88,20 +88,21 @@ func transformDMLWithInput(ctx *plancontext.PlanningContext, op *operators.DMLWi return nil, err } - var dmls []logicalPlan + var dmls []engine.Primitive for _, dml := range op.DML { del, err := transformToLogicalPlan(ctx, dml) if err != nil { return nil, err } - dmls = append(dmls, del) + dmls = append(dmls, del.Primitive()) } - return &dmlWithInput{ - input: input, - dmls: dmls, - outputCols: op.Offsets, - bvList: op.BvList, - }, nil + + return &primitiveWrapper{prim: &engine.DMLWithInput{ + DMLs: dmls, + Input: input.Primitive(), + OutputCols: op.Offsets, + BVList: op.BvList, + }}, nil } func transformUpsert(ctx *plancontext.PlanningContext, op *operators.Upsert) (logicalPlan, error) { From 97a0f6c3943128dcdc002043c4d5ca493b1e1e89 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 24 May 2024 08:52:58 +0200 Subject: [PATCH 08/18] refactor: remove filter logicalPlan Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/filter.go | 37 ------------------- .../planbuilder/operator_transformers.go | 16 +++----- 2 files changed, 6 insertions(+), 47 deletions(-) delete mode 100644 go/vt/vtgate/planbuilder/filter.go diff --git a/go/vt/vtgate/planbuilder/filter.go b/go/vt/vtgate/planbuilder/filter.go deleted file mode 100644 index c3686380446..00000000000 --- a/go/vt/vtgate/planbuilder/filter.go +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright 2021 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/vtgate/engine" -) - -type ( - // filter is the logicalPlan for engine.Filter. - filter struct { - logicalPlanCommon - efilter *engine.Filter - } -) - -var _ logicalPlan = (*filter)(nil) - -// Primitive implements the logicalPlan interface -func (l *filter) Primitive() engine.Primitive { - l.efilter.Input = l.input.Primitive() - return l.efilter -} diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index a38d42a4dbe..f3f3698bbe8 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -455,20 +455,16 @@ func transformFilter(ctx *plancontext.PlanningContext, op *operators.Filter) (lo } predicate := op.PredicateWithOffsets - ast := ctx.SemTable.AndExpressions(op.Predicates...) - if predicate == nil { panic("this should have already been done") } - return &filter{ - logicalPlanCommon: newBuilderCommon(plan), - efilter: &engine.Filter{ - Predicate: predicate, - ASTPredicate: ast, - Truncate: op.Truncate, - }, - }, nil + return &primitiveWrapper{prim: &engine.Filter{ + Input: plan.Primitive(), + Predicate: predicate, + ASTPredicate: ctx.SemTable.AndExpressions(op.Predicates...), + Truncate: op.Truncate, + }}, nil } func transformApplyJoinPlan(ctx *plancontext.PlanningContext, n *operators.ApplyJoin) (logicalPlan, error) { From cae671d428b59bb6ddca6d86412df713a4214a01 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 24 May 2024 09:16:53 +0200 Subject: [PATCH 09/18] refactor: remove fkVerify, fkCascade and insert logicalPlan Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/fk_cascade.go | 48 ---------------- go/vt/vtgate/planbuilder/fk_verify.go | 57 ------------------- go/vt/vtgate/planbuilder/insert.go | 19 +------ .../planbuilder/operator_transformers.go | 48 +++++++++++----- go/vt/vtgate/planbuilder/planner.go | 2 - 5 files changed, 34 insertions(+), 140 deletions(-) delete mode 100644 go/vt/vtgate/planbuilder/fk_cascade.go delete mode 100644 go/vt/vtgate/planbuilder/fk_verify.go diff --git a/go/vt/vtgate/planbuilder/fk_cascade.go b/go/vt/vtgate/planbuilder/fk_cascade.go deleted file mode 100644 index f2ca67ef5d0..00000000000 --- a/go/vt/vtgate/planbuilder/fk_cascade.go +++ /dev/null @@ -1,48 +0,0 @@ -/* -Copyright 2023 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/vtgate/engine" -) - -var _ logicalPlan = (*fkCascade)(nil) - -// fkCascade is the logicalPlan for engine.FkCascade. -type fkCascade struct { - parent logicalPlan - selection logicalPlan - children []*engine.FkChild -} - -// newFkCascade builds a new fkCascade. -func newFkCascade(parent, selection logicalPlan, children []*engine.FkChild) *fkCascade { - return &fkCascade{ - parent: parent, - selection: selection, - children: children, - } -} - -// Primitive implements the logicalPlan interface -func (fkc *fkCascade) Primitive() engine.Primitive { - return &engine.FkCascade{ - Parent: fkc.parent.Primitive(), - Selection: fkc.selection.Primitive(), - Children: fkc.children, - } -} diff --git a/go/vt/vtgate/planbuilder/fk_verify.go b/go/vt/vtgate/planbuilder/fk_verify.go deleted file mode 100644 index 206bad90fea..00000000000 --- a/go/vt/vtgate/planbuilder/fk_verify.go +++ /dev/null @@ -1,57 +0,0 @@ -/* -Copyright 2023 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/vtgate/engine" -) - -var _ logicalPlan = (*fkVerify)(nil) - -type verifyLP struct { - verify logicalPlan - typ string -} - -// fkVerify is the logicalPlan for engine.FkVerify. -type fkVerify struct { - input logicalPlan - verify []*verifyLP -} - -// newFkVerify builds a new fkVerify. -func newFkVerify(input logicalPlan, verify []*verifyLP) *fkVerify { - return &fkVerify{ - input: input, - verify: verify, - } -} - -// Primitive implements the logicalPlan interface -func (fkc *fkVerify) Primitive() engine.Primitive { - var verify []*engine.Verify - for _, v := range fkc.verify { - verify = append(verify, &engine.Verify{ - Exec: v.verify.Primitive(), - Typ: v.typ, - }) - } - return &engine.FkVerify{ - Exec: fkc.input.Primitive(), - Verify: verify, - } -} diff --git a/go/vt/vtgate/planbuilder/insert.go b/go/vt/vtgate/planbuilder/insert.go index e674850c753..d1cc07712bf 100644 --- a/go/vt/vtgate/planbuilder/insert.go +++ b/go/vt/vtgate/planbuilder/insert.go @@ -99,22 +99,5 @@ func insertUnshardedShortcut(stmt *sqlparser.Insert, ks *vindexes.Keyspace, tabl }, } eIns.Query = generateQuery(stmt) - return &insert{eInsert: eIns} -} - -type insert struct { - eInsert *engine.Insert - eInsertSelect *engine.InsertSelect - source logicalPlan -} - -var _ logicalPlan = (*insert)(nil) - -func (i *insert) Primitive() engine.Primitive { - if i.source == nil { - return i.eInsert - } - input := i.source.Primitive() - i.eInsertSelect.Input = input - return i.eInsertSelect + return &primitiveWrapper{prim: eIns} } diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index f3f3698bbe8..d950dcfd7bd 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -123,8 +123,12 @@ func transformOneUpsert(ctx *plancontext.PlanningContext, source operators.Upser if err != nil { return } - if ins, ok := iLp.(*insert); ok { - ins.eInsert.PreventAutoCommit = true + wrap, ok := iLp.(*primitiveWrapper) + if ok { + ins, ok := wrap.prim.(*engine.Insert) + if ok { + ins.PreventAutoCommit = true + } } uLp, err = transformToLogicalPlan(ctx, source.Update) return @@ -137,8 +141,12 @@ func transformSequential(ctx *plancontext.PlanningContext, op *operators.Sequent if err != nil { return nil, err } - if ins, ok := lp.(*insert); ok { - ins.eInsert.PreventAutoCommit = true + wrap, ok := lp.(*primitiveWrapper) + if ok { + ins, ok := wrap.prim.(*engine.Insert) + if ok { + ins.PreventAutoCommit = true + } } lps = append(lps, lp) } @@ -174,7 +182,6 @@ func transformInsertionSelection(ctx *plancontext.PlanningContext, op *operators }, VindexValueOffset: ins.VindexValueOffset, } - lp := &insert{eInsertSelect: eins} eins.Prefix, _, eins.Suffix = generateInsertShardedQuery(ins.AST) @@ -182,9 +189,9 @@ func transformInsertionSelection(ctx *plancontext.PlanningContext, op *operators if err != nil { return nil, err } - lp.source = selectionPlan - return lp, nil + eins.Input = selectionPlan.Primitive() + return &primitiveWrapper{prim: eins}, nil } // transformFkCascade transforms a FkCascade operator into a logical plan. @@ -220,7 +227,13 @@ func transformFkCascade(ctx *plancontext.PlanningContext, fkc *operators.FkCasca }) } - return newFkCascade(parentLP, selLP, children), nil + return &primitiveWrapper{ + prim: &engine.FkCascade{ + Selection: selLP.Primitive(), + Children: children, + Parent: parentLP.Primitive(), + }, + }, nil } func transformSubQuery(ctx *plancontext.PlanningContext, op *operators.SubQuery) (logicalPlan, error) { @@ -259,19 +272,25 @@ func transformFkVerify(ctx *plancontext.PlanningContext, fkv *operators.FkVerify ctx.SemTable = nil // Go over the children and convert them to Primitives too. - var verify []*verifyLP + var verify []*engine.Verify for _, v := range fkv.Verify { lp, err := transformToLogicalPlan(ctx, v.Op) if err != nil { return nil, err } - verify = append(verify, &verifyLP{ - verify: lp, - typ: v.Typ, + verify = append(verify, &engine.Verify{ + Exec: lp.Primitive(), + Typ: v.Typ, }) } - return newFkVerify(inputLP, verify), nil + return &primitiveWrapper{ + prim: &engine.FkVerify{ + Verify: verify, + Exec: inputLP.Primitive(), + }, + }, nil + } func transformAggregator(ctx *plancontext.PlanningContext, op *operators.Aggregator) (logicalPlan, error) { @@ -626,7 +645,6 @@ func buildInsertLogicalPlan( InsertCommon: ic, VindexValues: ins.VindexValues, } - lp := &insert{eInsert: eins} // we would need to generate the query on the fly. The only exception here is // when unsharded query with autoincrement for that there is no input operator. @@ -638,7 +656,7 @@ func buildInsertLogicalPlan( } eins.Query = generateQuery(stmt) - return lp, nil + return &primitiveWrapper{prim: eins}, nil } func mapToInsertOpCode(code engine.Opcode) engine.InsertOpcode { diff --git a/go/vt/vtgate/planbuilder/planner.go b/go/vt/vtgate/planbuilder/planner.go index e84e4d3180d..e4eab447115 100644 --- a/go/vt/vtgate/planbuilder/planner.go +++ b/go/vt/vtgate/planbuilder/planner.go @@ -60,8 +60,6 @@ func setCommentDirectivesOnPlan(plan logicalPlan, stmt sqlparser.Statement) { switch plan := plan.(type) { case *primitiveWrapper: setDirective(plan.prim, multiShardAutoCommit, timeout, scatterAsWarns) - case *insert: - setDirective(plan.eInsert, multiShardAutoCommit, timeout, scatterAsWarns) } } From 3bc7c5de3d6ffe3177b5f6732bb1f8176f237197 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 24 May 2024 09:30:34 +0200 Subject: [PATCH 10/18] refactor: remove limit, memorySort, mergeSort and orderedAggregate logicalPlan Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/limit.go | 47 ---------- go/vt/vtgate/planbuilder/memory_sort.go | 47 ---------- go/vt/vtgate/planbuilder/merge_sort.go | 47 ---------- .../planbuilder/operator_transformers.go | 56 +++++++----- go/vt/vtgate/planbuilder/ordered_aggregate.go | 91 ------------------- 5 files changed, 33 insertions(+), 255 deletions(-) delete mode 100644 go/vt/vtgate/planbuilder/limit.go delete mode 100644 go/vt/vtgate/planbuilder/memory_sort.go delete mode 100644 go/vt/vtgate/planbuilder/merge_sort.go delete mode 100644 go/vt/vtgate/planbuilder/ordered_aggregate.go diff --git a/go/vt/vtgate/planbuilder/limit.go b/go/vt/vtgate/planbuilder/limit.go deleted file mode 100644 index 5cfd27dfe06..00000000000 --- a/go/vt/vtgate/planbuilder/limit.go +++ /dev/null @@ -1,47 +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/vtgate/engine" -) - -var _ logicalPlan = (*limit)(nil) - -// limit is the logicalPlan for engine.Limit. -// This gets built if a limit needs to be applied -// after rows are returned from an underlying -// operation. Since a limit is the final operation -// of a SELECT, most pushes are not applicable. -type limit struct { - logicalPlanCommon - elimit *engine.Limit -} - -// newLimit builds a new limit. -func newLimit(plan logicalPlan) *limit { - return &limit{ - logicalPlanCommon: newBuilderCommon(plan), - elimit: &engine.Limit{}, - } -} - -// Primitive implements the logicalPlan interface -func (l *limit) Primitive() engine.Primitive { - l.elimit.Input = l.input.Primitive() - return l.elimit -} diff --git a/go/vt/vtgate/planbuilder/memory_sort.go b/go/vt/vtgate/planbuilder/memory_sort.go deleted file mode 100644 index e1d3cf311dc..00000000000 --- a/go/vt/vtgate/planbuilder/memory_sort.go +++ /dev/null @@ -1,47 +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/vterrors" - - "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vtgate/engine" -) - -var _ logicalPlan = (*memorySort)(nil) - -// memorySort is the logicalPlan for engine.Limit. -// This gets built if a limit needs to be applied -// after rows are returned from an underlying -// operation. Since a limit is the final operation -// of a SELECT, most pushes are not applicable. -type memorySort struct { - resultsBuilder - eMemorySort *engine.MemorySort -} - -// Primitive implements the logicalPlan interface -func (ms *memorySort) Primitive() engine.Primitive { - ms.eMemorySort.Input = ms.input.Primitive() - return ms.eMemorySort -} - -// SetLimit implements the logicalPlan interface -func (ms *memorySort) SetLimit(limit *sqlparser.Limit) error { - return vterrors.VT13001("memorySort.Limit: unreachable") -} diff --git a/go/vt/vtgate/planbuilder/merge_sort.go b/go/vt/vtgate/planbuilder/merge_sort.go deleted file mode 100644 index edca9194ccf..00000000000 --- a/go/vt/vtgate/planbuilder/merge_sort.go +++ /dev/null @@ -1,47 +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/vtgate/engine" -) - -var _ logicalPlan = (*mergeSort)(nil) - -// mergeSort is a pseudo-primitive. It amends the -// the underlying Route to perform a merge sort. -// It's differentiated as a separate primitive -// because some operations cannot be pushed down, -// which would otherwise be possible with a simple route. -// Since ORDER BY happens near the end of the SQL processing, -// most functions of this primitive are unreachable. -type mergeSort struct { - resultsBuilder - truncateColumnCount int -} - -// SetTruncateColumnCount satisfies the truncater interface. -// This function records the truncate column count and sets -// it later on the eroute during wire-up phase. -func (ms *mergeSort) SetTruncateColumnCount(count int) { - ms.truncateColumnCount = count -} - -// Primitive implements the logicalPlan interface -func (ms *mergeSort) Primitive() engine.Primitive { - return ms.input.Primitive() -} diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index d950dcfd7bd..afb76274435 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -297,15 +297,13 @@ func transformAggregator(ctx *plancontext.PlanningContext, op *operators.Aggrega if op.WithRollup { return nil, vterrors.VT12001("GROUP BY WITH ROLLUP not supported for sharded queries") } - plan, err := transformToLogicalPlan(ctx, op.Source) + src, err := transformToLogicalPlan(ctx, op.Source) if err != nil { return nil, err } - oa := &orderedAggregate{ - resultsBuilder: newResultsBuilder(plan, nil), - collationEnv: ctx.VSchema.Environment().CollationEnv(), - } + var aggregates []*engine.AggregateParams + var groupByKeys []*engine.GroupByParams for _, aggr := range op.Aggregations { if aggr.OpCode == opcode.AggregateUnassigned { @@ -317,11 +315,12 @@ func transformAggregator(ctx *plancontext.PlanningContext, op *operators.Aggrega aggrParam.OrigOpcode = aggr.OriginalOpCode aggrParam.WCol = aggr.WSOffset aggrParam.Type = aggr.GetTypeCollation(ctx) - oa.aggregates = append(oa.aggregates, aggrParam) + aggregates = append(aggregates, aggrParam) } + for _, groupBy := range op.Grouping { typ, _ := ctx.SemTable.TypeForExpr(groupBy.Inner) - oa.groupByKeys = append(oa.groupByKeys, &engine.GroupByParams{ + groupByKeys = append(groupByKeys, &engine.GroupByParams{ KeyCol: groupBy.ColOffset, WeightStringCol: groupBy.WSOffset, Expr: groupBy.Inner, @@ -330,8 +329,21 @@ func transformAggregator(ctx *plancontext.PlanningContext, op *operators.Aggrega }) } - oa.truncateColumnCount = op.ResultColumns - return oa, nil + if len(groupByKeys) == 0 { + return &primitiveWrapper{prim: &engine.ScalarAggregate{ + Aggregates: aggregates, + TruncateColumnCount: op.ResultColumns, + Input: src.Primitive(), + }}, nil + } + + return &primitiveWrapper{&engine.OrderedAggregate{ + Aggregates: aggregates, + GroupByKeys: groupByKeys, + TruncateColumnCount: op.ResultColumns, + Input: src.Primitive(), + CollationEnv: ctx.VSchema.Environment().CollationEnv(), + }}, nil } func transformDistinct(ctx *plancontext.PlanningContext, op *operators.Distinct) (logicalPlan, error) { @@ -357,17 +369,14 @@ func transformOrdering(ctx *plancontext.PlanningContext, op *operators.Ordering) } func createMemorySort(ctx *plancontext.PlanningContext, src logicalPlan, ordering *operators.Ordering) (logicalPlan, error) { - primitive := &engine.MemorySort{ + prim := &engine.MemorySort{ + Input: src.Primitive(), TruncateColumnCount: ordering.ResultColumns, } - ms := &memorySort{ - resultsBuilder: newResultsBuilder(src, primitive), - eMemorySort: primitive, - } for idx, order := range ordering.Order { typ, _ := ctx.SemTable.TypeForExpr(order.SimplifiedExpr) - ms.eMemorySort.OrderBy = append(ms.eMemorySort.OrderBy, evalengine.OrderByParams{ + prim.OrderBy = append(prim.OrderBy, evalengine.OrderByParams{ Col: ordering.Offset[idx], WeightStringCol: ordering.WOffset[idx], Desc: order.Inner.Direction == sqlparser.DescOrder, @@ -376,7 +385,7 @@ func createMemorySort(ctx *plancontext.PlanningContext, src logicalPlan, orderin }) } - return ms, nil + return &primitiveWrapper{prim}, nil } func transformProjection(ctx *plancontext.PlanningContext, op *operators.Projection) (logicalPlan, error) { @@ -877,26 +886,27 @@ func transformLimit(ctx *plancontext.PlanningContext, op *operators.Limit) (logi } func createLimit(input logicalPlan, limit *sqlparser.Limit, env *vtenv.Environment, coll collations.ID) (logicalPlan, error) { - plan := newLimit(input) cfg := &evalengine.Config{ Collation: coll, Environment: env, } - pv, err := evalengine.Translate(limit.Rowcount, cfg) + count, err := evalengine.Translate(limit.Rowcount, cfg) if err != nil { return nil, vterrors.Wrap(err, "unexpected expression in LIMIT") } - plan.elimit.Count = pv - + var offset evalengine.Expr if limit.Offset != nil { - pv, err = evalengine.Translate(limit.Offset, cfg) + offset, err = evalengine.Translate(limit.Offset, cfg) if err != nil { return nil, vterrors.Wrap(err, "unexpected expression in OFFSET") } - plan.elimit.Offset = pv } - return plan, nil + return &primitiveWrapper{prim: &engine.Limit{ + Count: count, + Offset: offset, + Input: input.Primitive(), + }}, nil } func transformHashJoin(ctx *plancontext.PlanningContext, op *operators.HashJoin) (logicalPlan, error) { diff --git a/go/vt/vtgate/planbuilder/ordered_aggregate.go b/go/vt/vtgate/planbuilder/ordered_aggregate.go deleted file mode 100644 index c6a37c8decb..00000000000 --- a/go/vt/vtgate/planbuilder/ordered_aggregate.go +++ /dev/null @@ -1,91 +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/mysql/collations" - "vitess.io/vitess/go/vt/vtgate/engine" -) - -var _ logicalPlan = (*orderedAggregate)(nil) - -// orderedAggregate is the logicalPlan for engine.OrderedAggregate. -// This gets built if there are aggregations on a SelectScatter -// route. The primitive requests the underlying route to order -// the results by the grouping columns. This will allow the -// engine code to aggregate the results as they come. -// For example: 'select col1, col2, count(*) from t group by col1, col2' -// will be sent to the scatter route as: -// 'select col1, col2, count(*) from t group by col1, col2 order by col1, col2` -// The orderAggregate primitive built for this will be: -// -// &engine.OrderedAggregate { -// // Aggregates has one column. It computes the count -// // using column 2 of the underlying route. -// Aggregates: []AggregateParams{{ -// Opcode: AggregateCount, -// Col: 2, -// }}, -// -// // Keys has the two group by values for col1 and col2. -// // The column numbers are from the underlying route. -// // These values will be used to perform the grouping -// // of the ordered results as they come from the underlying -// // route. -// Keys: []int{0, 1}, -// Input: (Scatter Route with the order by request), -// } -type orderedAggregate struct { - resultsBuilder - - // aggregates specifies the aggregation parameters for each - // aggregation function: function opcode and input column number. - aggregates []*engine.AggregateParams - - // groupByKeys specifies the input values that must be used for - // the aggregation key. - groupByKeys []*engine.GroupByParams - - truncateColumnCount int - - collationEnv *collations.Environment -} - -// Primitive implements the logicalPlan interface -func (oa *orderedAggregate) Primitive() engine.Primitive { - input := oa.input.Primitive() - if len(oa.groupByKeys) == 0 { - return &engine.ScalarAggregate{ - Aggregates: oa.aggregates, - TruncateColumnCount: oa.truncateColumnCount, - Input: input, - } - } - - return &engine.OrderedAggregate{ - Aggregates: oa.aggregates, - GroupByKeys: oa.groupByKeys, - TruncateColumnCount: oa.truncateColumnCount, - Input: input, - CollationEnv: oa.collationEnv, - } -} - -// SetTruncateColumnCount sets the truncate column count. -func (oa *orderedAggregate) SetTruncateColumnCount(count int) { - oa.truncateColumnCount = count -} From 6c9fce8183ea69c1a33c04f5620402c4e334906d Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 24 May 2024 09:36:54 +0200 Subject: [PATCH 11/18] refactor: remove unused field Signed-off-by: Andres Taylor --- go/vt/vtgate/engine/cached_size.go | 2 -- go/vt/vtgate/engine/ordered_aggregate.go | 6 ++-- go/vt/vtgate/engine/update_test.go | 28 ------------------- .../planbuilder/operator_transformers.go | 1 - go/vt/vtgate/planbuilder/show.go | 1 - .../tabletmanager/vdiff/table_differ.go | 7 ++--- go/vt/wrangler/vdiff.go | 7 ++--- go/vt/wrangler/vdiff_test.go | 5 ++-- 8 files changed, 10 insertions(+), 47 deletions(-) diff --git a/go/vt/vtgate/engine/cached_size.go b/go/vt/vtgate/engine/cached_size.go index f0354e9e726..8b12774fc43 100644 --- a/go/vt/vtgate/engine/cached_size.go +++ b/go/vt/vtgate/engine/cached_size.go @@ -793,8 +793,6 @@ func (cached *OrderedAggregate) CachedSize(alloc bool) int64 { if cc, ok := cached.Input.(cachedObject); ok { size += cc.CachedSize(true) } - // field CollationEnv *vitess.io/vitess/go/mysql/collations.Environment - size += cached.CollationEnv.CachedSize(true) return size } func (cached *Plan) CachedSize(alloc bool) int64 { diff --git a/go/vt/vtgate/engine/ordered_aggregate.go b/go/vt/vtgate/engine/ordered_aggregate.go index 5a72bdf4501..f02fb1b8002 100644 --- a/go/vt/vtgate/engine/ordered_aggregate.go +++ b/go/vt/vtgate/engine/ordered_aggregate.go @@ -51,8 +51,6 @@ type OrderedAggregate struct { // Input is the primitive that will feed into this Primitive. Input Primitive - - CollationEnv *collations.Environment } // GroupByParams specify the grouping key to be used. @@ -344,14 +342,14 @@ func (oa *OrderedAggregate) nextGroupBy(currentKey, nextRow []sqltypes.Value) (n return nextRow, true, nil } - cmp, err := evalengine.NullsafeCompare(v1, v2, oa.CollationEnv, gb.Type.Collation(), gb.Type.Values()) + cmp, err := evalengine.NullsafeCompare(v1, v2, gb.CollationEnv, gb.Type.Collation(), gb.Type.Values()) if err != nil { _, isCollationErr := err.(evalengine.UnsupportedCollationError) if !isCollationErr || gb.WeightStringCol == -1 { return nil, false, err } gb.KeyCol = gb.WeightStringCol - cmp, err = evalengine.NullsafeCompare(currentKey[gb.WeightStringCol], nextRow[gb.WeightStringCol], oa.CollationEnv, gb.Type.Collation(), gb.Type.Values()) + cmp, err = evalengine.NullsafeCompare(currentKey[gb.WeightStringCol], nextRow[gb.WeightStringCol], gb.CollationEnv, gb.Type.Collation(), gb.Type.Values()) if err != nil { return nil, false, err } diff --git a/go/vt/vtgate/engine/update_test.go b/go/vt/vtgate/engine/update_test.go index eab2742fc15..eb6af5a5299 100644 --- a/go/vt/vtgate/engine/update_test.go +++ b/go/vt/vtgate/engine/update_test.go @@ -209,34 +209,6 @@ func TestUpdateEqualNoRoute(t *testing.T) { }) } -func TestUpdateEqualNoScatter(t *testing.T) { - t.Skip("planner does not produces this plan anymore") - vindex, _ := vindexes.CreateVindex("lookup_unique", "", map[string]string{ - "table": "lkp", - "from": "from", - "to": "toc", - "write_only": "true", - }) - upd := &Update{ - DML: &DML{ - RoutingParameters: &RoutingParameters{ - Opcode: Equal, - Keyspace: &vindexes.Keyspace{ - Name: "ks", - Sharded: true, - }, - Vindex: vindex, - Values: []evalengine.Expr{evalengine.NewLiteralInt(1)}, - }, - Query: "dummy_update", - }, - } - - vc := newDMLTestVCursor("0") - _, err := upd.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) - require.EqualError(t, err, `cannot map vindex to unique keyspace id: DestinationKeyRange(-)`) -} - func TestUpdateEqualChangedVindex(t *testing.T) { ks := buildTestVSchema().Keyspaces["sharded"] upd := &Update{ diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index afb76274435..7d713158ec4 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -342,7 +342,6 @@ func transformAggregator(ctx *plancontext.PlanningContext, op *operators.Aggrega GroupByKeys: groupByKeys, TruncateColumnCount: op.ResultColumns, Input: src.Primitive(), - CollationEnv: ctx.VSchema.Environment().CollationEnv(), }}, nil } diff --git a/go/vt/vtgate/planbuilder/show.go b/go/vt/vtgate/planbuilder/show.go index 1830f197fa8..734885c9dd9 100644 --- a/go/vt/vtgate/planbuilder/show.go +++ b/go/vt/vtgate/planbuilder/show.go @@ -565,7 +565,6 @@ func buildShowVGtidPlan(show *sqlparser.ShowBasic, vschema plancontext.VSchema) }, TruncateColumnCount: 2, Input: send, - CollationEnv: vschema.Environment().CollationEnv(), }, nil } diff --git a/go/vt/vttablet/tabletmanager/vdiff/table_differ.go b/go/vt/vttablet/tabletmanager/vdiff/table_differ.go index f6550cc01cd..a98a3ce90f9 100644 --- a/go/vt/vttablet/tabletmanager/vdiff/table_differ.go +++ b/go/vt/vttablet/tabletmanager/vdiff/table_differ.go @@ -478,10 +478,9 @@ func (td *tableDiffer) setupRowSorters() { // the results, which engine.OrderedAggregate can do. if len(td.tablePlan.aggregates) != 0 { td.sourcePrimitive = &engine.OrderedAggregate{ - Aggregates: td.tablePlan.aggregates, - GroupByKeys: pkColsToGroupByParams(td.tablePlan.pkCols, td.wd.collationEnv), - Input: td.sourcePrimitive, - CollationEnv: td.wd.collationEnv, + Aggregates: td.tablePlan.aggregates, + GroupByKeys: pkColsToGroupByParams(td.tablePlan.pkCols, td.wd.collationEnv), + Input: td.sourcePrimitive, } } } diff --git a/go/vt/wrangler/vdiff.go b/go/vt/wrangler/vdiff.go index 2e9529070f6..4caad42ce1f 100644 --- a/go/vt/wrangler/vdiff.go +++ b/go/vt/wrangler/vdiff.go @@ -773,10 +773,9 @@ func (df *vdiff) buildTablePlan(table *tabletmanagerdatapb.TableDefinition, quer // the results, which engine.OrderedAggregate can do. if len(aggregates) != 0 { td.sourcePrimitive = &engine.OrderedAggregate{ - Aggregates: aggregates, - GroupByKeys: pkColsToGroupByParams(td.pkCols, td.collationEnv), - Input: td.sourcePrimitive, - CollationEnv: df.env.CollationEnv(), + Aggregates: aggregates, + GroupByKeys: pkColsToGroupByParams(td.pkCols, td.collationEnv), + Input: td.sourcePrimitive, } } diff --git a/go/vt/wrangler/vdiff_test.go b/go/vt/wrangler/vdiff_test.go index 87988c5fd7e..3ac6edb373c 100644 --- a/go/vt/wrangler/vdiff_test.go +++ b/go/vt/wrangler/vdiff_test.go @@ -441,9 +441,8 @@ func TestVDiffPlanSuccess(t *testing.T) { engine.NewAggregateParam(opcode.AggregateSum, 2, "", collationEnv), engine.NewAggregateParam(opcode.AggregateSum, 3, "", collationEnv), }, - GroupByKeys: []*engine.GroupByParams{{KeyCol: 0, WeightStringCol: -1, CollationEnv: collations.MySQL8()}}, - Input: newMergeSorter(nil, []compareColInfo{{0, collations.Unknown, nil, true}}, collationEnv), - CollationEnv: collationEnv, + GroupByKeys: []*engine.GroupByParams{{KeyCol: 0, WeightStringCol: -1, CollationEnv: collations.MySQL8()}}, + Input: newMergeSorter(nil, []compareColInfo{{0, collations.Unknown, nil, true}}, collationEnv), }, targetPrimitive: newMergeSorter(nil, []compareColInfo{{0, collations.Unknown, nil, true}}, collationEnv), collationEnv: collationEnv, From d6d99e4aa13951f8f3dfab6daf137d635ab860e3 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 24 May 2024 09:55:35 +0200 Subject: [PATCH 12/18] refactor: remove projection and semiJoin logicalPlan Signed-off-by: Andres Taylor --- go/vt/vtgate/engine/cached_size.go | 6 +- go/vt/vtgate/engine/semi_join.go | 48 ++------------- go/vt/vtgate/engine/semi_join_test.go | 2 - go/vt/vtgate/planbuilder/logical_plan.go | 16 ----- .../planbuilder/operator_transformers.go | 21 ++++--- go/vt/vtgate/planbuilder/projection.go | 37 ------------ go/vt/vtgate/planbuilder/semi_join.go | 59 ------------------- 7 files changed, 16 insertions(+), 173 deletions(-) delete mode 100644 go/vt/vtgate/planbuilder/projection.go delete mode 100644 go/vt/vtgate/planbuilder/semi_join.go diff --git a/go/vt/vtgate/engine/cached_size.go b/go/vt/vtgate/engine/cached_size.go index 8b12774fc43..e65ff61a9f6 100644 --- a/go/vt/vtgate/engine/cached_size.go +++ b/go/vt/vtgate/engine/cached_size.go @@ -1074,7 +1074,7 @@ func (cached *SemiJoin) CachedSize(alloc bool) int64 { } size := int64(0) if alloc { - size += int64(64) + size += int64(48) } // field Left vitess.io/vitess/go/vt/vtgate/engine.Primitive if cc, ok := cached.Left.(cachedObject); ok { @@ -1084,10 +1084,6 @@ func (cached *SemiJoin) CachedSize(alloc bool) int64 { if cc, ok := cached.Right.(cachedObject); ok { size += cc.CachedSize(true) } - // field Cols []int - { - size += hack.RuntimeAllocSize(int64(cap(cached.Cols)) * int64(8)) - } // field Vars map[string]int if cached.Vars != nil { size += int64(48) diff --git a/go/vt/vtgate/engine/semi_join.go b/go/vt/vtgate/engine/semi_join.go index 8ab0465249c..de8eeef5a32 100644 --- a/go/vt/vtgate/engine/semi_join.go +++ b/go/vt/vtgate/engine/semi_join.go @@ -18,8 +18,6 @@ package engine import ( "context" - "fmt" - "strings" "vitess.io/vitess/go/sqltypes" querypb "vitess.io/vitess/go/vt/proto/query" @@ -33,14 +31,6 @@ type SemiJoin struct { // of the SemiJoin. They can be any primitive. Left, Right Primitive `json:",omitempty"` - // Cols defines which columns from the left - // results should be used to build the - // return result. For results coming from the - // left query, the index values go as -1, -2, etc. - // If Cols is {-1, -2}, it means that - // the returned result will be {Left0, Left1}. - Cols []int `json:",omitempty"` - // Vars defines the list of SemiJoinVars that need to // be built from the LHS result before invoking // the RHS subquery. @@ -54,7 +44,7 @@ func (jn *SemiJoin) TryExecute(ctx context.Context, vcursor VCursor, bindVars ma if err != nil { return nil, err } - result := &sqltypes.Result{Fields: projectFields(lresult.Fields, jn.Cols)} + result := &sqltypes.Result{Fields: lresult.Fields} for _, lrow := range lresult.Rows { for k, col := range jn.Vars { joinVars[k] = sqltypes.ValueBindVariable(lrow[col]) @@ -64,7 +54,7 @@ func (jn *SemiJoin) TryExecute(ctx context.Context, vcursor VCursor, bindVars ma return nil, err } if len(rresult.Rows) > 0 { - result.Rows = append(result.Rows, projectRows(lrow, jn.Cols)) + result.Rows = append(result.Rows, lrow) } } return result, nil @@ -74,7 +64,7 @@ func (jn *SemiJoin) TryExecute(ctx context.Context, vcursor VCursor, bindVars ma func (jn *SemiJoin) TryStreamExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool, callback func(*sqltypes.Result) error) error { joinVars := make(map[string]*querypb.BindVariable) err := vcursor.StreamExecutePrimitive(ctx, jn.Left, bindVars, wantfields, func(lresult *sqltypes.Result) error { - result := &sqltypes.Result{Fields: projectFields(lresult.Fields, jn.Cols)} + result := &sqltypes.Result{Fields: lresult.Fields} for _, lrow := range lresult.Rows { for k, col := range jn.Vars { joinVars[k] = sqltypes.ValueBindVariable(lrow[col]) @@ -82,7 +72,7 @@ func (jn *SemiJoin) TryStreamExecute(ctx context.Context, vcursor VCursor, bindV rowAdded := false err := vcursor.StreamExecutePrimitive(ctx, jn.Right, combineVars(bindVars, joinVars), false, func(rresult *sqltypes.Result) error { if len(rresult.Rows) > 0 && !rowAdded { - result.Rows = append(result.Rows, projectRows(lrow, jn.Cols)) + result.Rows = append(result.Rows, lrow) rowAdded = true } return nil @@ -135,8 +125,7 @@ func (jn *SemiJoin) NeedsTransaction() bool { func (jn *SemiJoin) description() PrimitiveDescription { other := map[string]any{ - "TableName": jn.GetTableName(), - "ProjectedIndexes": strings.Trim(strings.Join(strings.Fields(fmt.Sprint(jn.Cols)), ","), "[]"), + "TableName": jn.GetTableName(), } if len(jn.Vars) > 0 { other["JoinVars"] = orderedStringIntMap(jn.Vars) @@ -146,30 +135,3 @@ func (jn *SemiJoin) description() PrimitiveDescription { Other: other, } } - -func projectFields(lfields []*querypb.Field, cols []int) []*querypb.Field { - if lfields == nil { - return nil - } - if len(cols) == 0 { - return lfields - } - fields := make([]*querypb.Field, len(cols)) - for i, index := range cols { - fields[i] = lfields[-index-1] - } - return fields -} - -func projectRows(lrow []sqltypes.Value, cols []int) []sqltypes.Value { - if len(cols) == 0 { - return lrow - } - row := make([]sqltypes.Value, len(cols)) - for i, index := range cols { - if index < 0 { - row[i] = lrow[-index-1] - } - } - return row -} diff --git a/go/vt/vtgate/engine/semi_join_test.go b/go/vt/vtgate/engine/semi_join_test.go index 9cf55d4f78f..8fee0490415 100644 --- a/go/vt/vtgate/engine/semi_join_test.go +++ b/go/vt/vtgate/engine/semi_join_test.go @@ -74,7 +74,6 @@ func TestSemiJoinExecute(t *testing.T) { Vars: map[string]int{ "bv": 1, }, - Cols: []int{-1, -2, -3}, } r, err := jn.TryExecute(context.Background(), &noopVCursor{}, bv, true) require.NoError(t, err) @@ -139,7 +138,6 @@ func TestSemiJoinStreamExecute(t *testing.T) { Vars: map[string]int{ "bv": 1, }, - Cols: []int{-1, -2, -3}, } r, err := wrapStreamExecute(jn, &noopVCursor{}, map[string]*querypb.BindVariable{}, true) require.NoError(t, err) diff --git a/go/vt/vtgate/planbuilder/logical_plan.go b/go/vt/vtgate/planbuilder/logical_plan.go index fac0bb59b5f..bbc6177847a 100644 --- a/go/vt/vtgate/planbuilder/logical_plan.go +++ b/go/vt/vtgate/planbuilder/logical_plan.go @@ -43,19 +43,3 @@ func newBuilderCommon(input logicalPlan) logicalPlanCommon { func (bc *logicalPlanCommon) Order() int { return bc.order } - -// ------------------------------------------------------------------------- - -// resultsBuilder is a superset of logicalPlanCommon. It also handles -// resultsColumn functionality. -type resultsBuilder struct { - logicalPlanCommon - truncater truncater -} - -func newResultsBuilder(input logicalPlan, truncater truncater) resultsBuilder { - return resultsBuilder{ - logicalPlanCommon: newBuilderCommon(input), - truncater: truncater, - } -} diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index 7d713158ec4..e83d9470880 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -256,8 +256,11 @@ func transformSubQuery(ctx *plancontext.PlanningContext, op *operators.SubQuery) return newUncorrelatedSubquery(op.FilterType, op.SubqueryValueName, op.HasValuesName, inner, outer), nil } - lhsCols := op.OuterExpressionsNeeded(ctx, op.Outer) - return newSemiJoin(outer, inner, op.Vars, lhsCols), nil + return &primitiveWrapper{prim: &engine.SemiJoin{ + Left: outer.Primitive(), + Right: inner.Primitive(), + Vars: op.Vars, + }}, nil } // transformFkVerify transforms a FkVerify operator into a logical plan. @@ -410,7 +413,7 @@ func transformProjection(ctx *plancontext.PlanningContext, op *operators.Project var evalengineExprs []evalengine.Expr var columnNames []string for _, pe := range ap { - ee, err := getEvalEngingeExpr(ctx, pe) + ee, err := getEvalEngineExpr(ctx, pe) if err != nil { return nil, err } @@ -418,15 +421,11 @@ func transformProjection(ctx *plancontext.PlanningContext, op *operators.Project columnNames = append(columnNames, pe.Original.ColumnName()) } - primitive := &engine.Projection{ + return &primitiveWrapper{prim: &engine.Projection{ + Input: src.Primitive(), Cols: columnNames, Exprs: evalengineExprs, - } - - return &projection{ - source: src, - primitive: primitive, - }, nil + }}, nil } // offsetInInputOrder returns true if the columns are in the same order as the input @@ -439,7 +438,7 @@ func offsetInInputOrder(cols []int) bool { return true } -func getEvalEngingeExpr(ctx *plancontext.PlanningContext, pe *operators.ProjExpr) (evalengine.Expr, error) { +func getEvalEngineExpr(ctx *plancontext.PlanningContext, pe *operators.ProjExpr) (evalengine.Expr, error) { switch e := pe.Info.(type) { case *operators.EvalEngine: return e.EExpr, nil diff --git a/go/vt/vtgate/planbuilder/projection.go b/go/vt/vtgate/planbuilder/projection.go deleted file mode 100644 index cb60c079c37..00000000000 --- a/go/vt/vtgate/planbuilder/projection.go +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright 2022 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/vtgate/engine" -) - -type projection struct { - source logicalPlan - primitive *engine.Projection -} - -var _ logicalPlan = (*projection)(nil) - -// Primitive implements the logicalPlan interface -func (p *projection) Primitive() engine.Primitive { - if p.primitive == nil { - panic("WireUp not yet run") - } - p.primitive.Input = p.source.Primitive() - return p.primitive -} diff --git a/go/vt/vtgate/planbuilder/semi_join.go b/go/vt/vtgate/planbuilder/semi_join.go deleted file mode 100644 index b12b04a1ed5..00000000000 --- a/go/vt/vtgate/planbuilder/semi_join.go +++ /dev/null @@ -1,59 +0,0 @@ -/* -Copyright 2021 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/vtgate/engine" -) - -var _ logicalPlan = (*semiJoin)(nil) - -// semiJoin is the logicalPlan for engine.SemiJoin. -// This gets built if a rhs is correlated and can -// be pulled out but requires some variables to be supplied from outside. -type semiJoin struct { - rhs logicalPlan - lhs logicalPlan - cols []int - - vars map[string]int - - // LHSColumns are the columns from the LHS used for the join. - // These are the same columns pushed on the LHS that are now used in the vars field - LHSColumns []*sqlparser.ColName -} - -// newSemiJoin builds a new semiJoin. -func newSemiJoin(lhs, rhs logicalPlan, vars map[string]int, lhsCols []*sqlparser.ColName) *semiJoin { - return &semiJoin{ - rhs: rhs, - lhs: lhs, - vars: vars, - LHSColumns: lhsCols, - } -} - -// Primitive implements the logicalPlan interface -func (ps *semiJoin) Primitive() engine.Primitive { - return &engine.SemiJoin{ - Left: ps.lhs.Primitive(), - Right: ps.rhs.Primitive(), - Vars: ps.vars, - Cols: ps.cols, - } -} From db89b294fe69a8053b959e7321cf57870a96362c Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 24 May 2024 10:06:23 +0200 Subject: [PATCH 13/18] refactor: remove more logical plans Signed-off-by: Andres Taylor --- go/vt/vtgate/engine/sql_calc_found_rows.go | 18 ++++---- go/vt/vtgate/planbuilder/logical_plan.go | 17 -------- .../planbuilder/operator_transformers.go | 25 +++++------ go/vt/vtgate/planbuilder/select.go | 14 +++++- go/vt/vtgate/planbuilder/sequential.go | 36 ---------------- go/vt/vtgate/planbuilder/simple_projection.go | 43 ------------------- .../vtgate/planbuilder/sql_calc_found_rows.go | 41 ------------------ 7 files changed, 33 insertions(+), 161 deletions(-) delete mode 100644 go/vt/vtgate/planbuilder/sequential.go delete mode 100644 go/vt/vtgate/planbuilder/simple_projection.go delete mode 100644 go/vt/vtgate/planbuilder/sql_calc_found_rows.go diff --git a/go/vt/vtgate/engine/sql_calc_found_rows.go b/go/vt/vtgate/engine/sql_calc_found_rows.go index 2472bfd1d14..64ec80f99c7 100644 --- a/go/vt/vtgate/engine/sql_calc_found_rows.go +++ b/go/vt/vtgate/engine/sql_calc_found_rows.go @@ -34,22 +34,22 @@ type SQLCalcFoundRows struct { } // RouteType implements the Primitive interface -func (s SQLCalcFoundRows) RouteType() string { +func (s *SQLCalcFoundRows) RouteType() string { return "SQLCalcFoundRows" } // GetKeyspaceName implements the Primitive interface -func (s SQLCalcFoundRows) GetKeyspaceName() string { +func (s *SQLCalcFoundRows) GetKeyspaceName() string { return s.LimitPrimitive.GetKeyspaceName() } // GetTableName implements the Primitive interface -func (s SQLCalcFoundRows) GetTableName() string { +func (s *SQLCalcFoundRows) GetTableName() string { return s.LimitPrimitive.GetTableName() } // TryExecute implements the Primitive interface -func (s SQLCalcFoundRows) TryExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) { +func (s *SQLCalcFoundRows) TryExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) { limitQr, err := vcursor.ExecutePrimitive(ctx, s.LimitPrimitive, bindVars, wantfields) if err != nil { return nil, err @@ -70,7 +70,7 @@ func (s SQLCalcFoundRows) TryExecute(ctx context.Context, vcursor VCursor, bindV } // TryStreamExecute implements the Primitive interface -func (s SQLCalcFoundRows) TryStreamExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool, callback func(*sqltypes.Result) error) error { +func (s *SQLCalcFoundRows) TryStreamExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool, callback func(*sqltypes.Result) error) error { err := vcursor.StreamExecutePrimitive(ctx, s.LimitPrimitive, bindVars, wantfields, callback) if err != nil { return err @@ -104,21 +104,21 @@ func (s SQLCalcFoundRows) TryStreamExecute(ctx context.Context, vcursor VCursor, } // GetFields implements the Primitive interface -func (s SQLCalcFoundRows) GetFields(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable) (*sqltypes.Result, error) { +func (s *SQLCalcFoundRows) GetFields(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable) (*sqltypes.Result, error) { return s.LimitPrimitive.GetFields(ctx, vcursor, bindVars) } // NeedsTransaction implements the Primitive interface -func (s SQLCalcFoundRows) NeedsTransaction() bool { +func (s *SQLCalcFoundRows) NeedsTransaction() bool { return s.LimitPrimitive.NeedsTransaction() } // Inputs implements the Primitive interface -func (s SQLCalcFoundRows) Inputs() ([]Primitive, []map[string]any) { +func (s *SQLCalcFoundRows) Inputs() ([]Primitive, []map[string]any) { return []Primitive{s.LimitPrimitive, s.CountPrimitive}, nil } -func (s SQLCalcFoundRows) description() PrimitiveDescription { +func (s *SQLCalcFoundRows) description() PrimitiveDescription { return PrimitiveDescription{ OperatorType: "SQL_CALC_FOUND_ROWS", } diff --git a/go/vt/vtgate/planbuilder/logical_plan.go b/go/vt/vtgate/planbuilder/logical_plan.go index bbc6177847a..ac569a1924f 100644 --- a/go/vt/vtgate/planbuilder/logical_plan.go +++ b/go/vt/vtgate/planbuilder/logical_plan.go @@ -26,20 +26,3 @@ type logicalPlan interface { // Primitive returns the underlying primitive. Primitive() engine.Primitive } - -// ------------------------------------------------------------------------- - -// logicalPlanCommon implements some common functionality of builders. -// Make sure to override in case behavior needs to be changed. -type logicalPlanCommon struct { - order int - input logicalPlan -} - -func newBuilderCommon(input logicalPlan) logicalPlanCommon { - return logicalPlanCommon{input: input} -} - -func (bc *logicalPlanCommon) Order() int { - return bc.order -} diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index e83d9470880..742a0122a05 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -135,7 +135,7 @@ func transformOneUpsert(ctx *plancontext.PlanningContext, source operators.Upser } func transformSequential(ctx *plancontext.PlanningContext, op *operators.Sequential) (logicalPlan, error) { - var lps []logicalPlan + var lps []engine.Primitive for _, source := range op.Sources { lp, err := transformToLogicalPlan(ctx, source) if err != nil { @@ -148,11 +148,10 @@ func transformSequential(ctx *plancontext.PlanningContext, op *operators.Sequent ins.PreventAutoCommit = true } } - lps = append(lps, lp) + lps = append(lps, lp.Primitive()) } - return &sequential{ - sources: lps, - }, nil + + return &primitiveWrapper{prim: engine.NewSequential(lps)}, nil } func transformInsertionSelection(ctx *plancontext.PlanningContext, op *operators.InsertSelection) (logicalPlan, error) { @@ -402,7 +401,7 @@ func transformProjection(ctx *plancontext.PlanningContext, op *operators.Project if len(op.Source.GetColumns(ctx)) == len(cols) && offsetInInputOrder(cols) { cols = nil } - return newSimpleProjection(cols, colNames, src) + return newSimpleProjection(cols, colNames, src.Primitive()) } ap, err := op.GetAliasedProjections() @@ -452,14 +451,12 @@ func getEvalEngineExpr(ctx *plancontext.PlanningContext, pe *operators.ProjExpr) } // newSimpleProjection creates a simple projections -func newSimpleProjection(cols []int, colNames []string, src logicalPlan) (logicalPlan, error) { - return &simpleProjection{ - logicalPlanCommon: newBuilderCommon(src), - eSimpleProj: &engine.SimpleProjection{ - Cols: cols, - ColNames: colNames, - }, - }, nil +func newSimpleProjection(cols []int, colNames []string, src engine.Primitive) (logicalPlan, error) { + return &primitiveWrapper{prim: &engine.SimpleProjection{ + Input: src, + Cols: cols, + ColNames: colNames, + }}, nil } // elementsMatchIndices checks if the elements of the input slice match diff --git a/go/vt/vtgate/planbuilder/select.go b/go/vt/vtgate/planbuilder/select.go index 0b67620c489..917e692ee54 100644 --- a/go/vt/vtgate/planbuilder/select.go +++ b/go/vt/vtgate/planbuilder/select.go @@ -169,7 +169,19 @@ func buildSQLCalcFoundRowsPlan( if err != nil { return nil, nil, err } - return &sqlCalcFoundRows{LimitQuery: limitPlan, CountQuery: countPlan}, tablesUsed, nil + + countPrim := countPlan.Primitive() + rb, ok := countPrim.(*engine.Route) + if ok { + // if our count query is an aggregation, we want the no-match result to still return a zero + rb.NoRoutesSpecialHandling = true + } + lp := &primitiveWrapper{&engine.SQLCalcFoundRows{ + LimitPrimitive: limitPlan.Primitive(), + CountPrimitive: countPrim, + }} + + return lp, tablesUsed, nil } func gen4PredicateRewrite(stmt sqlparser.Statement, getPlan func(selStatement sqlparser.SelectStatement) (logicalPlan, []string, error)) (logicalPlan, []string) { diff --git a/go/vt/vtgate/planbuilder/sequential.go b/go/vt/vtgate/planbuilder/sequential.go deleted file mode 100644 index ff6abacb437..00000000000 --- a/go/vt/vtgate/planbuilder/sequential.go +++ /dev/null @@ -1,36 +0,0 @@ -/* -Copyright 2023 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/vtgate/engine" -) - -type sequential struct { - sources []logicalPlan -} - -var _ logicalPlan = (*sequential)(nil) - -// Primitive implements the logicalPlan interface -func (s *sequential) Primitive() engine.Primitive { - var sources []engine.Primitive - for _, source := range s.sources { - sources = append(sources, source.Primitive()) - } - return engine.NewSequential(sources) -} diff --git a/go/vt/vtgate/planbuilder/simple_projection.go b/go/vt/vtgate/planbuilder/simple_projection.go deleted file mode 100644 index 4c29ef0ae9a..00000000000 --- a/go/vt/vtgate/planbuilder/simple_projection.go +++ /dev/null @@ -1,43 +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/vtgate/engine" -) - -var _ logicalPlan = (*simpleProjection)(nil) - -// simpleProjection is used for wrapping a derived table. -// This primitive wraps any derived table that results -// in something that's not a route. It builds a -// 'table' for the derived table allowing higher level -// constructs to reference its columns. If a derived table -// results in a route primitive, we instead build -// a new route that keeps the subquery in the FROM -// clause, because a route is more versatile than -// a simpleProjection. -type simpleProjection struct { - logicalPlanCommon - eSimpleProj *engine.SimpleProjection -} - -// Primitive implements the logicalPlan interface -func (sq *simpleProjection) Primitive() engine.Primitive { - sq.eSimpleProj.Input = sq.input.Primitive() - return sq.eSimpleProj -} diff --git a/go/vt/vtgate/planbuilder/sql_calc_found_rows.go b/go/vt/vtgate/planbuilder/sql_calc_found_rows.go deleted file mode 100644 index 62823a8c10e..00000000000 --- a/go/vt/vtgate/planbuilder/sql_calc_found_rows.go +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright 2020 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/vtgate/engine" -) - -var _ logicalPlan = (*sqlCalcFoundRows)(nil) - -type sqlCalcFoundRows struct { - LimitQuery, CountQuery logicalPlan -} - -// Primitive implements the logicalPlan interface -func (s *sqlCalcFoundRows) Primitive() engine.Primitive { - countPrim := s.CountQuery.Primitive() - rb, ok := countPrim.(*engine.Route) - if ok { - // if our count query is an aggregation, we want the no-match result to still return a zero - rb.NoRoutesSpecialHandling = true - } - return engine.SQLCalcFoundRows{ - LimitPrimitive: s.LimitQuery.Primitive(), - CountPrimitive: countPrim, - } -} From 92596ba564397c9b26c0e812483cf73380a7ec54 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 24 May 2024 10:16:41 +0200 Subject: [PATCH 14/18] refactor: remove last logicalPlan implementation Signed-off-by: Andres Taylor --- .../planbuilder/operator_transformers.go | 47 ++++++++++++-- .../planbuilder/uncorrelated_subquery.go | 53 ---------------- go/vt/vtgate/planbuilder/upsert.go | 37 ----------- go/vt/vtgate/planbuilder/vindex_func.go | 45 +++---------- go/vt/vtgate/planbuilder/vindex_op.go | 63 ------------------- 5 files changed, 50 insertions(+), 195 deletions(-) delete mode 100644 go/vt/vtgate/planbuilder/uncorrelated_subquery.go delete mode 100644 go/vt/vtgate/planbuilder/upsert.go delete mode 100644 go/vt/vtgate/planbuilder/vindex_op.go diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index 742a0122a05..4a56599fb7b 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -106,16 +106,15 @@ func transformDMLWithInput(ctx *plancontext.PlanningContext, op *operators.DMLWi } func transformUpsert(ctx *plancontext.PlanningContext, op *operators.Upsert) (logicalPlan, error) { - u := &upsert{} + u := &engine.Upsert{} for _, source := range op.Sources { iLp, uLp, err := transformOneUpsert(ctx, source) if err != nil { return nil, err } - u.insert = append(u.insert, iLp) - u.update = append(u.update, uLp) + u.AddUpsert(iLp.Primitive(), uLp.Primitive()) } - return u, nil + return &primitiveWrapper{prim: u}, nil } func transformOneUpsert(ctx *plancontext.PlanningContext, source operators.UpsertSource) (iLp, uLp logicalPlan, err error) { @@ -252,7 +251,13 @@ func transformSubQuery(ctx *plancontext.PlanningContext, op *operators.SubQuery) } if len(cols) == 0 { // no correlation, so uncorrelated it is - return newUncorrelatedSubquery(op.FilterType, op.SubqueryValueName, op.HasValuesName, inner, outer), nil + return &primitiveWrapper{prim: &engine.UncorrelatedSubquery{ + Opcode: op.FilterType, + SubqueryResult: op.SubqueryValueName, + HasValues: op.HasValuesName, + Subquery: inner.Primitive(), + Outer: outer.Primitive(), + }}, nil } return &primitiveWrapper{prim: &engine.SemiJoin{ @@ -961,6 +966,38 @@ func transformHashJoin(ctx *plancontext.PlanningContext, op *operators.HashJoin) }, nil } +func transformVindexPlan(ctx *plancontext.PlanningContext, op *operators.Vindex) (logicalPlan, error) { + single, ok := op.Vindex.(vindexes.SingleColumn) + if !ok { + return nil, vterrors.VT12001("multi-column vindexes not supported") + } + + expr, err := evalengine.Translate(op.Value, &evalengine.Config{ + Collation: ctx.SemTable.Collation, + ResolveType: ctx.SemTable.TypeForExpr, + Environment: ctx.VSchema.Environment(), + }) + if err != nil { + return nil, err + } + prim := &engine.VindexFunc{ + Opcode: op.OpCode, + Vindex: single, + Value: expr, + } + + for _, col := range op.Columns { + err := SupplyProjection(prim, &sqlparser.AliasedExpr{ + Expr: col, + As: sqlparser.IdentifierCI{}, + }, false) + if err != nil { + return nil, err + } + } + return &primitiveWrapper{prim: prim}, nil +} + func generateQuery(statement sqlparser.Statement) string { buf := sqlparser.NewTrackedBuffer(dmlFormatter) statement.Format(buf) diff --git a/go/vt/vtgate/planbuilder/uncorrelated_subquery.go b/go/vt/vtgate/planbuilder/uncorrelated_subquery.go deleted file mode 100644 index edb46e5b4fe..00000000000 --- a/go/vt/vtgate/planbuilder/uncorrelated_subquery.go +++ /dev/null @@ -1,53 +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/vtgate/engine" - popcode "vitess.io/vitess/go/vt/vtgate/engine/opcode" -) - -var _ logicalPlan = (*uncorrelatedSubquery)(nil) - -// uncorrelatedSubquery is the logicalPlan for engine.UncorrelatedSubquery. -// This gets built if a subquery is not correlated and can -// therefore can be pulled out and executed upfront. -type uncorrelatedSubquery struct { - subquery logicalPlan - outer logicalPlan - eSubquery *engine.UncorrelatedSubquery -} - -// newUncorrelatedSubquery builds a new uncorrelatedSubquery. -func newUncorrelatedSubquery(opcode popcode.PulloutOpcode, sqName, hasValues string, subquery, outer logicalPlan) *uncorrelatedSubquery { - return &uncorrelatedSubquery{ - subquery: subquery, - outer: outer, - eSubquery: &engine.UncorrelatedSubquery{ - Opcode: opcode, - SubqueryResult: sqName, - HasValues: hasValues, - }, - } -} - -// Primitive implements the logicalPlan interface -func (ps *uncorrelatedSubquery) Primitive() engine.Primitive { - ps.eSubquery.Subquery = ps.subquery.Primitive() - ps.eSubquery.Outer = ps.outer.Primitive() - return ps.eSubquery -} diff --git a/go/vt/vtgate/planbuilder/upsert.go b/go/vt/vtgate/planbuilder/upsert.go deleted file mode 100644 index cd9c127635c..00000000000 --- a/go/vt/vtgate/planbuilder/upsert.go +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright 2023 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/vtgate/engine" -) - -type upsert struct { - insert []logicalPlan - update []logicalPlan -} - -var _ logicalPlan = (*upsert)(nil) - -// Primitive implements the logicalPlan interface -func (u *upsert) Primitive() engine.Primitive { - up := &engine.Upsert{} - for i := 0; i < len(u.insert); i++ { - up.AddUpsert(u.insert[i].Primitive(), u.update[i].Primitive()) - } - return up -} diff --git a/go/vt/vtgate/planbuilder/vindex_func.go b/go/vt/vtgate/planbuilder/vindex_func.go index abfd2d1d9b3..6db9adab051 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/semantics" - "vitess.io/vitess/go/vt/vterrors" querypb "vitess.io/vitess/go/vt/proto/query" @@ -29,63 +27,36 @@ import ( "vitess.io/vitess/go/vt/vtgate/engine" ) -var _ logicalPlan = (*vindexFunc)(nil) - -// vindexFunc is used to build a VindexFunc primitive. -type vindexFunc struct { - order int - - // the tableID field is only used by the gen4 planner - tableID semantics.TableSet - - // eVindexFunc is the primitive being built. - eVindexFunc *engine.VindexFunc -} - -var colnames = []string{ - "id", - "keyspace_id", - "range_start", - "range_end", - "hex_keyspace_id", - "shard", -} - -// Primitive implements the logicalPlan interface -func (vf *vindexFunc) Primitive() engine.Primitive { - return vf.eVindexFunc -} - // 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. -func (vf *vindexFunc) SupplyProjection(expr *sqlparser.AliasedExpr, reuse bool) (int, error) { +func SupplyProjection(eVindexFunc *engine.VindexFunc, expr *sqlparser.AliasedExpr, reuse bool) error { colName, isColName := expr.Expr.(*sqlparser.ColName) if !isColName { - return 0, vterrors.VT12001("expression on results of a vindex function") + return vterrors.VT12001("expression on results of a vindex function") } enum := vindexColumnToIndex(colName) if enum == -1 { - return 0, vterrors.VT03016(colName.Name.String()) + return vterrors.VT03016(colName.Name.String()) } if reuse { - for i, col := range vf.eVindexFunc.Cols { + for _, col := range eVindexFunc.Cols { if col == enum { - return i, nil + return nil } } } - vf.eVindexFunc.Fields = append(vf.eVindexFunc.Fields, &querypb.Field{ + eVindexFunc.Fields = append(eVindexFunc.Fields, &querypb.Field{ Name: expr.ColumnName(), Type: querypb.Type_VARBINARY, Charset: collations.CollationBinaryID, Flags: uint32(querypb.MySqlFlag_BINARY_FLAG), }) - vf.eVindexFunc.Cols = append(vf.eVindexFunc.Cols, enum) - return len(vf.eVindexFunc.Cols) - 1, nil + eVindexFunc.Cols = append(eVindexFunc.Cols, enum) + return nil } // UnsupportedSupplyWeightString represents the error where the supplying a weight string is not supported diff --git a/go/vt/vtgate/planbuilder/vindex_op.go b/go/vt/vtgate/planbuilder/vindex_op.go deleted file mode 100644 index ffd304aa06d..00000000000 --- a/go/vt/vtgate/planbuilder/vindex_op.go +++ /dev/null @@ -1,63 +0,0 @@ -/* -Copyright 2022 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/engine" - "vitess.io/vitess/go/vt/vtgate/evalengine" - "vitess.io/vitess/go/vt/vtgate/planbuilder/operators" - "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" - "vitess.io/vitess/go/vt/vtgate/vindexes" -) - -func transformVindexPlan(ctx *plancontext.PlanningContext, op *operators.Vindex) (logicalPlan, error) { - single, ok := op.Vindex.(vindexes.SingleColumn) - if !ok { - return nil, vterrors.VT12001("multi-column vindexes not supported") - } - - expr, err := evalengine.Translate(op.Value, &evalengine.Config{ - Collation: ctx.SemTable.Collation, - ResolveType: ctx.SemTable.TypeForExpr, - Environment: ctx.VSchema.Environment(), - }) - if err != nil { - return nil, err - } - plan := &vindexFunc{ - order: 1, - tableID: op.Solved, - eVindexFunc: &engine.VindexFunc{ - Opcode: op.OpCode, - Vindex: single, - Value: expr, - }, - } - - for _, col := range op.Columns { - _, err := plan.SupplyProjection(&sqlparser.AliasedExpr{ - Expr: col, - As: sqlparser.IdentifierCI{}, - }, false) - if err != nil { - return nil, err - } - } - return plan, nil -} From fdc4cc292dcb952400e9a0d6ea7b45b2bdd6c827 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 24 May 2024 10:34:23 +0200 Subject: [PATCH 15/18] refactor: remove the logicalPlan interface and use engine.Primitive instead Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/delete.go | 8 +- go/vt/vtgate/planbuilder/insert.go | 8 +- go/vt/vtgate/planbuilder/logical_plan.go | 28 -- .../planbuilder/operator_transformers.go | 247 ++++++++---------- go/vt/vtgate/planbuilder/planner.go | 7 +- go/vt/vtgate/planbuilder/primitive_wrapper.go | 32 --- go/vt/vtgate/planbuilder/select.go | 60 ++--- .../planbuilder/single_sharded_shortcut.go | 4 +- go/vt/vtgate/planbuilder/update.go | 8 +- 9 files changed, 149 insertions(+), 253 deletions(-) delete mode 100644 go/vt/vtgate/planbuilder/logical_plan.go delete mode 100644 go/vt/vtgate/planbuilder/primitive_wrapper.go diff --git a/go/vt/vtgate/planbuilder/delete.go b/go/vt/vtgate/planbuilder/delete.go index 980af21df61..ab0925e7194 100644 --- a/go/vt/vtgate/planbuilder/delete.go +++ b/go/vt/vtgate/planbuilder/delete.go @@ -63,7 +63,7 @@ func gen4DeleteStmtPlanner( if ks, tables := ctx.SemTable.SingleUnshardedKeyspace(); ks != nil { if !ctx.SemTable.ForeignKeysPresent() { plan := deleteUnshardedShortcut(deleteStmt, ks, tables) - return newPlanResult(plan.Primitive(), operators.QualifiedTables(ks, tables)...), nil + return newPlanResult(plan, operators.QualifiedTables(ks, tables)...), nil } } @@ -83,7 +83,7 @@ func gen4DeleteStmtPlanner( return nil, err } - return newPlanResult(plan.Primitive(), operators.TablesUsed(op)...), nil + return newPlanResult(plan, operators.TablesUsed(op)...), nil } func rewriteSingleTbl(del *sqlparser.Delete) (*sqlparser.Delete, error) { @@ -123,7 +123,7 @@ func rewriteSingleTbl(del *sqlparser.Delete) (*sqlparser.Delete, error) { return del, nil } -func deleteUnshardedShortcut(stmt *sqlparser.Delete, ks *vindexes.Keyspace, tables []*vindexes.Table) logicalPlan { +func deleteUnshardedShortcut(stmt *sqlparser.Delete, ks *vindexes.Keyspace, tables []*vindexes.Table) engine.Primitive { edml := engine.NewDML() edml.Keyspace = ks edml.Opcode = engine.Unsharded @@ -131,5 +131,5 @@ func deleteUnshardedShortcut(stmt *sqlparser.Delete, ks *vindexes.Keyspace, tabl for _, tbl := range tables { edml.TableNames = append(edml.TableNames, tbl.Name.String()) } - return &primitiveWrapper{prim: &engine.Delete{DML: edml}} + return &engine.Delete{DML: edml} } diff --git a/go/vt/vtgate/planbuilder/insert.go b/go/vt/vtgate/planbuilder/insert.go index d1cc07712bf..93167451c3d 100644 --- a/go/vt/vtgate/planbuilder/insert.go +++ b/go/vt/vtgate/planbuilder/insert.go @@ -53,7 +53,7 @@ func gen4InsertStmtPlanner(version querypb.ExecuteOptions_PlannerVersion, insStm if tables[0].AutoIncrement == nil && !ctx.SemTable.ForeignKeysPresent() { plan := insertUnshardedShortcut(insStmt, ks, tables) setCommentDirectivesOnPlan(plan, insStmt) - return newPlanResult(plan.Primitive(), operators.QualifiedTables(ks, tables)...), nil + return newPlanResult(plan, operators.QualifiedTables(ks, tables)...), nil } } @@ -80,7 +80,7 @@ func gen4InsertStmtPlanner(version querypb.ExecuteOptions_PlannerVersion, insStm return nil, err } - return newPlanResult(plan.Primitive(), operators.TablesUsed(op)...), nil + return newPlanResult(plan, operators.TablesUsed(op)...), nil } func errOutIfPlanCannotBeConstructed(ctx *plancontext.PlanningContext, vTbl *vindexes.Table) error { @@ -90,7 +90,7 @@ func errOutIfPlanCannotBeConstructed(ctx *plancontext.PlanningContext, vTbl *vin return ctx.SemTable.NotUnshardedErr } -func insertUnshardedShortcut(stmt *sqlparser.Insert, ks *vindexes.Keyspace, tables []*vindexes.Table) logicalPlan { +func insertUnshardedShortcut(stmt *sqlparser.Insert, ks *vindexes.Keyspace, tables []*vindexes.Table) engine.Primitive { eIns := &engine.Insert{ InsertCommon: engine.InsertCommon{ Opcode: engine.InsertUnsharded, @@ -99,5 +99,5 @@ func insertUnshardedShortcut(stmt *sqlparser.Insert, ks *vindexes.Keyspace, tabl }, } eIns.Query = generateQuery(stmt) - return &primitiveWrapper{prim: eIns} + return eIns } diff --git a/go/vt/vtgate/planbuilder/logical_plan.go b/go/vt/vtgate/planbuilder/logical_plan.go deleted file mode 100644 index ac569a1924f..00000000000 --- a/go/vt/vtgate/planbuilder/logical_plan.go +++ /dev/null @@ -1,28 +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/vtgate/engine" -) - -// logicalPlan defines the interface that a primitive must -// satisfy. -type logicalPlan interface { - // Primitive returns the underlying primitive. - Primitive() engine.Primitive -} diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index 4a56599fb7b..4abc35397ae 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -37,7 +37,7 @@ import ( "vitess.io/vitess/go/vt/vtgate/vindexes" ) -func transformToLogicalPlan(ctx *plancontext.PlanningContext, op operators.Operator) (logicalPlan, error) { +func transformToLogicalPlan(ctx *plancontext.PlanningContext, op operators.Operator) (engine.Primitive, error) { switch op := op.(type) { case *operators.Route: return transformRoutePlan(ctx, op) @@ -82,7 +82,7 @@ func transformToLogicalPlan(ctx *plancontext.PlanningContext, op operators.Opera return nil, vterrors.VT13001(fmt.Sprintf("unknown type encountered: %T (transformToLogicalPlan)", op)) } -func transformDMLWithInput(ctx *plancontext.PlanningContext, op *operators.DMLWithInput) (logicalPlan, error) { +func transformDMLWithInput(ctx *plancontext.PlanningContext, op *operators.DMLWithInput) (engine.Primitive, error) { input, err := transformToLogicalPlan(ctx, op.Source) if err != nil { return nil, err @@ -94,66 +94,61 @@ func transformDMLWithInput(ctx *plancontext.PlanningContext, op *operators.DMLWi if err != nil { return nil, err } - dmls = append(dmls, del.Primitive()) + dmls = append(dmls, del) } - return &primitiveWrapper{prim: &engine.DMLWithInput{ + return &engine.DMLWithInput{ DMLs: dmls, - Input: input.Primitive(), + Input: input, OutputCols: op.Offsets, BVList: op.BvList, - }}, nil + }, nil } -func transformUpsert(ctx *plancontext.PlanningContext, op *operators.Upsert) (logicalPlan, error) { - u := &engine.Upsert{} +func transformUpsert(ctx *plancontext.PlanningContext, op *operators.Upsert) (engine.Primitive, error) { + upsert := &engine.Upsert{} for _, source := range op.Sources { iLp, uLp, err := transformOneUpsert(ctx, source) if err != nil { return nil, err } - u.AddUpsert(iLp.Primitive(), uLp.Primitive()) + upsert.AddUpsert(iLp, uLp) } - return &primitiveWrapper{prim: u}, nil + return upsert, nil } -func transformOneUpsert(ctx *plancontext.PlanningContext, source operators.UpsertSource) (iLp, uLp logicalPlan, err error) { +func transformOneUpsert(ctx *plancontext.PlanningContext, source operators.UpsertSource) (iLp, uLp engine.Primitive, err error) { iLp, err = transformToLogicalPlan(ctx, source.Insert) if err != nil { return } - wrap, ok := iLp.(*primitiveWrapper) + ins, ok := iLp.(*engine.Insert) if ok { - ins, ok := wrap.prim.(*engine.Insert) - if ok { - ins.PreventAutoCommit = true - } + ins.PreventAutoCommit = true } uLp, err = transformToLogicalPlan(ctx, source.Update) return } -func transformSequential(ctx *plancontext.PlanningContext, op *operators.Sequential) (logicalPlan, error) { - var lps []engine.Primitive +func transformSequential(ctx *plancontext.PlanningContext, op *operators.Sequential) (engine.Primitive, error) { + var prims []engine.Primitive for _, source := range op.Sources { - lp, err := transformToLogicalPlan(ctx, source) + prim, err := transformToLogicalPlan(ctx, source) if err != nil { return nil, err } - wrap, ok := lp.(*primitiveWrapper) + ins, ok := prim.(*engine.Insert) if ok { - ins, ok := wrap.prim.(*engine.Insert) - if ok { - ins.PreventAutoCommit = true - } + ins.PreventAutoCommit = true } - lps = append(lps, lp.Primitive()) + + prims = append(prims, prim) } - return &primitiveWrapper{prim: engine.NewSequential(lps)}, nil + return engine.NewSequential(prims), nil } -func transformInsertionSelection(ctx *plancontext.PlanningContext, op *operators.InsertSelection) (logicalPlan, error) { +func transformInsertionSelection(ctx *plancontext.PlanningContext, op *operators.InsertSelection) (engine.Primitive, error) { rb, isRoute := op.Insert.(*operators.Route) if !isRoute { return nil, vterrors.VT13001(fmt.Sprintf("Incorrect type encountered: %T (transformInsertionSelection)", op.Insert)) @@ -188,12 +183,12 @@ func transformInsertionSelection(ctx *plancontext.PlanningContext, op *operators return nil, err } - eins.Input = selectionPlan.Primitive() - return &primitiveWrapper{prim: eins}, nil + eins.Input = selectionPlan + return eins, nil } // transformFkCascade transforms a FkCascade operator into a logical plan. -func transformFkCascade(ctx *plancontext.PlanningContext, fkc *operators.FkCascade) (logicalPlan, error) { +func transformFkCascade(ctx *plancontext.PlanningContext, fkc *operators.FkCascade) (engine.Primitive, error) { // We convert the parent operator to a logical plan. parentLP, err := transformToLogicalPlan(ctx, fkc.Parent) if err != nil { @@ -216,7 +211,7 @@ func transformFkCascade(ctx *plancontext.PlanningContext, fkc *operators.FkCasca return nil, err } - childEngine := childLP.Primitive() + childEngine := childLP children = append(children, &engine.FkChild{ BVName: child.BVName, Cols: child.Cols, @@ -225,16 +220,14 @@ func transformFkCascade(ctx *plancontext.PlanningContext, fkc *operators.FkCasca }) } - return &primitiveWrapper{ - prim: &engine.FkCascade{ - Selection: selLP.Primitive(), - Children: children, - Parent: parentLP.Primitive(), - }, + return &engine.FkCascade{ + Selection: selLP, + Children: children, + Parent: parentLP, }, nil } -func transformSubQuery(ctx *plancontext.PlanningContext, op *operators.SubQuery) (logicalPlan, error) { +func transformSubQuery(ctx *plancontext.PlanningContext, op *operators.SubQuery) (engine.Primitive, error) { outer, err := transformToLogicalPlan(ctx, op.Outer) if err != nil { return nil, err @@ -251,24 +244,24 @@ func transformSubQuery(ctx *plancontext.PlanningContext, op *operators.SubQuery) } if len(cols) == 0 { // no correlation, so uncorrelated it is - return &primitiveWrapper{prim: &engine.UncorrelatedSubquery{ + return &engine.UncorrelatedSubquery{ Opcode: op.FilterType, SubqueryResult: op.SubqueryValueName, HasValues: op.HasValuesName, - Subquery: inner.Primitive(), - Outer: outer.Primitive(), - }}, nil + Subquery: inner, + Outer: outer, + }, nil } - return &primitiveWrapper{prim: &engine.SemiJoin{ - Left: outer.Primitive(), - Right: inner.Primitive(), + return &engine.SemiJoin{ + Left: outer, + Right: inner, Vars: op.Vars, - }}, nil + }, nil } // transformFkVerify transforms a FkVerify operator into a logical plan. -func transformFkVerify(ctx *plancontext.PlanningContext, fkv *operators.FkVerify) (logicalPlan, error) { +func transformFkVerify(ctx *plancontext.PlanningContext, fkv *operators.FkVerify) (engine.Primitive, error) { inputLP, err := transformToLogicalPlan(ctx, fkv.Input) if err != nil { return nil, err @@ -286,21 +279,19 @@ func transformFkVerify(ctx *plancontext.PlanningContext, fkv *operators.FkVerify return nil, err } verify = append(verify, &engine.Verify{ - Exec: lp.Primitive(), + Exec: lp, Typ: v.Typ, }) } - return &primitiveWrapper{ - prim: &engine.FkVerify{ - Verify: verify, - Exec: inputLP.Primitive(), - }, + return &engine.FkVerify{ + Verify: verify, + Exec: inputLP, }, nil } -func transformAggregator(ctx *plancontext.PlanningContext, op *operators.Aggregator) (logicalPlan, error) { +func transformAggregator(ctx *plancontext.PlanningContext, op *operators.Aggregator) (engine.Primitive, error) { if op.WithRollup { return nil, vterrors.VT12001("GROUP BY WITH ROLLUP not supported for sharded queries") } @@ -337,35 +328,35 @@ func transformAggregator(ctx *plancontext.PlanningContext, op *operators.Aggrega } if len(groupByKeys) == 0 { - return &primitiveWrapper{prim: &engine.ScalarAggregate{ + return &engine.ScalarAggregate{ Aggregates: aggregates, TruncateColumnCount: op.ResultColumns, - Input: src.Primitive(), - }}, nil + Input: src, + }, nil } - return &primitiveWrapper{&engine.OrderedAggregate{ + return &engine.OrderedAggregate{ Aggregates: aggregates, GroupByKeys: groupByKeys, TruncateColumnCount: op.ResultColumns, - Input: src.Primitive(), - }}, nil + Input: src, + }, nil } -func transformDistinct(ctx *plancontext.PlanningContext, op *operators.Distinct) (logicalPlan, error) { +func transformDistinct(ctx *plancontext.PlanningContext, op *operators.Distinct) (engine.Primitive, error) { src, err := transformToLogicalPlan(ctx, op.Source) if err != nil { return nil, err } - return &primitiveWrapper{prim: &engine.Distinct{ - Source: src.Primitive(), + return &engine.Distinct{ + Source: src, CheckCols: op.Columns, Truncate: op.Truncate, - }}, nil + }, nil } -func transformOrdering(ctx *plancontext.PlanningContext, op *operators.Ordering) (logicalPlan, error) { +func transformOrdering(ctx *plancontext.PlanningContext, op *operators.Ordering) (engine.Primitive, error) { plan, err := transformToLogicalPlan(ctx, op.Source) if err != nil { return nil, err @@ -374,9 +365,9 @@ func transformOrdering(ctx *plancontext.PlanningContext, op *operators.Ordering) return createMemorySort(ctx, plan, op) } -func createMemorySort(ctx *plancontext.PlanningContext, src logicalPlan, ordering *operators.Ordering) (logicalPlan, error) { +func createMemorySort(ctx *plancontext.PlanningContext, src engine.Primitive, ordering *operators.Ordering) (engine.Primitive, error) { prim := &engine.MemorySort{ - Input: src.Primitive(), + Input: src, TruncateColumnCount: ordering.ResultColumns, } @@ -391,10 +382,10 @@ func createMemorySort(ctx *plancontext.PlanningContext, src logicalPlan, orderin }) } - return &primitiveWrapper{prim}, nil + return prim, nil } -func transformProjection(ctx *plancontext.PlanningContext, op *operators.Projection) (logicalPlan, error) { +func transformProjection(ctx *plancontext.PlanningContext, op *operators.Projection) (engine.Primitive, error) { src, err := transformToLogicalPlan(ctx, op.Source) if err != nil { return nil, err @@ -406,7 +397,7 @@ func transformProjection(ctx *plancontext.PlanningContext, op *operators.Project if len(op.Source.GetColumns(ctx)) == len(cols) && offsetInInputOrder(cols) { cols = nil } - return newSimpleProjection(cols, colNames, src.Primitive()) + return newSimpleProjection(cols, colNames, src), nil } ap, err := op.GetAliasedProjections() @@ -425,11 +416,11 @@ func transformProjection(ctx *plancontext.PlanningContext, op *operators.Project columnNames = append(columnNames, pe.Original.ColumnName()) } - return &primitiveWrapper{prim: &engine.Projection{ - Input: src.Primitive(), + return &engine.Projection{ + Input: src, Cols: columnNames, Exprs: evalengineExprs, - }}, nil + }, nil } // offsetInInputOrder returns true if the columns are in the same order as the input @@ -456,28 +447,16 @@ func getEvalEngineExpr(ctx *plancontext.PlanningContext, pe *operators.ProjExpr) } // newSimpleProjection creates a simple projections -func newSimpleProjection(cols []int, colNames []string, src engine.Primitive) (logicalPlan, error) { - return &primitiveWrapper{prim: &engine.SimpleProjection{ +func newSimpleProjection(cols []int, colNames []string, src engine.Primitive) engine.Primitive { + return &engine.SimpleProjection{ Input: src, Cols: cols, ColNames: colNames, - }}, nil -} - -// elementsMatchIndices checks if the elements of the input slice match -// their corresponding index values. It returns true if all elements match -// their indices, and false otherwise. -func elementsMatchIndices(in []int) bool { - for idx, val := range in { - if val != idx { - return false - } } - return true } -func transformFilter(ctx *plancontext.PlanningContext, op *operators.Filter) (logicalPlan, error) { - plan, err := transformToLogicalPlan(ctx, op.Source) +func transformFilter(ctx *plancontext.PlanningContext, op *operators.Filter) (engine.Primitive, error) { + src, err := transformToLogicalPlan(ctx, op.Source) if err != nil { return nil, err } @@ -487,15 +466,15 @@ func transformFilter(ctx *plancontext.PlanningContext, op *operators.Filter) (lo panic("this should have already been done") } - return &primitiveWrapper{prim: &engine.Filter{ - Input: plan.Primitive(), + return &engine.Filter{ + Input: src, Predicate: predicate, ASTPredicate: ctx.SemTable.AndExpressions(op.Predicates...), Truncate: op.Truncate, - }}, nil + }, nil } -func transformApplyJoinPlan(ctx *plancontext.PlanningContext, n *operators.ApplyJoin) (logicalPlan, error) { +func transformApplyJoinPlan(ctx *plancontext.PlanningContext, n *operators.ApplyJoin) (engine.Primitive, error) { lhs, err := transformToLogicalPlan(ctx, n.LHS) if err != nil { return nil, err @@ -509,13 +488,13 @@ func transformApplyJoinPlan(ctx *plancontext.PlanningContext, n *operators.Apply opCode = engine.LeftJoin } - return &primitiveWrapper{prim: &engine.Join{ + return &engine.Join{ Opcode: opCode, - Left: lhs.Primitive(), - Right: rhs.Primitive(), + Left: lhs, + Right: rhs, Cols: n.Columns, Vars: n.Vars, - }}, nil + }, nil } func routeToEngineRoute(ctx *plancontext.PlanningContext, op *operators.Route, hints *queryHints) (*engine.Route, error) { @@ -573,7 +552,7 @@ func getHints(cmt *sqlparser.ParsedComments) *queryHints { } } -func transformRoutePlan(ctx *plancontext.PlanningContext, op *operators.Route) (logicalPlan, error) { +func transformRoutePlan(ctx *plancontext.PlanningContext, op *operators.Route) (engine.Primitive, error) { stmt, dmlOp, err := operators.ToSQL(ctx, op.Source) if err != nil { return nil, err @@ -602,7 +581,7 @@ func transformRoutePlan(ctx *plancontext.PlanningContext, op *operators.Route) ( } } -func buildRouteLogicalPlan(ctx *plancontext.PlanningContext, op *operators.Route, stmt sqlparser.SelectStatement, hints *queryHints) (logicalPlan, error) { +func buildRouteLogicalPlan(ctx *plancontext.PlanningContext, op *operators.Route, stmt sqlparser.SelectStatement, hints *queryHints) (engine.Primitive, error) { _ = updateSelectedVindexPredicate(op.Routing) eroute, err := routeToEngineRoute(ctx, op, hints) @@ -628,13 +607,13 @@ func buildRouteLogicalPlan(ctx *plancontext.PlanningContext, op *operators.Route return nil, err } - return &primitiveWrapper{prim: res}, nil + return res, nil } func buildInsertLogicalPlan( rb *operators.Route, op operators.Operator, stmt *sqlparser.Insert, hints *queryHints, -) (logicalPlan, error) { +) (engine.Primitive, error) { ins := op.(*operators.Insert) ic := engine.InsertCommon{ @@ -665,7 +644,7 @@ func buildInsertLogicalPlan( } eins.Query = generateQuery(stmt) - return &primitiveWrapper{prim: eins}, nil + return eins, nil } func mapToInsertOpCode(code engine.Opcode) engine.InsertOpcode { @@ -732,7 +711,7 @@ func buildUpdateLogicalPlan( dmlOp operators.Operator, stmt *sqlparser.Update, hints *queryHints, -) (logicalPlan, error) { +) (engine.Primitive, error) { upd := dmlOp.(*operators.Update) var vindexes []*vindexes.ColumnVindex vQuery := "" @@ -751,13 +730,13 @@ func buildUpdateLogicalPlan( _ = updateSelectedVindexPredicate(rb.Routing) edml := createDMLPrimitive(ctx, rb, hints, upd.Target.VTable, generateQuery(stmt), vindexes, vQuery) - return &primitiveWrapper{prim: &engine.Update{ + return &engine.Update{ DML: edml, ChangedVindexValues: upd.ChangedVindexValues, - }}, nil + }, nil } -func buildDeleteLogicalPlan(ctx *plancontext.PlanningContext, rb *operators.Route, dmlOp operators.Operator, stmt *sqlparser.Delete, hints *queryHints) (logicalPlan, error) { +func buildDeleteLogicalPlan(ctx *plancontext.PlanningContext, rb *operators.Route, dmlOp operators.Operator, stmt *sqlparser.Delete, hints *queryHints) (engine.Primitive, error) { del := dmlOp.(*operators.Delete) var vindexes []*vindexes.ColumnVindex @@ -771,7 +750,7 @@ func buildDeleteLogicalPlan(ctx *plancontext.PlanningContext, rb *operators.Rout _ = updateSelectedVindexPredicate(rb.Routing) edml := createDMLPrimitive(ctx, rb, hints, del.Target.VTable, generateQuery(stmt), vindexes, vQuery) - return &primitiveWrapper{prim: &engine.Delete{DML: edml}}, nil + return &engine.Delete{DML: edml}, nil } func createDMLPrimitive(ctx *plancontext.PlanningContext, rb *operators.Route, hints *queryHints, vTbl *vindexes.Table, query string, colVindexes []*vindexes.ColumnVindex, vindexQuery string) *engine.DML { @@ -855,28 +834,26 @@ func getAllTableNames(op *operators.Route) ([]string, error) { return tableNames, nil } -func transformUnionPlan(ctx *plancontext.PlanningContext, op *operators.Union) (logicalPlan, error) { +func transformUnionPlan(ctx *plancontext.PlanningContext, op *operators.Union) (engine.Primitive, error) { sources, err := slice.MapWithError(op.Sources, func(src operators.Operator) (engine.Primitive, error) { - plan, err := transformToLogicalPlan(ctx, src) + primitive, err := transformToLogicalPlan(ctx, src) if err != nil { return nil, err } - return plan.Primitive(), nil + return primitive, nil }) if err != nil { return nil, err } if len(sources) == 1 { - return &primitiveWrapper{prim: sources[0]}, nil + return sources[0], nil } - return &primitiveWrapper{ - prim: engine.NewConcatenate(sources, nil), - }, nil + return engine.NewConcatenate(sources, nil), nil } -func transformLimit(ctx *plancontext.PlanningContext, op *operators.Limit) (logicalPlan, error) { +func transformLimit(ctx *plancontext.PlanningContext, op *operators.Limit) (engine.Primitive, error) { plan, err := transformToLogicalPlan(ctx, op.Source) if err != nil { return nil, err @@ -885,7 +862,7 @@ func transformLimit(ctx *plancontext.PlanningContext, op *operators.Limit) (logi return createLimit(plan, op.AST, ctx.VSchema.Environment(), ctx.VSchema.ConnCollation()) } -func createLimit(input logicalPlan, limit *sqlparser.Limit, env *vtenv.Environment, coll collations.ID) (logicalPlan, error) { +func createLimit(input engine.Primitive, limit *sqlparser.Limit, env *vtenv.Environment, coll collations.ID) (engine.Primitive, error) { cfg := &evalengine.Config{ Collation: coll, Environment: env, @@ -902,14 +879,14 @@ func createLimit(input logicalPlan, limit *sqlparser.Limit, env *vtenv.Environme } } - return &primitiveWrapper{prim: &engine.Limit{ + return &engine.Limit{ + Input: input, Count: count, Offset: offset, - Input: input.Primitive(), - }}, nil + }, nil } -func transformHashJoin(ctx *plancontext.PlanningContext, op *operators.HashJoin) (logicalPlan, error) { +func transformHashJoin(ctx *plancontext.PlanningContext, op *operators.HashJoin) (engine.Primitive, error) { lhs, err := transformToLogicalPlan(ctx, op.LHS) if err != nil { return nil, err @@ -949,24 +926,22 @@ func transformHashJoin(ctx *plancontext.PlanningContext, op *operators.HashJoin) return nil, err } - return &primitiveWrapper{ - prim: &engine.HashJoin{ - Left: lhs.Primitive(), - Right: rhs.Primitive(), - Opcode: joinOp, - Cols: op.ColumnOffsets, - LHSKey: op.LHSKeys[0], - RHSKey: op.RHSKeys[0], - ASTPred: op.JoinPredicate(), - Collation: comparisonType.Collation(), - ComparisonType: comparisonType.Type(), - CollationEnv: ctx.VSchema.Environment().CollationEnv(), - Values: comparisonType.Values(), - }, + return &engine.HashJoin{ + Left: lhs, + Right: rhs, + Opcode: joinOp, + Cols: op.ColumnOffsets, + LHSKey: op.LHSKeys[0], + RHSKey: op.RHSKeys[0], + ASTPred: op.JoinPredicate(), + Collation: comparisonType.Collation(), + ComparisonType: comparisonType.Type(), + CollationEnv: ctx.VSchema.Environment().CollationEnv(), + Values: comparisonType.Values(), }, nil } -func transformVindexPlan(ctx *plancontext.PlanningContext, op *operators.Vindex) (logicalPlan, error) { +func transformVindexPlan(ctx *plancontext.PlanningContext, op *operators.Vindex) (engine.Primitive, error) { single, ok := op.Vindex.(vindexes.SingleColumn) if !ok { return nil, vterrors.VT12001("multi-column vindexes not supported") @@ -995,7 +970,7 @@ func transformVindexPlan(ctx *plancontext.PlanningContext, op *operators.Vindex) return nil, err } } - return &primitiveWrapper{prim: prim}, nil + return prim, nil } func generateQuery(statement sqlparser.Statement) string { diff --git a/go/vt/vtgate/planbuilder/planner.go b/go/vt/vtgate/planbuilder/planner.go index e4eab447115..cf4e110913d 100644 --- a/go/vt/vtgate/planbuilder/planner.go +++ b/go/vt/vtgate/planbuilder/planner.go @@ -45,7 +45,7 @@ func gen4Planner(query string, plannerVersion querypb.ExecuteOptions_PlannerVers } // setCommentDirectivesOnPlan adds comments to queries -func setCommentDirectivesOnPlan(plan logicalPlan, stmt sqlparser.Statement) { +func setCommentDirectivesOnPlan(plan engine.Primitive, stmt sqlparser.Statement) { var directives *sqlparser.CommentDirectives cmt, ok := stmt.(sqlparser.Commented) if !ok { @@ -57,10 +57,7 @@ func setCommentDirectivesOnPlan(plan logicalPlan, stmt sqlparser.Statement) { timeout := queryTimeout(directives) multiShardAutoCommit := directives.IsSet(sqlparser.DirectiveMultiShardAutocommit) - switch plan := plan.(type) { - case *primitiveWrapper: - setDirective(plan.prim, multiShardAutoCommit, timeout, scatterAsWarns) - } + setDirective(plan, multiShardAutoCommit, timeout, scatterAsWarns) } func setDirective(prim engine.Primitive, msac bool, timeout int, scatterAsWarns bool) { diff --git a/go/vt/vtgate/planbuilder/primitive_wrapper.go b/go/vt/vtgate/planbuilder/primitive_wrapper.go deleted file mode 100644 index a03c94ce850..00000000000 --- a/go/vt/vtgate/planbuilder/primitive_wrapper.go +++ /dev/null @@ -1,32 +0,0 @@ -/* -Copyright 2022 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/vtgate/engine" -) - -// primitiveWrapper is used when only need a logical plan that supports plan.Primitive() and nothing else -type primitiveWrapper struct { - prim engine.Primitive -} - -func (p *primitiveWrapper) Primitive() engine.Primitive { - return p.prim -} - -var _ logicalPlan = (*primitiveWrapper)(nil) diff --git a/go/vt/vtgate/planbuilder/select.go b/go/vt/vtgate/planbuilder/select.go index 917e692ee54..25d0ffa8510 100644 --- a/go/vt/vtgate/planbuilder/select.go +++ b/go/vt/vtgate/planbuilder/select.go @@ -62,7 +62,7 @@ func gen4SelectStmtPlanner( sel.SQLCalcFoundRows = false } - getPlan := func(selStatement sqlparser.SelectStatement) (logicalPlan, []string, error) { + getPlan := func(selStatement sqlparser.SelectStatement) (engine.Primitive, []string, error) { return newBuildSelectPlan(selStatement, reservedVars, vschema, plannerVersion) } @@ -74,15 +74,14 @@ func gen4SelectStmtPlanner( if shouldRetryAfterPredicateRewriting(plan) { // by transforming the predicates to CNF, the planner will sometimes find better plans // TODO: this should move to the operator side of planning - plan2, tablesUsed := gen4PredicateRewrite(stmt, getPlan) - if plan2 != nil { - return newPlanResult(plan2.Primitive(), tablesUsed...), nil + prim2, tablesUsed := gen4PredicateRewrite(stmt, getPlan) + if prim2 != nil { + return newPlanResult(prim2, tablesUsed...), nil } } - primitive := plan.Primitive() if !isSel { - return newPlanResult(primitive, tablesUsed...), nil + return newPlanResult(plan, tablesUsed...), nil } // this is done because engine.Route doesn't handle the empty result well @@ -90,14 +89,14 @@ func gen4SelectStmtPlanner( // All other engine primitives can handle this, so we only need it when // Route is the last (and only) instruction before the user sees a result if isOnlyDual(sel) || (sel.GroupBy == nil && sel.SelectExprs.AllAggregation()) { - switch prim := primitive.(type) { + switch prim := plan.(type) { case *engine.Route: prim.NoRoutesSpecialHandling = true case *engine.VindexLookup: prim.SendTo.NoRoutesSpecialHandling = true } } - return newPlanResult(primitive, tablesUsed...), nil + return newPlanResult(plan, tablesUsed...), nil } func gen4planSQLCalcFoundRows(vschema plancontext.VSchema, sel *sqlparser.Select, query string, reservedVars *sqlparser.ReservedVars) (*planResult, error) { @@ -116,7 +115,7 @@ func gen4planSQLCalcFoundRows(vschema plancontext.VSchema, sel *sqlparser.Select if err != nil { return nil, err } - return newPlanResult(plan.Primitive(), tablesUsed...), nil + return newPlanResult(plan, tablesUsed...), nil } func buildSQLCalcFoundRowsPlan( @@ -124,7 +123,7 @@ func buildSQLCalcFoundRowsPlan( sel *sqlparser.Select, reservedVars *sqlparser.ReservedVars, vschema plancontext.VSchema, -) (logicalPlan, []string, error) { +) (engine.Primitive, []string, error) { limitPlan, _, err := newBuildSelectPlan(sel, reservedVars, vschema, Gen4) if err != nil { return nil, nil, err @@ -170,21 +169,18 @@ func buildSQLCalcFoundRowsPlan( return nil, nil, err } - countPrim := countPlan.Primitive() - rb, ok := countPrim.(*engine.Route) + rb, ok := countPlan.(*engine.Route) if ok { // if our count query is an aggregation, we want the no-match result to still return a zero rb.NoRoutesSpecialHandling = true } - lp := &primitiveWrapper{&engine.SQLCalcFoundRows{ - LimitPrimitive: limitPlan.Primitive(), - CountPrimitive: countPrim, - }} - - return lp, tablesUsed, nil + return &engine.SQLCalcFoundRows{ + LimitPrimitive: limitPlan, + CountPrimitive: countPlan, + }, tablesUsed, nil } -func gen4PredicateRewrite(stmt sqlparser.Statement, getPlan func(selStatement sqlparser.SelectStatement) (logicalPlan, []string, error)) (logicalPlan, []string) { +func gen4PredicateRewrite(stmt sqlparser.Statement, getPlan func(selStatement sqlparser.SelectStatement) (engine.Primitive, []string, error)) (engine.Primitive, []string) { rewritten, isSel := sqlparser.RewritePredicate(stmt).(sqlparser.SelectStatement) if !isSel { // Fail-safe code, should never happen @@ -203,7 +199,7 @@ func newBuildSelectPlan( reservedVars *sqlparser.ReservedVars, vschema plancontext.VSchema, version querypb.ExecuteOptions_PlannerVersion, -) (plan logicalPlan, tablesUsed []string, err error) { +) (plan engine.Primitive, tablesUsed []string, err error) { ctx, err := plancontext.CreatePlanningContext(selStmt, reservedVars, vschema, version) if err != nil { return nil, nil, err @@ -263,28 +259,16 @@ func isOnlyDual(sel *sqlparser.Select) bool { return ok && tableName.Name.String() == "dual" && tableName.Qualifier.IsEmpty() } -func shouldRetryAfterPredicateRewriting(plan logicalPlan) bool { +func shouldRetryAfterPredicateRewriting(plan engine.Primitive) bool { // if we have a I_S query, but have not found table_schema or table_name, let's try CNF - var opcode engine.Opcode - var sysTableTableName map[string]evalengine.Expr - var sysTableTableSchema []evalengine.Expr - - switch routePlan := plan.(type) { - case *primitiveWrapper: - eroute, ok := routePlan.prim.(*engine.Route) - if !ok { - return false - } - opcode = eroute.Opcode - sysTableTableName = eroute.SysTableTableName - sysTableTableSchema = eroute.SysTableTableSchema + switch eroute := plan.(type) { + case *engine.Route: + return eroute.Opcode == engine.DBA && + len(eroute.SysTableTableName) == 0 && + len(eroute.SysTableTableSchema) == 0 default: return false } - - return opcode == engine.DBA && - len(sysTableTableName) == 0 && - len(sysTableTableSchema) == 0 } func handleDualSelects(sel *sqlparser.Select, vschema plancontext.VSchema) (engine.Primitive, error) { diff --git a/go/vt/vtgate/planbuilder/single_sharded_shortcut.go b/go/vt/vtgate/planbuilder/single_sharded_shortcut.go index b68defafe18..5d877cd341d 100644 --- a/go/vt/vtgate/planbuilder/single_sharded_shortcut.go +++ b/go/vt/vtgate/planbuilder/single_sharded_shortcut.go @@ -28,7 +28,7 @@ import ( "vitess.io/vitess/go/vt/vtgate/vindexes" ) -func selectUnshardedShortcut(ctx *plancontext.PlanningContext, stmt sqlparser.SelectStatement, ks *vindexes.Keyspace) (logicalPlan, []string, error) { +func selectUnshardedShortcut(ctx *plancontext.PlanningContext, stmt sqlparser.SelectStatement, ks *vindexes.Keyspace) (engine.Primitive, []string, error) { // this method is used when the query we are handling has all tables in the same unsharded keyspace sqlparser.SafeRewrite(stmt, nil, func(cursor *sqlparser.Cursor) bool { switch node := cursor.Node().(type) { @@ -57,7 +57,7 @@ func selectUnshardedShortcut(ctx *plancontext.PlanningContext, stmt sqlparser.Se if err != nil { return nil, nil, err } - return &primitiveWrapper{prim: prim}, operators.QualifiedTableNames(ks, tableNames), nil + return prim, operators.QualifiedTableNames(ks, tableNames), nil } func escapedTableNames(tableNames []sqlparser.TableName) []string { diff --git a/go/vt/vtgate/planbuilder/update.go b/go/vt/vtgate/planbuilder/update.go index 313f33b6bf1..192eb4cc444 100644 --- a/go/vt/vtgate/planbuilder/update.go +++ b/go/vt/vtgate/planbuilder/update.go @@ -61,7 +61,7 @@ func gen4UpdateStmtPlanner( if !ctx.SemTable.ForeignKeysPresent() { plan := updateUnshardedShortcut(updStmt, ks, tables) setCommentDirectivesOnPlan(plan, updStmt) - return newPlanResult(plan.Primitive(), operators.QualifiedTables(ks, tables)...), nil + return newPlanResult(plan, operators.QualifiedTables(ks, tables)...), nil } } @@ -79,10 +79,10 @@ func gen4UpdateStmtPlanner( return nil, err } - return newPlanResult(plan.Primitive(), operators.TablesUsed(op)...), nil + return newPlanResult(plan, operators.TablesUsed(op)...), nil } -func updateUnshardedShortcut(stmt *sqlparser.Update, ks *vindexes.Keyspace, tables []*vindexes.Table) logicalPlan { +func updateUnshardedShortcut(stmt *sqlparser.Update, ks *vindexes.Keyspace, tables []*vindexes.Table) engine.Primitive { edml := engine.NewDML() edml.Keyspace = ks edml.Opcode = engine.Unsharded @@ -90,5 +90,5 @@ func updateUnshardedShortcut(stmt *sqlparser.Update, ks *vindexes.Keyspace, tabl for _, tbl := range tables { edml.TableNames = append(edml.TableNames, tbl.Name.String()) } - return &primitiveWrapper{prim: &engine.Update{DML: edml}} + return &engine.Update{DML: edml} } From 0f3a7603f4b2a572fa4938eef86b46d222687d9a Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 24 May 2024 10:38:00 +0200 Subject: [PATCH 16/18] refactor: rename methods Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/delete.go | 2 +- go/vt/vtgate/planbuilder/insert.go | 2 +- .../planbuilder/operator_transformers.go | 78 +++++++++---------- go/vt/vtgate/planbuilder/select.go | 2 +- go/vt/vtgate/planbuilder/update.go | 2 +- 5 files changed, 43 insertions(+), 43 deletions(-) diff --git a/go/vt/vtgate/planbuilder/delete.go b/go/vt/vtgate/planbuilder/delete.go index ab0925e7194..239e7bae0ae 100644 --- a/go/vt/vtgate/planbuilder/delete.go +++ b/go/vt/vtgate/planbuilder/delete.go @@ -78,7 +78,7 @@ func gen4DeleteStmtPlanner( return nil, err } - plan, err := transformToLogicalPlan(ctx, op) + plan, err := transformToPrimitive(ctx, op) if err != nil { return nil, err } diff --git a/go/vt/vtgate/planbuilder/insert.go b/go/vt/vtgate/planbuilder/insert.go index 93167451c3d..80516871623 100644 --- a/go/vt/vtgate/planbuilder/insert.go +++ b/go/vt/vtgate/planbuilder/insert.go @@ -75,7 +75,7 @@ func gen4InsertStmtPlanner(version querypb.ExecuteOptions_PlannerVersion, insStm return nil, err } - plan, err := transformToLogicalPlan(ctx, op) + plan, err := transformToPrimitive(ctx, op) if err != nil { return nil, err } diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index 4abc35397ae..76c4ddd476c 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -37,7 +37,7 @@ import ( "vitess.io/vitess/go/vt/vtgate/vindexes" ) -func transformToLogicalPlan(ctx *plancontext.PlanningContext, op operators.Operator) (engine.Primitive, error) { +func transformToPrimitive(ctx *plancontext.PlanningContext, op operators.Operator) (engine.Primitive, error) { switch op := op.(type) { case *operators.Route: return transformRoutePlan(ctx, op) @@ -79,18 +79,18 @@ func transformToLogicalPlan(ctx *plancontext.PlanningContext, op operators.Opera return transformDMLWithInput(ctx, op) } - return nil, vterrors.VT13001(fmt.Sprintf("unknown type encountered: %T (transformToLogicalPlan)", op)) + return nil, vterrors.VT13001(fmt.Sprintf("unknown type encountered: %T (transformToPrimitive)", op)) } func transformDMLWithInput(ctx *plancontext.PlanningContext, op *operators.DMLWithInput) (engine.Primitive, error) { - input, err := transformToLogicalPlan(ctx, op.Source) + input, err := transformToPrimitive(ctx, op.Source) if err != nil { return nil, err } var dmls []engine.Primitive for _, dml := range op.DML { - del, err := transformToLogicalPlan(ctx, dml) + del, err := transformToPrimitive(ctx, dml) if err != nil { return nil, err } @@ -118,7 +118,7 @@ func transformUpsert(ctx *plancontext.PlanningContext, op *operators.Upsert) (en } func transformOneUpsert(ctx *plancontext.PlanningContext, source operators.UpsertSource) (iLp, uLp engine.Primitive, err error) { - iLp, err = transformToLogicalPlan(ctx, source.Insert) + iLp, err = transformToPrimitive(ctx, source.Insert) if err != nil { return } @@ -126,14 +126,14 @@ func transformOneUpsert(ctx *plancontext.PlanningContext, source operators.Upser if ok { ins.PreventAutoCommit = true } - uLp, err = transformToLogicalPlan(ctx, source.Update) + uLp, err = transformToPrimitive(ctx, source.Update) return } func transformSequential(ctx *plancontext.PlanningContext, op *operators.Sequential) (engine.Primitive, error) { var prims []engine.Primitive for _, source := range op.Sources { - prim, err := transformToLogicalPlan(ctx, source) + prim, err := transformToPrimitive(ctx, source) if err != nil { return nil, err } @@ -178,7 +178,7 @@ func transformInsertionSelection(ctx *plancontext.PlanningContext, op *operators eins.Prefix, _, eins.Suffix = generateInsertShardedQuery(ins.AST) - selectionPlan, err := transformToLogicalPlan(ctx, op.Select) + selectionPlan, err := transformToPrimitive(ctx, op.Select) if err != nil { return nil, err } @@ -187,18 +187,18 @@ func transformInsertionSelection(ctx *plancontext.PlanningContext, op *operators return eins, nil } -// transformFkCascade transforms a FkCascade operator into a logical plan. +// transformFkCascade transforms a FkCascade operator into an engine primitive func transformFkCascade(ctx *plancontext.PlanningContext, fkc *operators.FkCascade) (engine.Primitive, error) { - // We convert the parent operator to a logical plan. - parentLP, err := transformToLogicalPlan(ctx, fkc.Parent) + // We convert the parent operator to a primitive + parentLP, err := transformToPrimitive(ctx, fkc.Parent) if err != nil { return nil, nil } - // Once we have the parent logical plan, we can create the selection logical plan and the primitives for the children operators. + // Once we have the parent primitive, we can create the selection primitive and the primitives for the children operators. // For all of these, we don't need the semTable anymore. We set it to nil, to avoid using an incorrect one. ctx.SemTable = nil - selLP, err := transformToLogicalPlan(ctx, fkc.Selection) + selLP, err := transformToPrimitive(ctx, fkc.Selection) if err != nil { return nil, err } @@ -206,7 +206,7 @@ func transformFkCascade(ctx *plancontext.PlanningContext, fkc *operators.FkCasca // Go over the children and convert them to Primitives too. var children []*engine.FkChild for _, child := range fkc.Children { - childLP, err := transformToLogicalPlan(ctx, child.Op) + childLP, err := transformToPrimitive(ctx, child.Op) if err != nil { return nil, err } @@ -228,12 +228,12 @@ func transformFkCascade(ctx *plancontext.PlanningContext, fkc *operators.FkCasca } func transformSubQuery(ctx *plancontext.PlanningContext, op *operators.SubQuery) (engine.Primitive, error) { - outer, err := transformToLogicalPlan(ctx, op.Outer) + outer, err := transformToPrimitive(ctx, op.Outer) if err != nil { return nil, err } - inner, err := transformToLogicalPlan(ctx, op.Subquery) + inner, err := transformToPrimitive(ctx, op.Subquery) if err != nil { return nil, err } @@ -260,21 +260,21 @@ func transformSubQuery(ctx *plancontext.PlanningContext, op *operators.SubQuery) }, nil } -// transformFkVerify transforms a FkVerify operator into a logical plan. +// transformFkVerify transforms a FkVerify operator into a engine primitive func transformFkVerify(ctx *plancontext.PlanningContext, fkv *operators.FkVerify) (engine.Primitive, error) { - inputLP, err := transformToLogicalPlan(ctx, fkv.Input) + inputLP, err := transformToPrimitive(ctx, fkv.Input) if err != nil { return nil, err } - // Once we have the input logical plan, we can create the primitives for the verification operators. + // Once we have the input primitive, we can create the primitives for the verification operators. // For all of these, we don't need the semTable anymore. We set it to nil, to avoid using an incorrect one. ctx.SemTable = nil // Go over the children and convert them to Primitives too. var verify []*engine.Verify for _, v := range fkv.Verify { - lp, err := transformToLogicalPlan(ctx, v.Op) + lp, err := transformToPrimitive(ctx, v.Op) if err != nil { return nil, err } @@ -295,7 +295,7 @@ func transformAggregator(ctx *plancontext.PlanningContext, op *operators.Aggrega if op.WithRollup { return nil, vterrors.VT12001("GROUP BY WITH ROLLUP not supported for sharded queries") } - src, err := transformToLogicalPlan(ctx, op.Source) + src, err := transformToPrimitive(ctx, op.Source) if err != nil { return nil, err } @@ -344,7 +344,7 @@ func transformAggregator(ctx *plancontext.PlanningContext, op *operators.Aggrega } func transformDistinct(ctx *plancontext.PlanningContext, op *operators.Distinct) (engine.Primitive, error) { - src, err := transformToLogicalPlan(ctx, op.Source) + src, err := transformToPrimitive(ctx, op.Source) if err != nil { return nil, err } @@ -357,7 +357,7 @@ func transformDistinct(ctx *plancontext.PlanningContext, op *operators.Distinct) } func transformOrdering(ctx *plancontext.PlanningContext, op *operators.Ordering) (engine.Primitive, error) { - plan, err := transformToLogicalPlan(ctx, op.Source) + plan, err := transformToPrimitive(ctx, op.Source) if err != nil { return nil, err } @@ -386,7 +386,7 @@ func createMemorySort(ctx *plancontext.PlanningContext, src engine.Primitive, or } func transformProjection(ctx *plancontext.PlanningContext, op *operators.Projection) (engine.Primitive, error) { - src, err := transformToLogicalPlan(ctx, op.Source) + src, err := transformToPrimitive(ctx, op.Source) if err != nil { return nil, err } @@ -456,7 +456,7 @@ func newSimpleProjection(cols []int, colNames []string, src engine.Primitive) en } func transformFilter(ctx *plancontext.PlanningContext, op *operators.Filter) (engine.Primitive, error) { - src, err := transformToLogicalPlan(ctx, op.Source) + src, err := transformToPrimitive(ctx, op.Source) if err != nil { return nil, err } @@ -475,11 +475,11 @@ func transformFilter(ctx *plancontext.PlanningContext, op *operators.Filter) (en } func transformApplyJoinPlan(ctx *plancontext.PlanningContext, n *operators.ApplyJoin) (engine.Primitive, error) { - lhs, err := transformToLogicalPlan(ctx, n.LHS) + lhs, err := transformToPrimitive(ctx, n.LHS) if err != nil { return nil, err } - rhs, err := transformToLogicalPlan(ctx, n.RHS) + rhs, err := transformToPrimitive(ctx, n.RHS) if err != nil { return nil, err } @@ -569,19 +569,19 @@ func transformRoutePlan(ctx *plancontext.PlanningContext, op *operators.Route) ( if op.Lock != sqlparser.NoLock { stmt.SetLock(op.Lock) } - return buildRouteLogicalPlan(ctx, op, stmt, hints) + return buildRoutePrimitive(ctx, op, stmt, hints) case *sqlparser.Update: - return buildUpdateLogicalPlan(ctx, op, dmlOp, stmt, hints) + return buildUpdatePrimitive(ctx, op, dmlOp, stmt, hints) case *sqlparser.Delete: - return buildDeleteLogicalPlan(ctx, op, dmlOp, stmt, hints) + return buildDeletePrimitive(ctx, op, dmlOp, stmt, hints) case *sqlparser.Insert: - return buildInsertLogicalPlan(op, dmlOp, stmt, hints) + return buildInsertPrimitive(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, hints *queryHints) (engine.Primitive, error) { +func buildRoutePrimitive(ctx *plancontext.PlanningContext, op *operators.Route, stmt sqlparser.SelectStatement, hints *queryHints) (engine.Primitive, error) { _ = updateSelectedVindexPredicate(op.Routing) eroute, err := routeToEngineRoute(ctx, op, hints) @@ -610,7 +610,7 @@ func buildRouteLogicalPlan(ctx *plancontext.PlanningContext, op *operators.Route return res, nil } -func buildInsertLogicalPlan( +func buildInsertPrimitive( rb *operators.Route, op operators.Operator, stmt *sqlparser.Insert, hints *queryHints, ) (engine.Primitive, error) { @@ -705,7 +705,7 @@ func dmlFormatter(buf *sqlparser.TrackedBuffer, node sqlparser.SQLNode) { node.Format(buf) } -func buildUpdateLogicalPlan( +func buildUpdatePrimitive( ctx *plancontext.PlanningContext, rb *operators.Route, dmlOp operators.Operator, @@ -736,7 +736,7 @@ func buildUpdateLogicalPlan( }, nil } -func buildDeleteLogicalPlan(ctx *plancontext.PlanningContext, rb *operators.Route, dmlOp operators.Operator, stmt *sqlparser.Delete, hints *queryHints) (engine.Primitive, error) { +func buildDeletePrimitive(ctx *plancontext.PlanningContext, rb *operators.Route, dmlOp operators.Operator, stmt *sqlparser.Delete, hints *queryHints) (engine.Primitive, error) { del := dmlOp.(*operators.Delete) var vindexes []*vindexes.ColumnVindex @@ -836,7 +836,7 @@ func getAllTableNames(op *operators.Route) ([]string, error) { func transformUnionPlan(ctx *plancontext.PlanningContext, op *operators.Union) (engine.Primitive, error) { sources, err := slice.MapWithError(op.Sources, func(src operators.Operator) (engine.Primitive, error) { - primitive, err := transformToLogicalPlan(ctx, src) + primitive, err := transformToPrimitive(ctx, src) if err != nil { return nil, err } @@ -854,7 +854,7 @@ func transformUnionPlan(ctx *plancontext.PlanningContext, op *operators.Union) ( } func transformLimit(ctx *plancontext.PlanningContext, op *operators.Limit) (engine.Primitive, error) { - plan, err := transformToLogicalPlan(ctx, op.Source) + plan, err := transformToPrimitive(ctx, op.Source) if err != nil { return nil, err } @@ -887,11 +887,11 @@ func createLimit(input engine.Primitive, limit *sqlparser.Limit, env *vtenv.Envi } func transformHashJoin(ctx *plancontext.PlanningContext, op *operators.HashJoin) (engine.Primitive, error) { - lhs, err := transformToLogicalPlan(ctx, op.LHS) + lhs, err := transformToPrimitive(ctx, op.LHS) if err != nil { return nil, err } - rhs, err := transformToLogicalPlan(ctx, op.RHS) + rhs, err := transformToPrimitive(ctx, op.RHS) if err != nil { return nil, err } diff --git a/go/vt/vtgate/planbuilder/select.go b/go/vt/vtgate/planbuilder/select.go index 25d0ffa8510..01dfd8aa387 100644 --- a/go/vt/vtgate/planbuilder/select.go +++ b/go/vt/vtgate/planbuilder/select.go @@ -224,7 +224,7 @@ func newBuildSelectPlan( return nil, nil, err } - plan, err = transformToLogicalPlan(ctx, op) + plan, err = transformToPrimitive(ctx, op) if err != nil { return nil, nil, err } diff --git a/go/vt/vtgate/planbuilder/update.go b/go/vt/vtgate/planbuilder/update.go index 192eb4cc444..d653df867fb 100644 --- a/go/vt/vtgate/planbuilder/update.go +++ b/go/vt/vtgate/planbuilder/update.go @@ -74,7 +74,7 @@ func gen4UpdateStmtPlanner( return nil, err } - plan, err := transformToLogicalPlan(ctx, op) + plan, err := transformToPrimitive(ctx, op) if err != nil { return nil, err } From 72e6d634c3d20afb1231ec433daa0993c7f411c0 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 24 May 2024 15:26:35 +0200 Subject: [PATCH 17/18] clean up: remove unused interface and implementation Signed-off-by: Andres Taylor --- go/vt/vtgate/engine/memory_sort.go | 5 ----- go/vt/vtgate/engine/ordered_aggregate.go | 5 ----- go/vt/vtgate/engine/route.go | 5 ----- go/vt/vtgate/planbuilder/builder.go | 4 ---- 4 files changed, 19 deletions(-) diff --git a/go/vt/vtgate/engine/memory_sort.go b/go/vt/vtgate/engine/memory_sort.go index 4e222498f26..d9919045eaf 100644 --- a/go/vt/vtgate/engine/memory_sort.go +++ b/go/vt/vtgate/engine/memory_sort.go @@ -59,11 +59,6 @@ func (ms *MemorySort) GetTableName() string { return ms.Input.GetTableName() } -// SetTruncateColumnCount sets the truncate column count. -func (ms *MemorySort) SetTruncateColumnCount(count int) { - ms.TruncateColumnCount = count -} - // TryExecute satisfies the Primitive interface. func (ms *MemorySort) TryExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) { count, err := ms.fetchCount(ctx, vcursor, bindVars) diff --git a/go/vt/vtgate/engine/ordered_aggregate.go b/go/vt/vtgate/engine/ordered_aggregate.go index f02fb1b8002..b67483216cf 100644 --- a/go/vt/vtgate/engine/ordered_aggregate.go +++ b/go/vt/vtgate/engine/ordered_aggregate.go @@ -94,11 +94,6 @@ func (oa *OrderedAggregate) GetTableName() string { return oa.Input.GetTableName() } -// SetTruncateColumnCount sets the truncate column count. -func (oa *OrderedAggregate) SetTruncateColumnCount(count int) { - oa.TruncateColumnCount = count -} - // TryExecute is a Primitive function. func (oa *OrderedAggregate) TryExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, _ bool) (*sqltypes.Result, error) { qr, err := oa.execute(ctx, vcursor, bindVars) diff --git a/go/vt/vtgate/engine/route.go b/go/vt/vtgate/engine/route.go index a45329c8e84..f28dda01a52 100644 --- a/go/vt/vtgate/engine/route.go +++ b/go/vt/vtgate/engine/route.go @@ -128,11 +128,6 @@ func (route *Route) GetTableName() string { return route.TableName } -// SetTruncateColumnCount sets the truncate column count. -func (route *Route) SetTruncateColumnCount(count int) { - route.TruncateColumnCount = count -} - // TryExecute performs a non-streaming exec. func (route *Route) TryExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (*sqltypes.Result, error) { ctx, cancelFunc := addQueryTimeout(ctx, vcursor, route.QueryTimeout) diff --git a/go/vt/vtgate/planbuilder/builder.go b/go/vt/vtgate/planbuilder/builder.go index e79e19ee96b..5d1d4ecd622 100644 --- a/go/vt/vtgate/planbuilder/builder.go +++ b/go/vt/vtgate/planbuilder/builder.go @@ -47,10 +47,6 @@ var ( ) type ( - truncater interface { - SetTruncateColumnCount(int) - } - planResult struct { primitive engine.Primitive tables []string From 7af4f5f7a847be5fd43abbdf4ee6d4ce3a3a4100 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 24 May 2024 15:30:17 +0200 Subject: [PATCH 18/18] refactor: if condition always false Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/ddl.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/go/vt/vtgate/planbuilder/ddl.go b/go/vt/vtgate/planbuilder/ddl.go index 41c868c7450..351bf42672c 100644 --- a/go/vt/vtgate/planbuilder/ddl.go +++ b/go/vt/vtgate/planbuilder/ddl.go @@ -230,9 +230,6 @@ func buildCreateViewCommon( sqlparser.RemoveKeyspace(ddl) if vschema.IsViewsEnabled() { - if keyspace == nil { - return nil, nil, vterrors.VT09005() - } return destination, keyspace, nil } isRoutePlan, opCode := tryToGetRoutePlan(selectPlan.primitive)