diff --git a/go/vt/vtgate/planbuilder/concatenate.go b/go/vt/vtgate/planbuilder/concatenate.go index b482e795845..93cb30d5935 100644 --- a/go/vt/vtgate/planbuilder/concatenate.go +++ b/go/vt/vtgate/planbuilder/concatenate.go @@ -54,12 +54,12 @@ func (c *concatenate) Wireup(plan logicalPlan, jt *jointab) error { return c.rhs.Wireup(plan, jt) } -func (c *concatenate) WireupV4(semTable *semantics.SemTable) error { - err := c.lhs.WireupV4(semTable) +func (c *concatenate) WireupGen4(semTable *semantics.SemTable) error { + err := c.lhs.WireupGen4(semTable) if err != nil { return err } - return c.rhs.WireupV4(semTable) + return c.rhs.WireupGen4(semTable) } func (c *concatenate) SupplyVar(from, to int, col *sqlparser.ColName, varname string) { diff --git a/go/vt/vtgate/planbuilder/expr.go b/go/vt/vtgate/planbuilder/expr.go index 1b14122fb0c..5adbf2c4fac 100644 --- a/go/vt/vtgate/planbuilder/expr.go +++ b/go/vt/vtgate/planbuilder/expr.go @@ -71,8 +71,8 @@ type subqueryInfo struct { // origin is chosen as the default. func (pb *primitiveBuilder) findOrigin(expr sqlparser.Expr, reservedVars *sqlparser.ReservedVars) (pullouts []*pulloutSubquery, origin logicalPlan, pushExpr sqlparser.Expr, err error) { // highestOrigin tracks the highest origin referenced by the expression. - // Default is the First. - highestOrigin := First(pb.plan) + // Default is the first. + highestOrigin := first(pb.plan) // subqueries tracks the list of subqueries encountered. var subqueries []subqueryInfo diff --git a/go/vt/vtgate/planbuilder/join.go b/go/vt/vtgate/planbuilder/join.go index 4da9fd5a9f8..f8bcbabeb20 100644 --- a/go/vt/vtgate/planbuilder/join.go +++ b/go/vt/vtgate/planbuilder/join.go @@ -154,12 +154,12 @@ func (jb *join) Wireup(plan logicalPlan, jt *jointab) error { } // Wireup2 implements the logicalPlan interface -func (jb *join) WireupV4(semTable *semantics.SemTable) error { - err := jb.Right.WireupV4(semTable) +func (jb *join) WireupGen4(semTable *semantics.SemTable) error { + err := jb.Right.WireupGen4(semTable) if err != nil { return err } - return jb.Left.WireupV4(semTable) + return jb.Left.WireupGen4(semTable) } // SupplyVar implements the logicalPlan interface diff --git a/go/vt/vtgate/planbuilder/join2.go b/go/vt/vtgate/planbuilder/joinGen4.go similarity index 66% rename from go/vt/vtgate/planbuilder/join2.go rename to go/vt/vtgate/planbuilder/joinGen4.go index 7b273c88865..5f406f517de 100644 --- a/go/vt/vtgate/planbuilder/join2.go +++ b/go/vt/vtgate/planbuilder/joinGen4.go @@ -22,11 +22,11 @@ import ( "vitess.io/vitess/go/vt/vtgate/semantics" ) -var _ logicalPlan = (*joinV4)(nil) +var _ logicalPlan = (*joinGen4)(nil) -// joinV4 is used to build a Join primitive. -// It's used to build an inner join and only used by the V4 planner -type joinV4 struct { +// joinGen4 is used to build a Join primitive. +// It's used to build an inner join and only used by the Gen4 planner +type joinGen4 struct { // Left and Right are the nodes for the join. Left, Right logicalPlan Cols []int @@ -34,51 +34,51 @@ type joinV4 struct { } // Order implements the logicalPlan interface -func (j *joinV4) Order() int { +func (j *joinGen4) Order() int { panic("implement me") } // ResultColumns implements the logicalPlan interface -func (j *joinV4) ResultColumns() []*resultColumn { +func (j *joinGen4) ResultColumns() []*resultColumn { panic("implement me") } // Reorder implements the logicalPlan interface -func (j *joinV4) Reorder(i int) { +func (j *joinGen4) Reorder(i int) { panic("implement me") } // Wireup implements the logicalPlan interface -func (j *joinV4) Wireup(lp logicalPlan, jt *jointab) error { +func (j *joinGen4) Wireup(lp logicalPlan, jt *jointab) error { panic("implement me") } // Wireup2 implements the logicalPlan interface -func (j *joinV4) WireupV4(semTable *semantics.SemTable) error { - err := j.Left.WireupV4(semTable) +func (j *joinGen4) WireupGen4(semTable *semantics.SemTable) error { + err := j.Left.WireupGen4(semTable) if err != nil { return err } - return j.Right.WireupV4(semTable) + return j.Right.WireupGen4(semTable) } // SupplyVar implements the logicalPlan interface -func (j *joinV4) SupplyVar(from, to int, col *sqlparser.ColName, varname string) { +func (j *joinGen4) SupplyVar(from, to int, col *sqlparser.ColName, varname string) { panic("implement me") } // SupplyCol implements the logicalPlan interface -func (j *joinV4) SupplyCol(col *sqlparser.ColName) (rc *resultColumn, colNumber int) { +func (j *joinGen4) SupplyCol(col *sqlparser.ColName) (rc *resultColumn, colNumber int) { panic("implement me") } // SupplyWeightString implements the logicalPlan interface -func (j *joinV4) SupplyWeightString(colNumber int) (weightcolNumber int, err error) { +func (j *joinGen4) SupplyWeightString(colNumber int) (weightcolNumber int, err error) { panic("implement me") } // Primitive implements the logicalPlan interface -func (j *joinV4) Primitive() engine.Primitive { +func (j *joinGen4) Primitive() engine.Primitive { return &engine.Join{ Left: j.Left.Primitive(), Right: j.Right.Primitive(), @@ -88,16 +88,16 @@ func (j *joinV4) Primitive() engine.Primitive { } // Inputs implements the logicalPlan interface -func (j *joinV4) Inputs() []logicalPlan { +func (j *joinGen4) Inputs() []logicalPlan { panic("implement me") } // Rewrite implements the logicalPlan interface -func (j *joinV4) Rewrite(inputs ...logicalPlan) error { +func (j *joinGen4) Rewrite(inputs ...logicalPlan) error { panic("implement me") } // Solves implements the logicalPlan interface -func (j *joinV4) ContainsTables() semantics.TableSet { +func (j *joinGen4) ContainsTables() semantics.TableSet { return j.Left.ContainsTables().Merge(j.Right.ContainsTables()) } diff --git a/go/vt/vtgate/planbuilder/jointree_transformers.go b/go/vt/vtgate/planbuilder/jointree_transformers.go index f190eae16e0..4583f2ea738 100644 --- a/go/vt/vtgate/planbuilder/jointree_transformers.go +++ b/go/vt/vtgate/planbuilder/jointree_transformers.go @@ -50,7 +50,7 @@ func transformJoinPlan(n *joinPlan, semTable *semantics.SemTable) (logicalPlan, if err != nil { return nil, err } - return &joinV4{ + return &joinGen4{ Left: lhs, Right: rhs, Cols: n.columns, diff --git a/go/vt/vtgate/planbuilder/logical_plan.go b/go/vt/vtgate/planbuilder/logical_plan.go index 81e4fae0aa2..00ee488a2cf 100644 --- a/go/vt/vtgate/planbuilder/logical_plan.go +++ b/go/vt/vtgate/planbuilder/logical_plan.go @@ -49,8 +49,8 @@ type logicalPlan interface { // the lhs nodes. Wireup(lp logicalPlan, jt *jointab) error - // WireupV4 does the wire up work for the V4 planner - WireupV4(semTable *semantics.SemTable) error + // WireupGen4 does the wire up work for the Gen4 planner + WireupGen4(semTable *semantics.SemTable) error // SupplyVar finds the common root between from and to. If it's // the common root, it supplies the requested var to the rhs tree. @@ -83,7 +83,7 @@ type logicalPlan interface { Rewrite(inputs ...logicalPlan) error // ContainsTables keeps track which query tables are being solved by this logical plan - // This is only applicable for plans that have been built with the V4 planner + // This is only applicable for plans that have been built with the Gen4 planner ContainsTables() semantics.TableSet } @@ -118,14 +118,14 @@ func visit(node logicalPlan, visitor planVisitor) (logicalPlan, error) { return node, nil } -// First returns the first logical plan of the tree, +// first returns the first logical plan of the tree, // which is usually the left most leaf. -func First(input logicalPlan) logicalPlan { +func first(input logicalPlan) logicalPlan { inputs := input.Inputs() if len(inputs) == 0 { return input } - return First(inputs[0]) + return first(inputs[0]) } //------------------------------------------------------------------------- @@ -158,8 +158,8 @@ func (bc *logicalPlanCommon) Wireup(plan logicalPlan, jt *jointab) error { return bc.input.Wireup(plan, jt) } -func (bc *logicalPlanCommon) WireupV4(semTable *semantics.SemTable) error { - return bc.input.WireupV4(semTable) +func (bc *logicalPlanCommon) WireupGen4(semTable *semantics.SemTable) error { + return bc.input.WireupGen4(semTable) } func (bc *logicalPlanCommon) SupplyVar(from, to int, col *sqlparser.ColName, varname string) { diff --git a/go/vt/vtgate/planbuilder/memory_sort.go b/go/vt/vtgate/planbuilder/memory_sort.go index fe741c631c1..8f06423699f 100644 --- a/go/vt/vtgate/planbuilder/memory_sort.go +++ b/go/vt/vtgate/planbuilder/memory_sort.go @@ -136,6 +136,6 @@ func (ms *memorySort) Wireup(plan logicalPlan, jt *jointab) error { return ms.input.Wireup(plan, jt) } -func (ms *memorySort) WireupV4(semTable *semantics.SemTable) error { - return ms.input.WireupV4(semTable) +func (ms *memorySort) WireupGen4(semTable *semantics.SemTable) error { + return ms.input.WireupGen4(semTable) } diff --git a/go/vt/vtgate/planbuilder/merge_sort.go b/go/vt/vtgate/planbuilder/merge_sort.go index 1fea7894cc4..76915f3b623 100644 --- a/go/vt/vtgate/planbuilder/merge_sort.go +++ b/go/vt/vtgate/planbuilder/merge_sort.go @@ -89,6 +89,6 @@ func (ms *mergeSort) Wireup(plan logicalPlan, jt *jointab) error { return ms.input.Wireup(plan, jt) } -func (ms *mergeSort) WireupV4(semTable *semantics.SemTable) error { - return ms.input.WireupV4(semTable) +func (ms *mergeSort) WireupGen4(semTable *semantics.SemTable) error { + return ms.input.WireupGen4(semTable) } diff --git a/go/vt/vtgate/planbuilder/ordered_aggregate.go b/go/vt/vtgate/planbuilder/ordered_aggregate.go index 3aec72a52f0..e3a82a08f47 100644 --- a/go/vt/vtgate/planbuilder/ordered_aggregate.go +++ b/go/vt/vtgate/planbuilder/ordered_aggregate.go @@ -354,6 +354,6 @@ func (oa *orderedAggregate) Wireup(plan logicalPlan, jt *jointab) error { return oa.input.Wireup(plan, jt) } -func (oa *orderedAggregate) WireupV4(semTable *semantics.SemTable) error { - return oa.input.WireupV4(semTable) +func (oa *orderedAggregate) WireupGen4(semTable *semantics.SemTable) error { + return oa.input.WireupGen4(semTable) } diff --git a/go/vt/vtgate/planbuilder/plan_test.go b/go/vt/vtgate/planbuilder/plan_test.go index 4e9fddf8c8e..9c35d472c48 100644 --- a/go/vt/vtgate/planbuilder/plan_test.go +++ b/go/vt/vtgate/planbuilder/plan_test.go @@ -441,7 +441,7 @@ func escapeNewLines(in string) string { return strings.ReplaceAll(in, "\n", "\\n") } -func testFile(t *testing.T, filename, tempDir string, vschema *vschemaWrapper, checkV4equalPlan bool) { +func testFile(t *testing.T, filename, tempDir string, vschema *vschemaWrapper, checkGen4equalPlan bool) { var checkAllTests = false t.Run(filename, func(t *testing.T) { expected := &strings.Builder{} @@ -478,14 +478,14 @@ func testFile(t *testing.T, filename, tempDir string, vschema *vschemaWrapper, c // - it produces a different but accepted plan - this is shown using the accepted plan // - or it produces a different plan that has not yet been accepted, or it fails to produce a plan // this is shown by not having any info at all after the result for the V3 planner - // with this last expectation, it is an error if the V4 planner + // with this last expectation, it is an error if the Gen4 planner // produces the same plan as the V3 planner does - testName := fmt.Sprintf("%d V4: %s", tcase.lineno, tcase.comments) + testName := fmt.Sprintf("%d Gen4: %s", tcase.lineno, tcase.comments) if !empty || checkAllTests { t.Run(testName, func(t *testing.T) { if out != tcase.output2ndPlanner { fail = true - t.Errorf("V4 - %s:%d\nDiff:\n%s\n[%s] \n[%s]", filename, tcase.lineno, cmp.Diff(tcase.output2ndPlanner, out), tcase.output, out) + t.Errorf("Gen4 - %s:%d\nDiff:\n%s\n[%s] \n[%s]", filename, tcase.lineno, cmp.Diff(tcase.output2ndPlanner, out), tcase.output, out) } if err != nil { @@ -499,9 +499,9 @@ func testFile(t *testing.T, filename, tempDir string, vschema *vschemaWrapper, c } }) } else { - if out == tcase.output && checkV4equalPlan { + if out == tcase.output && checkGen4equalPlan { t.Run(testName, func(t *testing.T) { - t.Errorf("V4 - %s:%d\nplanner produces same output as V3", filename, tcase.lineno) + t.Errorf("Gen4 - %s:%d\nplanner produces same output as V3", filename, tcase.lineno) }) } } @@ -658,10 +658,10 @@ func BenchmarkPlanner(b *testing.B) { b.Run(filename+"-v3", func(b *testing.B) { benchmarkPlanner(b, V3, testCases, vschema) }) - b.Run(filename+"-v4", func(b *testing.B) { + b.Run(filename+"-gen4", func(b *testing.B) { benchmarkPlanner(b, Gen4, testCases, vschema) }) - b.Run(filename+"-v4left2right", func(b *testing.B) { + b.Run(filename+"-gen4left2right", func(b *testing.B) { benchmarkPlanner(b, Gen4Left2Right, testCases, vschema) }) } diff --git a/go/vt/vtgate/planbuilder/pullout_subquery.go b/go/vt/vtgate/planbuilder/pullout_subquery.go index ec0862bcf0d..8b03ec852bd 100644 --- a/go/vt/vtgate/planbuilder/pullout_subquery.go +++ b/go/vt/vtgate/planbuilder/pullout_subquery.go @@ -88,11 +88,11 @@ func (ps *pulloutSubquery) Wireup(plan logicalPlan, jt *jointab) error { } // Wireup2 implements the logicalPlan interface -func (ps *pulloutSubquery) WireupV4(semTable *semantics.SemTable) error { - if err := ps.underlying.WireupV4(semTable); err != nil { +func (ps *pulloutSubquery) WireupGen4(semTable *semantics.SemTable) error { + if err := ps.underlying.WireupGen4(semTable); err != nil { return err } - return ps.subquery.WireupV4(semTable) + return ps.subquery.WireupGen4(semTable) } // SupplyVar implements the logicalPlan interface diff --git a/go/vt/vtgate/planbuilder/route.go b/go/vt/vtgate/planbuilder/route.go index 603e65a5d75..8267fe9f4e7 100644 --- a/go/vt/vtgate/planbuilder/route.go +++ b/go/vt/vtgate/planbuilder/route.go @@ -133,7 +133,7 @@ func (rb *route) SetLimit(limit *sqlparser.Limit) { } // Wireup2 implements the logicalPlan interface -func (rb *route) WireupV4(semTable *semantics.SemTable) error { +func (rb *route) WireupGen4(semTable *semantics.SemTable) error { rb.prepareTheAST() rb.eroute.Query = sqlparser.String(rb.Select) diff --git a/go/vt/vtgate/planbuilder/route_planning.go b/go/vt/vtgate/planbuilder/route_planning.go index 09c2fe57e25..13fe095fa7f 100644 --- a/go/vt/vtgate/planbuilder/route_planning.go +++ b/go/vt/vtgate/planbuilder/route_planning.go @@ -91,7 +91,7 @@ func newBuildSelectPlan(sel *sqlparser.Select, vschema ContextVSchema) (engine.P return nil, err } - if err := plan.WireupV4(semTable); err != nil { + if err := plan.WireupGen4(semTable); err != nil { return nil, err } return plan.Primitive(), nil diff --git a/go/vt/vtgate/planbuilder/select.go b/go/vt/vtgate/planbuilder/select.go index 45872e3f21a..b9d1f730f31 100644 --- a/go/vt/vtgate/planbuilder/select.go +++ b/go/vt/vtgate/planbuilder/select.go @@ -20,12 +20,8 @@ import ( "errors" "fmt" - "vitess.io/vitess/go/sqltypes" - "vitess.io/vitess/go/vt/orchestrator/external/golib/log" - "vitess.io/vitess/go/vt/vtgate/semantics" - "vitess.io/vitess/go/vt/key" vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" @@ -102,133 +98,6 @@ func shouldRetryWithCNFRewriting(plan logicalPlan) bool { } -func pushProjection(expr *sqlparser.AliasedExpr, plan logicalPlan, semTable *semantics.SemTable) (int, error) { - switch node := plan.(type) { - case *route: - sel := node.Select.(*sqlparser.Select) - offset := len(sel.SelectExprs) - sel.SelectExprs = append(sel.SelectExprs, expr) - return offset, nil - case *joinV4: - lhsSolves := node.Left.ContainsTables() - rhsSolves := node.Right.ContainsTables() - deps := semTable.Dependencies(expr.Expr) - switch { - case deps.IsSolvedBy(lhsSolves): - offset, err := pushProjection(expr, node.Left, semTable) - if err != nil { - return 0, err - } - node.Cols = append(node.Cols, -(offset + 1)) - case deps.IsSolvedBy(rhsSolves): - offset, err := pushProjection(expr, node.Right, semTable) - if err != nil { - return 0, err - } - node.Cols = append(node.Cols, offset+1) - default: - return 0, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "unknown dependencies for %s", sqlparser.String(expr)) - } - return len(node.Cols) - 1, nil - default: - return 0, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "%T not yet supported", node) - } -} - -func planAggregations(qp *queryProjection, plan logicalPlan, semTable *semantics.SemTable) (logicalPlan, error) { - eaggr := &engine.OrderedAggregate{} - oa := &orderedAggregate{ - resultsBuilder: newResultsBuilder(plan, eaggr), - eaggr: eaggr, - } - for _, e := range qp.aggrExprs { - offset, err := pushProjection(e, plan, semTable) - if err != nil { - return nil, err - } - fExpr := e.Expr.(*sqlparser.FuncExpr) - opcode := engine.SupportedAggregates[fExpr.Name.Lowered()] - oa.eaggr.Aggregates = append(oa.eaggr.Aggregates, engine.AggregateParams{ - Opcode: opcode, - Col: offset, - }) - } - return oa, nil -} - -func planOrderBy(qp *queryProjection, plan logicalPlan, semTable *semantics.SemTable) (logicalPlan, error) { - switch plan := plan.(type) { - case *route: - additionalColAdded := false - for _, order := range qp.orderExprs { - offset, exists := qp.orderExprColMap[order] - colName, ok := order.Expr.(*sqlparser.ColName) - if !ok { - return nil, semantics.Gen4NotSupportedF("order by non-column expression") - } - if !exists { - expr := &sqlparser.AliasedExpr{ - Expr: order.Expr, - } - var err error - offset, err = pushProjection(expr, plan, semTable) - if err != nil { - return nil, err - } - additionalColAdded = true - } - - table := semTable.Dependencies(colName) - tableInfo, err := semTable.TableInfoFor(table) - if err != nil { - return nil, err - } - weightStringNeeded := true - for _, c := range tableInfo.Table.Columns { - if colName.Name.Equal(c.Name) { - if sqltypes.IsNumber(c.Type) { - weightStringNeeded = false - } - break - } - } - - weightStringOffset := -1 - if weightStringNeeded { - expr := &sqlparser.AliasedExpr{ - Expr: &sqlparser.FuncExpr{ - Name: sqlparser.NewColIdent("weight_string"), - Exprs: []sqlparser.SelectExpr{ - &sqlparser.AliasedExpr{ - Expr: order.Expr, - }, - }, - }, - } - weightStringOffset, err = pushProjection(expr, plan, semTable) - if err != nil { - return nil, err - } - additionalColAdded = true - } - - plan.eroute.OrderBy = append(plan.eroute.OrderBy, engine.OrderbyParams{ - Col: offset, - WeightStringCol: weightStringOffset, - Desc: order.Direction == sqlparser.DescOrder, - }) - plan.Select.AddOrder(order) - } - if additionalColAdded { - plan.eroute.TruncateColumnCount = len(qp.selectExprs) + len(qp.aggrExprs) - } - - return plan, nil - default: - return nil, semantics.Gen4NotSupportedF("ordering on complex query") - } -} - var errSQLCalcFoundRows = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.CantUseOptionHere, "Incorrect usage/placement of 'SQL_CALC_FOUND_ROWS'") var errInto = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.CantUseOptionHere, "Incorrect usage/placement of 'INTO'") diff --git a/go/vt/vtgate/planbuilder/selectGen4.go b/go/vt/vtgate/planbuilder/selectGen4.go new file mode 100644 index 00000000000..bfa765917c1 --- /dev/null +++ b/go/vt/vtgate/planbuilder/selectGen4.go @@ -0,0 +1,156 @@ +/* +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/sqltypes" + + "vitess.io/vitess/go/vt/vtgate/semantics" + + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/vterrors" + + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vtgate/engine" +) + +func pushProjection(expr *sqlparser.AliasedExpr, plan logicalPlan, semTable *semantics.SemTable) (int, error) { + switch node := plan.(type) { + case *route: + sel := node.Select.(*sqlparser.Select) + offset := len(sel.SelectExprs) + sel.SelectExprs = append(sel.SelectExprs, expr) + return offset, nil + case *joinGen4: + lhsSolves := node.Left.ContainsTables() + rhsSolves := node.Right.ContainsTables() + deps := semTable.Dependencies(expr.Expr) + switch { + case deps.IsSolvedBy(lhsSolves): + offset, err := pushProjection(expr, node.Left, semTable) + if err != nil { + return 0, err + } + node.Cols = append(node.Cols, -(offset + 1)) + case deps.IsSolvedBy(rhsSolves): + offset, err := pushProjection(expr, node.Right, semTable) + if err != nil { + return 0, err + } + node.Cols = append(node.Cols, offset+1) + default: + return 0, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "unknown dependencies for %s", sqlparser.String(expr)) + } + return len(node.Cols) - 1, nil + default: + return 0, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "%T not yet supported", node) + } +} + +func planAggregations(qp *queryProjection, plan logicalPlan, semTable *semantics.SemTable) (logicalPlan, error) { + eaggr := &engine.OrderedAggregate{} + oa := &orderedAggregate{ + resultsBuilder: newResultsBuilder(plan, eaggr), + eaggr: eaggr, + } + for _, e := range qp.aggrExprs { + offset, err := pushProjection(e, plan, semTable) + if err != nil { + return nil, err + } + fExpr := e.Expr.(*sqlparser.FuncExpr) + opcode := engine.SupportedAggregates[fExpr.Name.Lowered()] + oa.eaggr.Aggregates = append(oa.eaggr.Aggregates, engine.AggregateParams{ + Opcode: opcode, + Col: offset, + }) + } + return oa, nil +} + +func planOrderBy(qp *queryProjection, plan logicalPlan, semTable *semantics.SemTable) (logicalPlan, error) { + switch plan := plan.(type) { + case *route: + additionalColAdded := false + for _, order := range qp.orderExprs { + offset, exists := qp.orderExprColMap[order] + colName, ok := order.Expr.(*sqlparser.ColName) + if !ok { + return nil, semantics.Gen4NotSupportedF("order by non-column expression") + } + if !exists { + expr := &sqlparser.AliasedExpr{ + Expr: order.Expr, + } + var err error + offset, err = pushProjection(expr, plan, semTable) + if err != nil { + return nil, err + } + additionalColAdded = true + } + + table := semTable.Dependencies(colName) + tableInfo, err := semTable.TableInfoFor(table) + if err != nil { + return nil, err + } + weightStringNeeded := true + for _, c := range tableInfo.Table.Columns { + if colName.Name.Equal(c.Name) { + if sqltypes.IsNumber(c.Type) { + weightStringNeeded = false + } + break + } + } + + weightStringOffset := -1 + if weightStringNeeded { + expr := &sqlparser.AliasedExpr{ + Expr: &sqlparser.FuncExpr{ + Name: sqlparser.NewColIdent("weight_string"), + Exprs: []sqlparser.SelectExpr{ + &sqlparser.AliasedExpr{ + Expr: order.Expr, + }, + }, + }, + } + weightStringOffset, err = pushProjection(expr, plan, semTable) + if err != nil { + return nil, err + } + additionalColAdded = true + } + + plan.eroute.OrderBy = append(plan.eroute.OrderBy, engine.OrderbyParams{ + Col: offset, + WeightStringCol: weightStringOffset, + Desc: order.Direction == sqlparser.DescOrder, + }) + plan.Select.AddOrder(order) + } + if additionalColAdded { + plan.eroute.TruncateColumnCount = len(qp.selectExprs) + len(qp.aggrExprs) + } + + return plan, nil + default: + return nil, semantics.Gen4NotSupportedF("ordering on complex query") + } +} diff --git a/go/vt/vtgate/planbuilder/sql_calc_found_rows.go b/go/vt/vtgate/planbuilder/sql_calc_found_rows.go index 21a7bae3d29..5534d20bee0 100644 --- a/go/vt/vtgate/planbuilder/sql_calc_found_rows.go +++ b/go/vt/vtgate/planbuilder/sql_calc_found_rows.go @@ -41,12 +41,12 @@ func (s *sqlCalcFoundRows) Wireup(logicalPlan, *jointab) error { } //Wireup2 implements the logicalPlan interface -func (s *sqlCalcFoundRows) WireupV4(semTable *semantics.SemTable) error { - err := s.LimitQuery.WireupV4(semTable) +func (s *sqlCalcFoundRows) WireupGen4(semTable *semantics.SemTable) error { + err := s.LimitQuery.WireupGen4(semTable) if err != nil { return err } - return s.CountQuery.WireupV4(semTable) + return s.CountQuery.WireupGen4(semTable) } // Solves implements the logicalPlan interface diff --git a/go/vt/vtgate/planbuilder/vindex_func.go b/go/vt/vtgate/planbuilder/vindex_func.go index 8d9a6d0a74a..217c0fc8c46 100644 --- a/go/vt/vtgate/planbuilder/vindex_func.go +++ b/go/vt/vtgate/planbuilder/vindex_func.go @@ -99,7 +99,7 @@ func (vf *vindexFunc) Wireup(logicalPlan, *jointab) error { } // Wireup2 implements the logicalPlan interface -func (vf *vindexFunc) WireupV4(*semantics.SemTable) error { +func (vf *vindexFunc) WireupGen4(*semantics.SemTable) error { return nil }