From ad06b8088a9817f30d9194bc658c0a287a43b8fd Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Thu, 6 Jul 2023 15:36:12 +0200 Subject: [PATCH 01/44] start moving UNION planning over to the operators Signed-off-by: Andres Taylor --- go/slices2/slices.go | 14 + go/vt/sqlparser/ast.go | 1 + go/vt/sqlparser/ast_funcs.go | 10 + .../planbuilder/operator_transformers.go | 283 +--- go/vt/vtgate/planbuilder/operators/ast2op.go | 3 + .../operators/horizon_expanding.go | 45 +- .../planbuilder/operators/horizon_planning.go | 12 +- go/vt/vtgate/planbuilder/operators/union.go | 99 +- .../ddl_cases_no_default_keyspace.json | 16 +- .../testdata/info_schema57_cases.json | 368 +++-- .../testdata/info_schema80_cases.json | 368 +++-- .../testdata/large_union_cases.json | 968 +---------- .../planbuilder/testdata/select_cases.json | 92 +- .../planbuilder/testdata/union_cases.json | 1463 +++++++---------- .../testdata/unsupported_cases.json | 2 +- 15 files changed, 1244 insertions(+), 2500 deletions(-) diff --git a/go/slices2/slices.go b/go/slices2/slices.go index 69e9cdc62d4..f5b091179cb 100644 --- a/go/slices2/slices.go +++ b/go/slices2/slices.go @@ -48,3 +48,17 @@ func Map[From, To any](in []From, f func(From) To) []To { } return result } + +func MapWithError[From, To any](in []From, f func(From) (To, error)) (result []To, err error) { + if in == nil { + return nil, nil + } + result = make([]To, len(in)) + for i, col := range in { + result[i], err = f(col) + if err != nil { + return nil, err + } + } + return +} diff --git a/go/vt/sqlparser/ast.go b/go/vt/sqlparser/ast.go index c80ba642218..e44898a0c8f 100644 --- a/go/vt/sqlparser/ast.go +++ b/go/vt/sqlparser/ast.go @@ -70,6 +70,7 @@ type ( GetColumnCount() int GetColumns() SelectExprs Commented + IsDistinct() bool } // DDLStatement represents any DDL Statement diff --git a/go/vt/sqlparser/ast_funcs.go b/go/vt/sqlparser/ast_funcs.go index 1d7ab540c12..63b0a9c4811 100644 --- a/go/vt/sqlparser/ast_funcs.go +++ b/go/vt/sqlparser/ast_funcs.go @@ -1067,6 +1067,11 @@ func (node *Select) MakeDistinct() { node.Distinct = true } +// IsDistinct implements the SelectStatement interface +func (node *Select) IsDistinct() bool { + return node.Distinct +} + // GetColumnCount return SelectExprs count. func (node *Select) GetColumnCount() int { return len(node.SelectExprs) @@ -1192,6 +1197,11 @@ func (node *Union) MakeDistinct() { node.Distinct = true } +// IsDistinct implements the SelectStatement interface +func (node *Union) IsDistinct() bool { + return node.Distinct +} + // GetColumnCount implements the SelectStatement interface func (node *Union) GetColumnCount() int { return node.Left.GetColumnCount() diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index c0fab8a820c..c1e392e55eb 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -23,7 +23,6 @@ import ( "strconv" "strings" - "vitess.io/vitess/go/mysql/collations" "vitess.io/vitess/go/slices2" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/sqlparser" @@ -45,7 +44,7 @@ func transformToLogicalPlan(ctx *plancontext.PlanningContext, op ops.Operator, i case *operators.ApplyJoin: return transformApplyJoinPlan(ctx, op) case *operators.Union: - return transformUnionPlan(ctx, op, isRoot) + return transformUnionPlan(ctx, op) case *operators.Vindex: return transformVindexPlan(ctx, op) case *operators.SubQueryOp: @@ -486,6 +485,7 @@ func generateInsertShardedQuery(ins *sqlparser.Insert) (prefix string, mid []str mid[rowNum] = midBuf.String() midBuf.Reset() } + return } @@ -636,224 +636,26 @@ func getAllTableNames(op *operators.Route) ([]string, error) { return tableNames, nil } -func transformUnionPlan(ctx *plancontext.PlanningContext, op *operators.Union, isRoot bool) (logicalPlan, error) { - var sources []logicalPlan - var err error - if op.Distinct { - sources, err = transformAndMerge(ctx, op) - if err != nil { - return nil, err - } - for _, source := range sources { - pushDistinct(source) - } - } else { - sources, err = transformAndMergeInOrder(ctx, op) - if err != nil { - return nil, err - } - } - var result logicalPlan - if len(sources) == 1 { - src := sources[0] - if rb, isRoute := src.(*route); isRoute && rb.isSingleShard() { - // if we have a single shard route, we don't need to do anything to make it distinct - // TODO - // rb.Select.SetLimit(op.limit) - // rb.Select.SetOrderBy(op.ordering) - return src, nil - } - result = src - } else { - if len(op.Ordering) > 0 { - return nil, vterrors.VT12001("ORDER BY on top of UNION") - } - result = &concatenate{sources: sources} - } - if op.Distinct { - colls := getCollationsFor(ctx, op) - checkCols, err := getCheckColsForUnion(ctx, result, colls) +func transformUnionPlan(ctx *plancontext.PlanningContext, op *operators.Union) (logicalPlan, error) { + sources, err := slices2.MapWithError(op.Sources, func(src ops.Operator) (logicalPlan, error) { + plan, err := transformToLogicalPlan(ctx, src, false) if err != nil { return nil, err } - return newDistinctGen4Legacy(result, checkCols, isRoot), nil - } - return result, nil - -} - -func getWeightStringForSelectExpr(selectExpr sqlparser.SelectExpr) (*sqlparser.AliasedExpr, error) { - expr, isAliased := selectExpr.(*sqlparser.AliasedExpr) - if !isAliased { - return nil, vterrors.VT12001("get weight string expression for non-aliased expression") - } - return &sqlparser.AliasedExpr{Expr: weightStringFor(expr.Expr)}, nil -} - -func getCheckColsForUnion(ctx *plancontext.PlanningContext, result logicalPlan, colls []collationInfo) ([]engine.CheckCol, error) { - checkCols := make([]engine.CheckCol, 0, len(colls)) - for i, coll := range colls { - checkCol := engine.CheckCol{Col: i, Type: coll.typ, Collation: coll.col} - if coll.typ >= 0 { - checkCols = append(checkCols, checkCol) - continue - } - // We might need a weight string - let's push one - // `might` because we just don't know what type we are dealing with. - // If we encounter a numerical value, we don't need any weight_string values - newOffset, err := pushWeightStringForDistinct(ctx, result, i) - if err != nil { - return nil, err - } - checkCol.WsCol = &newOffset - checkCols = append(checkCols, checkCol) - } - return checkCols, nil -} - -// pushWeightStringForDistinct adds a weight_string projection -func pushWeightStringForDistinct(ctx *plancontext.PlanningContext, plan logicalPlan, offset int) (newOffset int, err error) { - switch node := plan.(type) { - case *route: - allSelects := sqlparser.GetAllSelects(node.Select) - for _, sel := range allSelects { - expr, err := getWeightStringForSelectExpr(sel.SelectExprs[offset]) - if err != nil { - return 0, err - } - if i := checkIfAlreadyExists(expr, sel, ctx.SemTable); i != -1 { - return i, nil - } - sel.SelectExprs = append(sel.SelectExprs, expr) - newOffset = len(sel.SelectExprs) - 1 - } - // we leave the responsibility of truncating to distinct - node.eroute.TruncateColumnCount = 0 - case *concatenate: - for _, source := range node.sources { - newOffset, err = pushWeightStringForDistinct(ctx, source, offset) - if err != nil { - return 0, err - } - } - node.noNeedToTypeCheck = append(node.noNeedToTypeCheck, newOffset) - case *join: - joinOffset := node.Cols[offset] - switch { - case joinOffset < 0: - offset, err = pushWeightStringForDistinct(ctx, node.Left, -(joinOffset + 1)) - offset = -(offset + 1) - case joinOffset > 0: - offset, err = pushWeightStringForDistinct(ctx, node.Right, joinOffset-1) - offset = offset + 1 - default: - return 0, vterrors.VT13001("wrong column offset in join plan to push DISTINCT WEIGHT_STRING") - } - if err != nil { - return 0, err - } - newOffset = len(node.Cols) - node.Cols = append(node.Cols, offset) - default: - return 0, vterrors.VT13001(fmt.Sprintf("pushWeightStringForDistinct on %T", plan)) - } - return -} - -func transformAndMerge(ctx *plancontext.PlanningContext, op *operators.Union) (sources []logicalPlan, err error) { - for _, source := range op.Sources { - // first we go over all the operator inputs and turn them into logical plans, - // including horizon planning - plan, err := transformToLogicalPlan(ctx, source, false) - if err != nil { - return nil, err - } - sources = append(sources, plan) - } - - // next we'll go over all the plans from and check if any two can be merged. if they can, they are merged, - // and we continue checking for pairs of plans that can be merged into a single route - idx := 0 - for idx < len(sources) { - keep := make([]bool, len(sources)) - srcA := sources[idx] - merged := false - for j, srcB := range sources { - if j <= idx { - continue - } - newPlan := mergeUnionLogicalPlans(ctx, srcA, srcB) - if newPlan != nil { - sources[idx] = newPlan - srcA = newPlan - merged = true - } else { - keep[j] = true - } - } - if !merged { - return sources, nil - } - var phase []logicalPlan - for i, source := range sources { - if keep[i] || i <= idx { - phase = append(phase, source) - } - } - idx++ - sources = phase + return plan, nil + }) + if err != nil { + return nil, err } - return sources, nil -} -func transformAndMergeInOrder(ctx *plancontext.PlanningContext, op *operators.Union) (sources []logicalPlan, err error) { - // We go over all the input operators and turn them into logical plans - for i, source := range op.Sources { - plan, err := transformToLogicalPlan(ctx, source, false) - if err != nil { - return nil, err - } - if i == 0 { - sources = append(sources, plan) - continue - } - - // next we check if the last plan we produced can be merged with this new plan - last := sources[len(sources)-1] - newPlan := mergeUnionLogicalPlans(ctx, last, plan) - if newPlan != nil { - // if we could merge them, let's replace the last plan with this new merged one - sources[len(sources)-1] = newPlan - continue - } - // else we just add the new plan to the end of list - sources = append(sources, plan) + if len(sources) == 1 { + return sources[0], nil } - return sources, nil -} - -type collationInfo struct { - typ sqltypes.Type - col collations.ID -} - -func getCollationsFor(ctx *plancontext.PlanningContext, n *operators.Union) []collationInfo { - // TODO: coerce selects' select expressions' collations - var colls []collationInfo + return &concatenate{ + sources: sources, + noNeedToTypeCheck: nil, + }, nil - sel, err := n.GetSelectFor(0) - if err != nil { - return nil - } - for _, expr := range sel.SelectExprs { - aliasedE, ok := expr.(*sqlparser.AliasedExpr) - if !ok { - return nil - } - typ, col, _ := ctx.SemTable.TypeForExpr(aliasedE.Expr) - colls = append(colls, collationInfo{typ: typ, col: col}) - } - return colls } func transformDerivedPlan(ctx *plancontext.PlanningContext, op *operators.Horizon) (logicalPlan, error) { @@ -932,61 +734,6 @@ func (sqr *subQReplacer) replacer(cursor *sqlparser.Cursor) bool { return true } -func pushDistinct(plan logicalPlan) { - switch n := plan.(type) { - case *route: - n.Select.MakeDistinct() - case *concatenate: - for _, source := range n.sources { - pushDistinct(source) - } - } -} - -func mergeUnionLogicalPlans(ctx *plancontext.PlanningContext, left logicalPlan, right logicalPlan) logicalPlan { - lroute, ok := left.(*route) - if !ok { - return nil - } - rroute, ok := right.(*route) - if !ok { - return nil - } - - if canMergeUnionPlans(ctx, lroute, rroute) { - lroute.Select = &sqlparser.Union{Left: lroute.Select, Distinct: false, Right: rroute.Select} - return mergeSystemTableInformation(lroute, rroute) - } - return nil -} - -func canMergeUnionPlans(ctx *plancontext.PlanningContext, a, b *route) bool { - // this method should be close to tryMerge below. it does the same thing, but on logicalPlans instead of queryTrees - if a.eroute.Keyspace.Name != b.eroute.Keyspace.Name { - return false - } - switch a.eroute.Opcode { - case engine.Unsharded, engine.Reference: - return a.eroute.Opcode == b.eroute.Opcode - case engine.DBA: - return canSelectDBAMerge(a, b) - case engine.EqualUnique: - // Check if they target the same shard. - if b.eroute.Opcode == engine.EqualUnique && - a.eroute.Vindex == b.eroute.Vindex && - a.condition != nil && - b.condition != nil && - gen4ValuesEqual(ctx, []sqlparser.Expr{a.condition}, []sqlparser.Expr{b.condition}) { - return true - } - case engine.Scatter: - return b.eroute.Opcode == engine.Scatter - case engine.Next: - return false - } - return false -} - func canSelectDBAMerge(a, b *route) bool { if a.eroute.Opcode != engine.DBA { return false diff --git a/go/vt/vtgate/planbuilder/operators/ast2op.go b/go/vt/vtgate/planbuilder/operators/ast2op.go index 59223f0e631..916e71c650d 100644 --- a/go/vt/vtgate/planbuilder/operators/ast2op.go +++ b/go/vt/vtgate/planbuilder/operators/ast2op.go @@ -100,9 +100,12 @@ func createOperatorFromUnion(ctx *plancontext.PlanningContext, node *sqlparser.U return nil, err } + lexprs := sqlparser.GetFirstSelect(node.Left).SelectExprs + rexprs := sqlparser.GetFirstSelect(node.Right).SelectExprs union := &Union{ Distinct: node.Distinct, Sources: []ops.Operator{opLHS, opRHS}, + Selects: []sqlparser.SelectExprs{lexprs, rexprs}, } return &Horizon{Source: union, Query: node}, nil } diff --git a/go/vt/vtgate/planbuilder/operators/horizon_expanding.go b/go/vt/vtgate/planbuilder/operators/horizon_expanding.go index 36891288b95..3e991641178 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_expanding.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_expanding.go @@ -27,11 +27,50 @@ import ( ) func expandHorizon(ctx *plancontext.PlanningContext, horizon *Horizon) (ops.Operator, *rewrite.ApplyResult, error) { - sel, isSel := horizon.selectStatement().(*sqlparser.Select) - if !isSel { - return nil, nil, errHorizonNotPlanned() + + switch sel := horizon.selectStatement().(type) { + case *sqlparser.Select: + return expandSelectHorizon(ctx, horizon, sel) + case *sqlparser.Union: + return expandUnionHorizon(ctx, horizon, sel) + } + + panic("the switch should be exhaustive") +} + +func expandUnionHorizon(ctx *plancontext.PlanningContext, horizon *Horizon, union *sqlparser.Union) (ops.Operator, *rewrite.ApplyResult, error) { + op := horizon.Source + + qp, err := horizon.getQP(ctx) + if err != nil { + return nil, nil, err + } + + if union.Distinct { + op = &Distinct{ + Source: op, + QP: qp, + } } + if len(qp.OrderExprs) > 0 { + op = &Ordering{ + Source: op, + Order: qp.OrderExprs, + } + } + + if union.Limit != nil { + op = &Limit{ + Source: op, + AST: union.Limit, + } + } + + return op, rewrite.NewTree("expand horizon into smaller components", op), nil +} + +func expandSelectHorizon(ctx *plancontext.PlanningContext, horizon *Horizon, sel *sqlparser.Select) (ops.Operator, *rewrite.ApplyResult, error) { op, err := createProjectionFromSelect(ctx, horizon) if err != nil { return nil, nil, err diff --git a/go/vt/vtgate/planbuilder/operators/horizon_planning.go b/go/vt/vtgate/planbuilder/operators/horizon_planning.go index 63558d3be78..ae257f55330 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_planning.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_planning.go @@ -145,9 +145,6 @@ func pushOrExpandHorizon(ctx *plancontext.PlanningContext, in *Horizon) (ops.Ope } sel, isSel := in.selectStatement().(*sqlparser.Select) - if !isSel { - return nil, nil, errHorizonNotPlanned() - } qp, err := in.getQP(ctx) if err != nil { @@ -155,7 +152,14 @@ func pushOrExpandHorizon(ctx *plancontext.PlanningContext, in *Horizon) (ops.Ope } needsOrdering := len(qp.OrderExprs) > 0 - canPushDown := isRoute && sel.Having == nil && !needsOrdering && !qp.NeedsAggregation() && !sel.Distinct && sel.Limit == nil + hasHaving := isSel && sel.Having != nil + + canPushDown := isRoute && + !hasHaving && + !needsOrdering && + !qp.NeedsAggregation() && + !in.selectStatement().IsDistinct() && + in.selectStatement().GetLimit() == nil if canPushDown { return rewrite.Swap(in, rb, "push horizon into route") diff --git a/go/vt/vtgate/planbuilder/operators/union.go b/go/vt/vtgate/planbuilder/operators/union.go index 6568521383d..f368c8052c5 100644 --- a/go/vt/vtgate/planbuilder/operators/union.go +++ b/go/vt/vtgate/planbuilder/operators/union.go @@ -17,6 +17,10 @@ limitations under the License. package operators import ( + "fmt" + + "golang.org/x/exp/slices" + "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" @@ -26,18 +30,20 @@ import ( type Union struct { Sources []ops.Operator + Selects []sqlparser.SelectExprs Distinct bool // TODO this should be removed. For now it's used to fail queries Ordering []ops.OrderBy - noColumns + offsetPlanned bool } // Clone implements the Operator interface func (u *Union) Clone(inputs []ops.Operator) ops.Operator { newOp := *u newOp.Sources = inputs + newOp.Selects = slices.Clone(u.Selects) return &newOp } @@ -188,8 +194,99 @@ func (u *Union) Compact(*plancontext.PlanningContext) (ops.Operator, *rewrite.Ap return u, anythingChanged, nil } +func (u *Union) AddColumn(ctx *plancontext.PlanningContext, ae *sqlparser.AliasedExpr, reuseExisting, addToGroupBy bool) (ops.Operator, int, error) { + err := u.planOffsets(ctx) + if err != nil { + return nil, 0, err + } + cols, err := u.GetColumns() + if err != nil { + return nil, 0, err + } + for idx, col := range cols { + if ctx.SemTable.EqualsExprWithDeps(ae.Expr, col.Expr) { + return u, idx, nil + } + } + + ws, isWeightString := ae.Expr.(*sqlparser.WeightStringFuncExpr) + if !isWeightString { + return nil, 0, vterrors.VT13001(fmt.Sprintf("only weight_string function is expected - got %s", sqlparser.String(ae))) + } + + newSrc, offset, err := u.Sources[0].AddColumn(ctx, ae, true, false) + if err != nil { + return nil, 0, err + } + u.Sources[0] = newSrc + + // we are adding a weight_string function. let's find the offset of the argument to it + argIdx := slices.IndexFunc(u.Selects[0], func(se sqlparser.SelectExpr) bool { + ae, ok := se.(*sqlparser.AliasedExpr) + if !ok { + err = vterrors.VT12001("can't handle star expressions inside UNION") + return false + } + return ctx.SemTable.EqualsExprWithDeps(ae.Expr, ws.Expr) + }) + if argIdx == -1 { + return nil, 0, vterrors.VT13001(fmt.Sprintf("could not find the actual expression to add weight_string function: %s", sqlparser.String(ws.Expr))) + } + + for i := 1; i < len(u.Sources); i++ { + exprs := u.Selects[i] + selectExpr := exprs[argIdx] + ae, ok := selectExpr.(*sqlparser.AliasedExpr) + if !ok { + return nil, 0, vterrors.VT09015() + } + newSrc, this, err := u.Sources[i].AddColumn(ctx, aeWrap(weightStringFor(ae.Expr)), true, false) + if err != nil { + return nil, 0, err + } + if this != offset { + panic("uh oh") + } + u.Sources[i] = newSrc + } + return u, offset, nil +} + +func (u *Union) GetColumns() ([]*sqlparser.AliasedExpr, error) { + return u.Sources[0].GetColumns() +} + +func (u *Union) GetSelectExprs() (sqlparser.SelectExprs, error) { + return u.Sources[0].GetSelectExprs() +} + func (u *Union) NoLHSTableSet() {} func (u *Union) ShortDescription() string { return "" } + +func (u *Union) planOffsets(ctx *plancontext.PlanningContext) error { + if u.offsetPlanned { + return nil + } + u.offsetPlanned = true + + for idx, source := range u.Sources { + for eIdx, expr := range u.Selects[idx] { + ae, ok := expr.(*sqlparser.AliasedExpr) + if !ok { + return vterrors.VT09015() + } + newOp, offset, err := source.AddColumn(ctx, ae, false, false) + if err != nil { + return err + } + if offset != eIdx { + return vterrors.VT13001(fmt.Sprintf("index mismatch while pushing the column for '%s'", sqlparser.String(ae))) + } + u.Sources[idx] = newOp + } + } + return nil +} diff --git a/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json b/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json index 9df66921fd5..db815ad46bb 100644 --- a/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json +++ b/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json @@ -501,21 +501,7 @@ { "comment": "create view with union with the same target shard", "query": "create view user.view_a as select * from music where user_id = 1 union select * from user where id = 1", - "plan": { - "QueryType": "DDL", - "Original": "create view user.view_a as select * from music where user_id = 1 union select * from user where id = 1", - "Instructions": { - "OperatorType": "DDL", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "Query": "create view view_a as select * from music where user_id = 1 union select * from `user` where id = 1" - }, - "TablesUsed": [ - "user.view_a" - ] - } + "plan": "VT09015: schema tracking required" }, { "comment": "create view with testing SingleRow Projection", diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json index cca2885ec70..413e0a91bd1 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json @@ -101,15 +101,45 @@ "QueryType": "SELECT", "Original": "select TABLE_NAME from information_schema.columns union select table_schema from information_schema.tables", "Instructions": { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_NAME from information_schema.`columns` where 1 != 1 union select table_schema from information_schema.`tables` where 1 != 1", - "Query": "select TABLE_NAME from information_schema.`columns` union select table_schema from information_schema.`tables`", - "Table": "information_schema.`columns`" + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "0 COLLATE utf8mb4_0900_ai_ci", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "0 ASC COLLATE utf8mb4_0900_ai_ci", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_NAME from information_schema.`columns` where 1 != 1", + "Query": "select TABLE_NAME from information_schema.`columns`", + "Table": "information_schema.`columns`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select table_schema from information_schema.`tables` where 1 != 1", + "Query": "select table_schema from information_schema.`tables`", + "Table": "information_schema.`tables`" + } + ] + } + ] + } + ] } } }, @@ -120,57 +150,43 @@ "QueryType": "SELECT", "Original": "select * from information_schema.tables where table_schema = 'user' union select * from information_schema.tables where table_schema = 'main'", "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "0: utf8mb4_0900_ai_ci", - "1: utf8mb4_0900_ai_ci", - "2: utf8mb4_0900_ai_ci", - "3: utf8mb4_0900_ai_ci", - "4: utf8mb4_0900_ai_ci", - "5", - "6: utf8mb4_0900_ai_ci", - "7", - "8", - "9", - "10", - "11", - "12", - "13", - "14", - "15", - "16", - "17: utf8mb4_0900_ai_ci", - "18", - "19: utf8mb4_0900_ai_ci", - "20: utf8mb4_0900_ai_ci" - ], + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "0 COLLATE utf8mb4_0900_ai_ci, 1 COLLATE utf8mb4_0900_ai_ci, 2 COLLATE utf8mb4_0900_ai_ci, 3 COLLATE utf8mb4_0900_ai_ci, 4 COLLATE utf8mb4_0900_ai_ci, 5, 6 COLLATE utf8mb4_0900_ai_ci, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 COLLATE utf8mb4_0900_ai_ci, 18, 19 COLLATE utf8mb4_0900_ai_ci, 20 COLLATE utf8mb4_0900_ai_ci", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "0 ASC COLLATE utf8mb4_0900_ai_ci, 1 ASC COLLATE utf8mb4_0900_ai_ci, 2 ASC COLLATE utf8mb4_0900_ai_ci, 3 ASC COLLATE utf8mb4_0900_ai_ci, 4 ASC COLLATE utf8mb4_0900_ai_ci, 5 ASC, 6 ASC COLLATE utf8mb4_0900_ai_ci, 7 ASC, 8 ASC, 9 ASC, 10 ASC, 11 ASC, 12 ASC, 13 ASC, 14 ASC, 15 ASC, 16 ASC, 17 ASC COLLATE utf8mb4_0900_ai_ci, 18 ASC, 19 ASC COLLATE utf8mb4_0900_ai_ci, 20 ASC COLLATE utf8mb4_0900_ai_ci", "Inputs": [ { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where 1 != 1", - "Query": "select distinct TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", - "SysTableTableSchema": "[VARCHAR(\"user\")]", - "Table": "information_schema.`tables`" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where 1 != 1", - "Query": "select distinct TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", - "SysTableTableSchema": "[VARCHAR(\"main\")]", - "Table": "information_schema.`tables`" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where 1 != 1", + "Query": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"user\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where 1 != 1", + "Query": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"main\")]", + "Table": "information_schema.`tables`" + } + ] } ] } @@ -755,42 +771,12 @@ { "comment": "select sum(found) from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", "query": "select sum(found) from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", - "plan": { - "QueryType": "SELECT", - "Original": "select sum(found) from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", - "Instructions": { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select sum(found) from (select 1 as found from information_schema.`tables` where 1 != 1 union all (select 1 as found from information_schema.views where 1 != 1)) as t where 1 != 1", - "Query": "select sum(found) from (select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */ union all (select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1)) as t", - "SysTableTableSchema": "[VARCHAR(\"music\"), VARCHAR(\"music\")]", - "Table": "information_schema.`tables`" - } - } + "plan": "VT13001: [BUG] only weight_string function is expected - got found" }, { "comment": "union as a derived table", "query": "select found from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", - "plan": { - "QueryType": "SELECT", - "Original": "select found from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", - "Instructions": { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select found from (select 1 as found from information_schema.`tables` where 1 != 1 union all (select 1 as found from information_schema.views where 1 != 1)) as t where 1 != 1", - "Query": "select found from (select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */ union all (select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1)) as t", - "SysTableTableSchema": "[VARCHAR(\"music\"), VARCHAR(\"music\")]", - "Table": "information_schema.`tables`" - } - } + "plan": "VT13001: [BUG] only weight_string function is expected - got found" }, { "comment": "merge system schema queries as long as they have any same table_schema", @@ -799,16 +785,33 @@ "QueryType": "SELECT", "Original": "select 1 as found from information_schema.`tables` where table_schema = 'music' and table_schema = 'Music' union all (select 1 as found from information_schema.views where table_schema = 'music' and table_schema = 'user' limit 1)", "Instructions": { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1 union all (select 1 as found from information_schema.views where 1 != 1)", - "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */ union all (select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1)", - "SysTableTableSchema": "[VARCHAR(\"music\"), VARCHAR(\"Music\"), VARCHAR(\"music\"), VARCHAR(\"user\")]", - "Table": "information_schema.`tables`" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", + "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"music\"), VARCHAR(\"Music\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.views where 1 != 1", + "Query": "select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1", + "SysTableTableSchema": "[VARCHAR(\"music\"), VARCHAR(\"user\")]", + "Table": "information_schema.views" + } + ] } } }, @@ -819,16 +822,33 @@ "QueryType": "SELECT", "Original": "select 1 as found from information_schema.`tables` where table_schema = 'music' and table_schema = 'Music' union all (select 1 as found from information_schema.views where table_schema = 'music' and table_schema = 'user' limit 1)", "Instructions": { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1 union all (select 1 as found from information_schema.views where 1 != 1)", - "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */ union all (select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1)", - "SysTableTableSchema": "[VARCHAR(\"music\"), VARCHAR(\"Music\"), VARCHAR(\"music\"), VARCHAR(\"user\")]", - "Table": "information_schema.`tables`" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", + "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"music\"), VARCHAR(\"Music\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.views where 1 != 1", + "Query": "select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1", + "SysTableTableSchema": "[VARCHAR(\"music\"), VARCHAR(\"user\")]", + "Table": "information_schema.views" + } + ] } } }, @@ -839,38 +859,61 @@ "QueryType": "SELECT", "Original": "select 1 as found from information_schema.`tables` where table_name = 'music' and table_name = 'Music' and exists (select 1 as found from information_schema.`tables` where table_name = 'music' and table_name = 'Music' union all (select 1 as found from information_schema.views where table_name = 'music' and table_name = 'user' limit 1))", "Instructions": { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", - "Query": "select 1 as found from information_schema.`tables` where table_name = :table_name /* VARCHAR */ and table_name = :table_name1 /* VARCHAR */ and exists (select 1 as found from information_schema.`tables` where table_name = :table_name2 /* VARCHAR */ and table_name = :table_name3 /* VARCHAR */ union all (select 1 as found from information_schema.views where table_name = :table_name4 /* VARCHAR */ and table_name = :table_name5 /* VARCHAR */ limit 1))", - "SysTableTableName": "[table_name1:VARCHAR(\"Music\"), table_name2:VARCHAR(\"music\"), table_name3:VARCHAR(\"Music\"), table_name4:VARCHAR(\"music\"), table_name5:VARCHAR(\"user\"), table_name:VARCHAR(\"music\")]", - "Table": "information_schema.`tables`" + "OperatorType": "Subquery", + "Variant": "PulloutExists", + "PulloutVars": [ + "__sq_has_values1" + ], + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", + "Query": "select 1 as found from information_schema.`tables` where table_name = :table_name2 /* VARCHAR */ and table_name = :table_name3 /* VARCHAR */", + "SysTableTableName": "[table_name2:VARCHAR(\"music\"), table_name3:VARCHAR(\"Music\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.views where 1 != 1", + "Query": "select 1 as found from information_schema.views where table_name = :table_name4 /* VARCHAR */ and table_name = :table_name5 /* VARCHAR */ limit 1", + "SysTableTableName": "[table_name4:VARCHAR(\"music\"), table_name5:VARCHAR(\"user\")]", + "Table": "information_schema.views" + } + ] + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", + "Query": "select 1 as found from information_schema.`tables` where table_name = :table_name /* VARCHAR */ and table_name = :table_name1 /* VARCHAR */ and :__sq_has_values1", + "SysTableTableName": "[table_name1:VARCHAR(\"Music\"), table_name:VARCHAR(\"music\")]", + "Table": "information_schema.`tables`" + } + ] } } }, { "comment": "merge even one side have schema name in derived table", "query": "select * from (select TABLE_NAME from information_schema.tables t where t.TABLE_SCHEMA = 'a' union select TABLE_NAME from information_schema.columns) dt", - "plan": { - "QueryType": "SELECT", - "Original": "select * from (select TABLE_NAME from information_schema.tables t where t.TABLE_SCHEMA = 'a' union select TABLE_NAME from information_schema.columns) dt", - "Instructions": { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select dt.TABLE_NAME from (select TABLE_NAME from information_schema.`tables` as t where 1 != 1 union select TABLE_NAME from information_schema.`columns` where 1 != 1) as dt where 1 != 1", - "Query": "select dt.TABLE_NAME from (select TABLE_NAME from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */ union select TABLE_NAME from information_schema.`columns`) as dt", - "SysTableTableSchema": "[VARCHAR(\"a\")]", - "Table": "information_schema.`tables`" - } - } + "plan": "VT13001: [BUG] did not expect to add group by here" }, { "comment": "merge even one side have schema name in subquery", @@ -879,16 +922,53 @@ "QueryType": "SELECT", "Original": "select `COLLATION_NAME` from information_schema.`COLUMNS` t where `COLUMN_NAME` in (select `COLUMN_NAME` from information_schema.tables t where t.TABLE_SCHEMA = 'a' union select `COLUMN_NAME` from information_schema.columns)", "Instructions": { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select COLLATION_NAME from information_schema.`COLUMNS` as t where 1 != 1", - "Query": "select COLLATION_NAME from information_schema.`COLUMNS` as t where COLUMN_NAME in (select COLUMN_NAME from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */ union select COLUMN_NAME from information_schema.`columns`)", - "SysTableTableSchema": "[VARCHAR(\"a\")]", - "Table": "information_schema.`COLUMNS`" + "OperatorType": "Subquery", + "Variant": "PulloutIn", + "PulloutVars": [ + "__sq_has_values1", + "__sq1" + ], + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select COLUMN_NAME from information_schema.`tables` as t where 1 != 1", + "Query": "select COLUMN_NAME from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"a\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select COLUMN_NAME from information_schema.`columns` where 1 != 1", + "Query": "select COLUMN_NAME from information_schema.`columns`", + "Table": "information_schema.`columns`" + } + ] + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select COLLATION_NAME from information_schema.`COLUMNS` as t where 1 != 1", + "Query": "select COLLATION_NAME from information_schema.`COLUMNS` as t where :__sq_has_values1 = 1 and COLUMN_NAME in ::__sq1", + "Table": "information_schema.`COLUMNS`" + } + ] } } }, diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json index b33f6d553ae..b676dc78f22 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json @@ -101,15 +101,45 @@ "QueryType": "SELECT", "Original": "select TABLE_NAME from information_schema.columns union select table_schema from information_schema.tables", "Instructions": { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_NAME from information_schema.`columns` where 1 != 1 union select table_schema from information_schema.`tables` where 1 != 1", - "Query": "select TABLE_NAME from information_schema.`columns` union select table_schema from information_schema.`tables`", - "Table": "information_schema.`columns`" + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "0 COLLATE utf8mb4_0900_ai_ci", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "0 ASC COLLATE utf8mb4_0900_ai_ci", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_NAME from information_schema.`columns` where 1 != 1", + "Query": "select TABLE_NAME from information_schema.`columns`", + "Table": "information_schema.`columns`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select table_schema from information_schema.`tables` where 1 != 1", + "Query": "select table_schema from information_schema.`tables`", + "Table": "information_schema.`tables`" + } + ] + } + ] + } + ] } } }, @@ -120,57 +150,43 @@ "QueryType": "SELECT", "Original": "select * from information_schema.tables where table_schema = 'user' union select * from information_schema.tables where table_schema = 'main'", "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "0: utf8mb4_0900_ai_ci", - "1: utf8mb4_0900_ai_ci", - "2: utf8mb4_0900_ai_ci", - "3", - "4: utf8mb4_0900_ai_ci", - "5", - "6", - "7", - "8", - "9", - "10", - "11", - "12", - "13", - "14", - "15", - "16", - "17: utf8mb4_0900_ai_ci", - "18", - "19: utf8mb4_0900_ai_ci", - "20: utf8mb4_0900_ai_ci" - ], + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "0 COLLATE utf8mb4_0900_ai_ci, 1 COLLATE utf8mb4_0900_ai_ci, 2 COLLATE utf8mb4_0900_ai_ci, 3, 4 COLLATE utf8mb4_0900_ai_ci, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 COLLATE utf8mb4_0900_ai_ci, 18, 19 COLLATE utf8mb4_0900_ai_ci, 20 COLLATE utf8mb4_0900_ai_ci", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "0 ASC COLLATE utf8mb4_0900_ai_ci, 1 ASC COLLATE utf8mb4_0900_ai_ci, 2 ASC COLLATE utf8mb4_0900_ai_ci, 3 ASC, 4 ASC COLLATE utf8mb4_0900_ai_ci, 5 ASC, 6 ASC, 7 ASC, 8 ASC, 9 ASC, 10 ASC, 11 ASC, 12 ASC, 13 ASC, 14 ASC, 15 ASC, 16 ASC, 17 ASC COLLATE utf8mb4_0900_ai_ci, 18 ASC, 19 ASC COLLATE utf8mb4_0900_ai_ci, 20 ASC COLLATE utf8mb4_0900_ai_ci", "Inputs": [ { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where 1 != 1", - "Query": "select distinct TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", - "SysTableTableSchema": "[VARCHAR(\"user\")]", - "Table": "information_schema.`tables`" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where 1 != 1", - "Query": "select distinct TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", - "SysTableTableSchema": "[VARCHAR(\"main\")]", - "Table": "information_schema.`tables`" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where 1 != 1", + "Query": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"user\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where 1 != 1", + "Query": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"main\")]", + "Table": "information_schema.`tables`" + } + ] } ] } @@ -820,42 +836,12 @@ { "comment": "select sum(found) from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", "query": "select sum(found) from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", - "plan": { - "QueryType": "SELECT", - "Original": "select sum(found) from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", - "Instructions": { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select sum(found) from (select 1 as found from information_schema.`tables` where 1 != 1 union all (select 1 as found from information_schema.views where 1 != 1)) as t where 1 != 1", - "Query": "select sum(found) from (select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */ union all (select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1)) as t", - "SysTableTableSchema": "[VARCHAR(\"music\"), VARCHAR(\"music\")]", - "Table": "information_schema.`tables`" - } - } + "plan": "VT13001: [BUG] only weight_string function is expected - got found" }, { "comment": "union as a derived table", "query": "select found from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", - "plan": { - "QueryType": "SELECT", - "Original": "select found from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", - "Instructions": { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select found from (select 1 as found from information_schema.`tables` where 1 != 1 union all (select 1 as found from information_schema.views where 1 != 1)) as t where 1 != 1", - "Query": "select found from (select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */ union all (select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1)) as t", - "SysTableTableSchema": "[VARCHAR(\"music\"), VARCHAR(\"music\")]", - "Table": "information_schema.`tables`" - } - } + "plan": "VT13001: [BUG] only weight_string function is expected - got found" }, { "comment": "merge system schema queries as long as they have any same table_schema", @@ -864,16 +850,33 @@ "QueryType": "SELECT", "Original": "select 1 as found from information_schema.`tables` where table_schema = 'music' and table_schema = 'Music' union all (select 1 as found from information_schema.views where table_schema = 'music' and table_schema = 'user' limit 1)", "Instructions": { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1 union all (select 1 as found from information_schema.views where 1 != 1)", - "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */ union all (select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1)", - "SysTableTableSchema": "[VARCHAR(\"music\"), VARCHAR(\"Music\"), VARCHAR(\"music\"), VARCHAR(\"user\")]", - "Table": "information_schema.`tables`" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", + "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"music\"), VARCHAR(\"Music\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.views where 1 != 1", + "Query": "select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1", + "SysTableTableSchema": "[VARCHAR(\"music\"), VARCHAR(\"user\")]", + "Table": "information_schema.views" + } + ] } } }, @@ -884,16 +887,33 @@ "QueryType": "SELECT", "Original": "select 1 as found from information_schema.`tables` where table_schema = 'music' and table_schema = 'Music' union all (select 1 as found from information_schema.views where table_schema = 'music' and table_schema = 'user' limit 1)", "Instructions": { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1 union all (select 1 as found from information_schema.views where 1 != 1)", - "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */ union all (select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1)", - "SysTableTableSchema": "[VARCHAR(\"music\"), VARCHAR(\"Music\"), VARCHAR(\"music\"), VARCHAR(\"user\")]", - "Table": "information_schema.`tables`" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", + "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"music\"), VARCHAR(\"Music\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.views where 1 != 1", + "Query": "select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1", + "SysTableTableSchema": "[VARCHAR(\"music\"), VARCHAR(\"user\")]", + "Table": "information_schema.views" + } + ] } } }, @@ -904,38 +924,61 @@ "QueryType": "SELECT", "Original": "select 1 as found from information_schema.`tables` where table_name = 'music' and table_name = 'Music' and exists (select 1 as found from information_schema.`tables` where table_name = 'music' and table_name = 'Music' union all (select 1 as found from information_schema.views where table_name = 'music' and table_name = 'user' limit 1))", "Instructions": { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", - "Query": "select 1 as found from information_schema.`tables` where table_name = :table_name /* VARCHAR */ and table_name = :table_name1 /* VARCHAR */ and exists (select 1 as found from information_schema.`tables` where table_name = :table_name2 /* VARCHAR */ and table_name = :table_name3 /* VARCHAR */ union all (select 1 as found from information_schema.views where table_name = :table_name4 /* VARCHAR */ and table_name = :table_name5 /* VARCHAR */ limit 1))", - "SysTableTableName": "[table_name1:VARCHAR(\"Music\"), table_name2:VARCHAR(\"music\"), table_name3:VARCHAR(\"Music\"), table_name4:VARCHAR(\"music\"), table_name5:VARCHAR(\"user\"), table_name:VARCHAR(\"music\")]", - "Table": "information_schema.`tables`" + "OperatorType": "Subquery", + "Variant": "PulloutExists", + "PulloutVars": [ + "__sq_has_values1" + ], + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", + "Query": "select 1 as found from information_schema.`tables` where table_name = :table_name2 /* VARCHAR */ and table_name = :table_name3 /* VARCHAR */", + "SysTableTableName": "[table_name2:VARCHAR(\"music\"), table_name3:VARCHAR(\"Music\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.views where 1 != 1", + "Query": "select 1 as found from information_schema.views where table_name = :table_name4 /* VARCHAR */ and table_name = :table_name5 /* VARCHAR */ limit 1", + "SysTableTableName": "[table_name4:VARCHAR(\"music\"), table_name5:VARCHAR(\"user\")]", + "Table": "information_schema.views" + } + ] + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", + "Query": "select 1 as found from information_schema.`tables` where table_name = :table_name /* VARCHAR */ and table_name = :table_name1 /* VARCHAR */ and :__sq_has_values1", + "SysTableTableName": "[table_name1:VARCHAR(\"Music\"), table_name:VARCHAR(\"music\")]", + "Table": "information_schema.`tables`" + } + ] } } }, { "comment": "merge even one side have schema name in derived table", "query": "select * from (select TABLE_NAME from information_schema.tables t where t.TABLE_SCHEMA = 'a' union select TABLE_NAME from information_schema.columns) dt", - "plan": { - "QueryType": "SELECT", - "Original": "select * from (select TABLE_NAME from information_schema.tables t where t.TABLE_SCHEMA = 'a' union select TABLE_NAME from information_schema.columns) dt", - "Instructions": { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select dt.TABLE_NAME from (select TABLE_NAME from information_schema.`tables` as t where 1 != 1 union select TABLE_NAME from information_schema.`columns` where 1 != 1) as dt where 1 != 1", - "Query": "select dt.TABLE_NAME from (select TABLE_NAME from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */ union select TABLE_NAME from information_schema.`columns`) as dt", - "SysTableTableSchema": "[VARCHAR(\"a\")]", - "Table": "information_schema.`tables`" - } - } + "plan": "VT13001: [BUG] did not expect to add group by here" }, { "comment": "merge even one side have schema name in subquery", @@ -944,16 +987,53 @@ "QueryType": "SELECT", "Original": "select `COLLATION_NAME` from information_schema.`COLUMNS` t where `COLUMN_NAME` in (select `COLUMN_NAME` from information_schema.tables t where t.TABLE_SCHEMA = 'a' union select `COLUMN_NAME` from information_schema.columns)", "Instructions": { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select COLLATION_NAME from information_schema.`COLUMNS` as t where 1 != 1", - "Query": "select COLLATION_NAME from information_schema.`COLUMNS` as t where COLUMN_NAME in (select COLUMN_NAME from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */ union select COLUMN_NAME from information_schema.`columns`)", - "SysTableTableSchema": "[VARCHAR(\"a\")]", - "Table": "information_schema.`COLUMNS`" + "OperatorType": "Subquery", + "Variant": "PulloutIn", + "PulloutVars": [ + "__sq_has_values1", + "__sq1" + ], + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select COLUMN_NAME from information_schema.`tables` as t where 1 != 1", + "Query": "select COLUMN_NAME from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"a\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select COLUMN_NAME from information_schema.`columns` where 1 != 1", + "Query": "select COLUMN_NAME from information_schema.`columns`", + "Table": "information_schema.`columns`" + } + ] + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select COLLATION_NAME from information_schema.`COLUMNS` as t where 1 != 1", + "Query": "select COLLATION_NAME from information_schema.`COLUMNS` as t where :__sq_has_values1 = 1 and COLUMN_NAME in ::__sq1", + "Table": "information_schema.`COLUMNS`" + } + ] } } }, diff --git a/go/vt/vtgate/planbuilder/testdata/large_union_cases.json b/go/vt/vtgate/planbuilder/testdata/large_union_cases.json index c50ba09d3ce..5679aa826eb 100644 --- a/go/vt/vtgate/planbuilder/testdata/large_union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/large_union_cases.json @@ -2,972 +2,6 @@ { "comment": "this testcase breaks goland, so it lives on its own file", "query": "(SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270698330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270699497 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270703806 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270707364 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270714657 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270721330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270812079 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271011532 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271034164 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271034177 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271066849 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271098740 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271355000 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271924504 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272086055 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272127855 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272191137 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272468271 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270644941 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270650576 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270652906 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270660650 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270670201 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270698330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270699497 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270707364 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271799956 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271799956 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270644941 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270649256 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270653671 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270670201 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270717223 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270720898 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271346411 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271352121 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271354908 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271367516 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271472522 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271821733 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272068709 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272127855 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272191137 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272244005 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272468271 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272244005 ORDER BY created_at ASC, id ASC LIMIT 11)", - "plan": { - "QueryType": "SELECT", - "Original": "(SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270698330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270699497 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270703806 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270707364 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270714657 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270721330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270812079 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271011532 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271034164 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271034177 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271066849 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271098740 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271355000 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271924504 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272086055 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272127855 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272191137 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272468271 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270644941 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270650576 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270652906 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270660650 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270670201 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270698330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270699497 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270707364 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271799956 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271799956 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270644941 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270649256 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270653671 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270670201 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270717223 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270720898 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271346411 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271352121 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271354908 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271367516 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271472522 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271821733 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272068709 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272127855 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272191137 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272244005 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272468271 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272244005 ORDER BY created_at ASC, id ASC LIMIT 11)", - "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "(0:2)", - "(1:3)" - ], - "ResultColumns": 2, - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "(select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1) union (select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1)", - "Query": "(select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270698330 order by created_at asc, id asc limit 11) union (select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270698330 order by created_at asc, id asc limit 11)", - "Table": "music", - "Values": [ - "INT64(1270698330)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "(select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1) union (select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1)", - "Query": "(select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270699497 order by created_at asc, id asc limit 11) union (select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270699497 order by created_at asc, id asc limit 11)", - "Table": "music", - "Values": [ - "INT64(1270699497)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270703806 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270703806)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270707364 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270707364)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270714657 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270714657)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270721330 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270721330)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270812079 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270812079)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271011532 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271011532)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271034164 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271034164)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271034177 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271034177)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271066849 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271066849)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271098740 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271098740)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271355000 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271355000)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271639345 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271639345)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271914117 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271914117)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271924504 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271924504)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272086055 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272086055)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272127855 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272127855)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272191137 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272191137)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272468271 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272468271)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270637436 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270637436)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270644941 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270644941)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270650576 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270650576)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270652906 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270652906)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270660650 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270660650)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270670201 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270670201)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270707364 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270707364)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271365691)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271799956 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271799956)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271914117 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271914117)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270637436 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270637436)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271799956 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271799956)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270637436 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270637436)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271639345 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271639345)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270644941 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270644941)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270649256 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270649256)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270653671 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270653671)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270670201 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270670201)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270717223 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270717223)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270720898 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270720898)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270982590 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270982590)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271346411 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271346411)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271352121 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271352121)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271354908 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271354908)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271365691)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271367516 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271367516)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271472522 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271472522)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271607757 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271607757)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271639345 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271639345)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271821733 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271821733)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271914117 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271914117)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272068709 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272068709)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272127855 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272127855)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272191137 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272191137)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272244005 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272244005)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272468271 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272468271)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270982590 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270982590)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271365691)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271607757 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271607757)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270982590 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270982590)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271365691)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271607757 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271607757)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272244005 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272244005)" - ], - "Vindex": "user_index" - } - ] - } - ] - }, - "TablesUsed": [ - "user.music" - ] - } + "plan": "VT13001: [BUG] index mismatch while pushing the column for 'content'" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.json b/go/vt/vtgate/planbuilder/testdata/select_cases.json index 825e405a50d..d19799c16e0 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.json @@ -1360,56 +1360,12 @@ { "comment": "union with the same target shard", "query": "select * from music where user_id = 1 union select * from user where id = 1", - "plan": { - "QueryType": "SELECT", - "Original": "select * from music where user_id = 1 union select * from user where id = 1", - "Instructions": { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select * from music where 1 != 1 union select * from `user` where 1 != 1", - "Query": "select * from music where user_id = 1 union select * from `user` where id = 1", - "Table": "music", - "Values": [ - "INT64(1)" - ], - "Vindex": "user_index" - }, - "TablesUsed": [ - "user.music", - "user.user" - ] - } + "plan": "VT09015: schema tracking required" }, { "comment": "union with the same target shard last_insert_id", "query": "select *, last_insert_id() from music where user_id = 1 union select * from user where id = 1", - "plan": { - "QueryType": "SELECT", - "Original": "select *, last_insert_id() from music where user_id = 1 union select * from user where id = 1", - "Instructions": { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select *, :__lastInsertId as `last_insert_id()` from music where 1 != 1 union select * from `user` where 1 != 1", - "Query": "select *, :__lastInsertId as `last_insert_id()` from music where user_id = 1 union select * from `user` where id = 1", - "Table": "music", - "Values": [ - "INT64(1)" - ], - "Vindex": "user_index" - }, - "TablesUsed": [ - "user.music", - "user.user" - ] - } + "plan": "VT09015: schema tracking required" }, { "comment": "unsharded union in derived table", @@ -2473,49 +2429,7 @@ { "comment": "union as a derived table", "query": "select found from (select id as found from user union all (select id from unsharded)) as t", - "plan": { - "QueryType": "SELECT", - "Original": "select found from (select id as found from user union all (select id from unsharded)) as t", - "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id as found from `user` where 1 != 1", - "Query": "select id as found from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select id from unsharded where 1 != 1", - "Query": "select id from unsharded", - "Table": "unsharded" - } - ] - } - ] - }, - "TablesUsed": [ - "main.unsharded", - "user.user" - ] - } + "plan": "VT13001: [BUG] only weight_string function is expected - got found" }, { "comment": "use output column containing data from both sides of the join", diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 836393bcbe6..0aeababca9b 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -6,15 +6,31 @@ "QueryType": "SELECT", "Original": "select id from user union all select id from music", "Instructions": { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id from `user` where 1 != 1 union all select id from music where 1 != 1", - "Query": "select id from `user` union all select id from music", - "Table": "`user`" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from `user` where 1 != 1", + "Query": "select id from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from music where 1 != 1", + "Query": "select id from music", + "Table": "music" + } + ] }, "TablesUsed": [ "user.music", @@ -29,22 +45,44 @@ "QueryType": "SELECT", "Original": "select id from user union select id from music", "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "(0:1)" - ], + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|1)", "ResultColumns": 1, "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1 union select id, weight_string(id) from music where 1 != 1", - "Query": "select id, weight_string(id) from `user` union select id, weight_string(id) from music", - "Table": "`user`" + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|1) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "Query": "select id, weight_string(id) from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from music where 1 != 1", + "Query": "select id, weight_string(id) from music", + "Table": "music" + } + ] + } + ] } ] }, @@ -107,43 +145,49 @@ "QueryType": "SELECT", "Original": "(SELECT id FROM user ORDER BY id DESC LIMIT 1) UNION ALL (SELECT id FROM music ORDER BY id DESC LIMIT 1)", "Instructions": { - "OperatorType": "Concatenate", + "OperatorType": "SimpleProjection", + "Columns": [ + 0 + ], "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(1)", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", - "ResultColumns": 1, - "Table": "`user`" - } - ] - }, - { - "OperatorType": "Limit", - "Count": "INT64(1)", - "Inputs": [ + "OperatorType": "Limit", + "Count": "INT64(1)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", + "Table": "`user`" + } + ] + }, { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from music where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", - "ResultColumns": 1, - "Table": "music" + "OperatorType": "Limit", + "Count": "INT64(1)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from music where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", + "Table": "music" + } + ] } ] } @@ -162,15 +206,31 @@ "QueryType": "SELECT", "Original": "select col1, col2 from user union all select col1, col2 from user_extra", "Instructions": { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select col1, col2 from `user` where 1 != 1 union all select col1, col2 from user_extra where 1 != 1", - "Query": "select col1, col2 from `user` union all select col1, col2 from user_extra", - "Table": "`user`" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select col1, col2 from `user` where 1 != 1", + "Query": "select col1, col2 from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select col1, col2 from user_extra where 1 != 1", + "Query": "select col1, col2 from user_extra", + "Table": "user_extra" + } + ] }, "TablesUsed": [ "user.user", @@ -181,48 +241,12 @@ { "comment": "union operations in subqueries (FROM)", "query": "select * from (select * from user union all select * from user_extra) as t", - "plan": { - "QueryType": "SELECT", - "Original": "select * from (select * from user union all select * from user_extra) as t", - "Instructions": { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select * from (select * from `user` where 1 != 1 union all select * from user_extra where 1 != 1) as t where 1 != 1", - "Query": "select * from (select * from `user` union all select * from user_extra) as t", - "Table": "`user`" - }, - "TablesUsed": [ - "user.user", - "user.user_extra" - ] - } + "plan": "VT12001: unsupported: '*' expression in cross-shard query" }, { "comment": "union operations in derived table, without star expression (FROM)¡", "query": "select col1,col2 from (select col1, col2 from user union all select col1, col2 from user_extra) as t", - "plan": { - "QueryType": "SELECT", - "Original": "select col1,col2 from (select col1, col2 from user union all select col1, col2 from user_extra) as t", - "Instructions": { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select col1, col2 from (select col1, col2 from `user` where 1 != 1 union all select col1, col2 from user_extra where 1 != 1) as t where 1 != 1", - "Query": "select col1, col2 from (select col1, col2 from `user` union all select col1, col2 from user_extra) as t", - "Table": "`user`" - }, - "TablesUsed": [ - "user.user", - "user.user_extra" - ] - } + "plan": "VT13001: [BUG] only weight_string function is expected - got col1" }, { "comment": "union all between two scatter selects, with order by", @@ -231,43 +255,49 @@ "QueryType": "SELECT", "Original": "(select id from user order by id limit 5) union all (select id from music order by id desc limit 5)", "Instructions": { - "OperatorType": "Concatenate", + "OperatorType": "SimpleProjection", + "Columns": [ + 0 + ], "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(5)", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) ASC", - "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", - "ResultColumns": 1, - "Table": "`user`" - } - ] - }, - { - "OperatorType": "Limit", - "Count": "INT64(5)", - "Inputs": [ + "OperatorType": "Limit", + "Count": "INT64(5)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) ASC", + "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", + "Table": "`user`" + } + ] + }, { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from music where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", - "ResultColumns": 1, - "Table": "music" + "OperatorType": "Limit", + "Count": "INT64(5)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from music where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", + "Table": "music" + } + ] } ] } @@ -289,19 +319,39 @@ "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id from `user` where 1 != 1 union select id from `user` where 1 != 1", - "Query": "select id from `user` where id = 1 union select id from `user` where id = 1", - "Table": "`user`", - "Values": [ - "INT64(1)" - ], - "Vindex": "user_index" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from `user` where 1 != 1", + "Query": "select id from `user` where id = 1", + "Table": "`user`", + "Values": [ + "INT64(1)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from `user` where 1 != 1", + "Query": "select id from `user` where id = 1", + "Table": "`user`", + "Values": [ + "INT64(1)" + ], + "Vindex": "user_index" + } + ] }, { "OperatorType": "Route", @@ -328,78 +378,41 @@ "QueryType": "SELECT", "Original": "select CHARACTER_SET_NAME from information_schema.CHARACTER_SETS union select user_name from unsharded", "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "0: utf8mb4_0900_ai_ci" - ], + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "0 COLLATE utf8mb4_0900_ai_ci", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "0 ASC COLLATE utf8mb4_0900_ai_ci", "Inputs": [ { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select CHARACTER_SET_NAME from information_schema.CHARACTER_SETS where 1 != 1", - "Query": "select distinct CHARACTER_SET_NAME from information_schema.CHARACTER_SETS", - "Table": "information_schema.CHARACTER_SETS" - }, - { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select user_name from unsharded where 1 != 1", - "Query": "select distinct user_name from unsharded", - "Table": "unsharded" - } - ] - } - ] - }, - "TablesUsed": [ - "main.unsharded" - ] - } - }, - { - "comment": "union of information_schema with normal table", - "query": "select * from unsharded union select * from information_schema.CHARACTER_SETS", - "plan": { - "QueryType": "SELECT", - "Original": "select * from unsharded union select * from information_schema.CHARACTER_SETS", - "Instructions": { - "OperatorType": "Distinct", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select * from unsharded where 1 != 1", - "Query": "select distinct * from unsharded", - "Table": "unsharded" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select CHARACTER_SET_NAME, DEFAULT_COLLATE_NAME, DESCRIPTION, MAXLEN from information_schema.CHARACTER_SETS where 1 != 1", - "Query": "select distinct CHARACTER_SET_NAME, DEFAULT_COLLATE_NAME, DESCRIPTION, MAXLEN from information_schema.CHARACTER_SETS", - "Table": "information_schema.CHARACTER_SETS" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select CHARACTER_SET_NAME from information_schema.CHARACTER_SETS where 1 != 1", + "Query": "select CHARACTER_SET_NAME from information_schema.CHARACTER_SETS", + "Table": "information_schema.CHARACTER_SETS" + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select user_name from unsharded where 1 != 1", + "Query": "select user_name from unsharded", + "Table": "unsharded" + } + ] } ] } @@ -410,54 +423,15 @@ ] } }, + { + "comment": "union of information_schema with normal table", + "query": "select * from unsharded union select * from information_schema.CHARACTER_SETS", + "plan": "VT09015: schema tracking required" + }, { "comment": "multi-shard union", "query": "(select id from user union select id from music) union select 1 from dual", - "plan": { - "QueryType": "SELECT", - "Original": "(select id from user union select id from music) union select 1 from dual", - "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "(0:1)" - ], - "ResultColumns": 1, - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1 union select id, weight_string(id) from music where 1 != 1", - "Query": "select id, weight_string(id) from `user` union select id, weight_string(id) from music", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Reference", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1, weight_string(1) from dual where 1 != 1", - "Query": "select distinct 1, weight_string(1) from dual", - "Table": "dual" - } - ] - } - ] - }, - "TablesUsed": [ - "main.dual", - "user.music", - "user.user" - ] - } + "plan": "VT13001: [BUG] index mismatch while pushing the column for '1'" }, { "comment": "multi-shard union", @@ -472,54 +446,7 @@ { "comment": "union with the same target shard because of vindex", "query": "select * from music where id = 1 union select * from user where id = 1", - "plan": { - "QueryType": "SELECT", - "Original": "select * from music where id = 1 union select * from user where id = 1", - "Instructions": { - "OperatorType": "Distinct", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select * from music where 1 != 1", - "Query": "select distinct * from music where id = 1", - "Table": "music", - "Values": [ - "INT64(1)" - ], - "Vindex": "music_user_map" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select * from `user` where 1 != 1", - "Query": "select distinct * from `user` where id = 1", - "Table": "`user`", - "Values": [ - "INT64(1)" - ], - "Vindex": "user_index" - } - ] - } - ] - }, - "TablesUsed": [ - "user.music", - "user.user" - ] - } + "plan": "VT09015: schema tracking required" }, { "comment": "union with different target shards", @@ -528,233 +455,78 @@ "QueryType": "SELECT", "Original": "select 1 from music where id = 1 union select 1 from music where id = 2", "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "0" - ], - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select 1 from music where 1 != 1", - "Query": "select distinct 1 from music where id = 1", - "Table": "music", - "Values": [ - "INT64(1)" - ], - "Vindex": "music_user_map" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select 1 from music where 1 != 1", - "Query": "select distinct 1 from music where id = 2", - "Table": "music", - "Values": [ - "INT64(2)" - ], - "Vindex": "music_user_map" - } - ] - } - ] - }, - "TablesUsed": [ - "user.music" - ] - } - }, - { - "comment": "multiple select statement have inner order by with union - TODO (systay) no need to send down ORDER BY if we are going to loose it with UNION DISTINCT", - "query": "(select id from user order by 1 desc) union (select id from user order by 1 asc)", - "plan": { - "QueryType": "SELECT", - "Original": "(select id from user order by 1 desc) union (select id from user order by 1 asc)", - "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "(0:1)" - ], - "ResultColumns": 1, - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "(select id, weight_string(id) from `user` where 1 != 1) union (select id, weight_string(id) from `user` where 1 != 1)", - "OrderBy": "(0|1) DESC", - "Query": "(select id, weight_string(id) from `user` order by id desc) union (select id, weight_string(id) from `user` order by id asc)", - "ResultColumns": 1, - "Table": "`user`" - } - ] - }, - "TablesUsed": [ - "user.user" - ] - } - }, - { - "comment": "multiple unions", - "query": "select 1 union select null union select 1.0 union select '1' union select 2 union select 2.0 from user", - "plan": { - "QueryType": "SELECT", - "Original": "select 1 union select null union select 1.0 union select '1' union select 2 union select 2.0 from user", - "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "0" - ], - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Reference", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 from dual where 1 != 1 union all select null from dual where 1 != 1 union all select 1.0 from dual where 1 != 1 union all select '1' from dual where 1 != 1 union select 2 from dual where 1 != 1", - "Query": "select 1 from dual union all select null from dual union all select 1.0 from dual union all select '1' from dual union select 2 from dual", - "Table": "dual" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select 2.0 from `user` where 1 != 1", - "Query": "select distinct 2.0 from `user`", - "Table": "`user`" - } - ] - } - ] - }, - "TablesUsed": [ - "main.dual", - "user.user" - ] - } - }, - { - "comment": "union distinct between a scatter query and a join (other side)", - "query": "(select user.id, user.name from user join user_extra where user_extra.extra = 'asdf') union select 'b','c' from user", - "plan": { - "QueryType": "SELECT", - "Original": "(select user.id, user.name from user join user_extra where user_extra.extra = 'asdf') union select 'b','c' from user", - "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "(0:2)", - "(1:3)" - ], - "ResultColumns": 2, + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "0", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "0 ASC", "Inputs": [ { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "L:0,L:1,L:2,L:3", - "TableName": "`user`_user_extra", + "OperatorType": "Concatenate", "Inputs": [ { "OperatorType": "Route", - "Variant": "Scatter", + "Variant": "EqualUnique", "Keyspace": { "Name": "user", "Sharded": true }, - "FieldQuery": "select `user`.id, `user`.`name`, weight_string(`user`.id), weight_string(`user`.`name`) from `user` where 1 != 1", - "Query": "select `user`.id, `user`.`name`, weight_string(`user`.id), weight_string(`user`.`name`) from `user`", - "Table": "`user`" + "FieldQuery": "select 1 from music where 1 != 1", + "Query": "select 1 from music where id = 1", + "Table": "music", + "Values": [ + "INT64(1)" + ], + "Vindex": "music_user_map" }, { "OperatorType": "Route", - "Variant": "Scatter", + "Variant": "EqualUnique", "Keyspace": { "Name": "user", "Sharded": true }, - "FieldQuery": "select 1 from user_extra where 1 != 1", - "Query": "select 1 from user_extra where user_extra.extra = 'asdf'", - "Table": "user_extra" + "FieldQuery": "select 1 from music where 1 != 1", + "Query": "select 1 from music where id = 2", + "Table": "music", + "Values": [ + "INT64(2)" + ], + "Vindex": "music_user_map" } ] - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select 'b', 'c', weight_string('b'), weight_string('c') from `user` where 1 != 1", - "Query": "select distinct 'b', 'c', weight_string('b'), weight_string('c') from `user`", - "Table": "`user`" } ] } ] }, "TablesUsed": [ - "user.user", - "user.user_extra" + "user.music" ] } }, { - "comment": "union distinct between a scatter query and a join (other side)", - "query": "select 'b','c' from user union (select user.id, user.name from user join user_extra where user_extra.extra = 'asdf')", + "comment": "multiple select statement have inner order by with union - TODO (systay) no need to send down ORDER BY if we are going to loose it with UNION DISTINCT", + "query": "(select id from user order by 1 desc) union (select id from user order by 1 asc)", "plan": { "QueryType": "SELECT", - "Original": "select 'b','c' from user union (select user.id, user.name from user join user_extra where user_extra.extra = 'asdf')", + "Original": "(select id from user order by 1 desc) union (select id from user order by 1 asc)", "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "0: utf8mb4_0900_ai_ci", - "1: utf8mb4_0900_ai_ci" - ], + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|1)", + "ResultColumns": 1, "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|1) ASC", "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select 'b', 'c' from `user` where 1 != 1", - "Query": "select distinct 'b', 'c' from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "L:0,L:1", - "TableName": "`user`_user_extra", + "OperatorType": "Concatenate", "Inputs": [ { "OperatorType": "Route", @@ -763,8 +535,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select `user`.id, `user`.`name` from `user` where 1 != 1", - "Query": "select `user`.id, `user`.`name` from `user`", + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from `user` order by id desc", "Table": "`user`" }, { @@ -774,9 +547,10 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select 1 from user_extra where 1 != 1", - "Query": "select 1 from user_extra where user_extra.extra = 'asdf'", - "Table": "user_extra" + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) ASC", + "Query": "select id, weight_string(id) from `user` order by id asc", + "Table": "`user`" } ] } @@ -785,49 +559,65 @@ ] }, "TablesUsed": [ - "user.user", - "user.user_extra" + "user.user" ] } }, { - "comment": "unmergable because we are using aggregation", - "query": "select count(*) as s from user union select count(*) as s from music", + "comment": "multiple unions", + "query": "select 1 union select null union select 1.0 union select '1' union select 2 union select 2.0 from user", + "plan": "VT13001: [BUG] index mismatch while pushing the column for '2.0'" + }, + { + "comment": "union distinct between a scatter query and a join (other side)", + "query": "(select user.id, user.name from user join user_extra where user_extra.extra = 'asdf') union select 'b','c' from user", "plan": { "QueryType": "SELECT", - "Original": "select count(*) as s from user union select count(*) as s from music", + "Original": "(select user.id, user.name from user join user_extra where user_extra.extra = 'asdf') union select 'b','c' from user", "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "0" - ], + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "ResultColumns": 2, "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Scalar", - "Aggregates": "sum_count_star(0) AS s", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select count(*) as s from `user` where 1 != 1", - "Query": "select count(*) as s from `user`", - "Table": "`user`" - } - ] - }, - { - "OperatorType": "Aggregate", - "Variant": "Scalar", - "Aggregates": "sum_count_star(0) AS s", - "Inputs": [ + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,L:1,L:2,L:3", + "TableName": "`user`_user_extra", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select `user`.id, `user`.`name`, weight_string(`user`.id), weight_string(`user`.`name`) from `user` where 1 != 1", + "Query": "select `user`.id, `user`.`name`, weight_string(`user`.id), weight_string(`user`.`name`) from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 1 from user_extra where 1 != 1", + "Query": "select 1 from user_extra where user_extra.extra = 'asdf'", + "Table": "user_extra" + } + ] + }, { "OperatorType": "Route", "Variant": "Scatter", @@ -835,9 +625,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select count(*) as s from music where 1 != 1", - "Query": "select count(*) as s from music", - "Table": "music" + "FieldQuery": "select 'b', 'c', weight_string('b'), weight_string('c') from `user` where 1 != 1", + "Query": "select 'b', 'c', weight_string('b'), weight_string('c') from `user`", + "Table": "`user`" } ] } @@ -845,45 +635,6 @@ } ] }, - "TablesUsed": [ - "user.music", - "user.user" - ] - } - }, - { - "comment": "Union in derived table with first SELECT being an UNION", - "query": "select * from ((select id from user union select id+1 from user) union select user_id from user_extra) as t", - "plan": { - "QueryType": "SELECT", - "Original": "select * from ((select id from user union select id+1 from user) union select user_id from user_extra) as t", - "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], - "Inputs": [ - { - "OperatorType": "Distinct", - "Collations": [ - "(0:1)" - ], - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1 union all select id + 1, weight_string(id + 1) from `user` where 1 != 1 union select user_id, weight_string(user_id) from user_extra where 1 != 1", - "Query": "select id, weight_string(id) from `user` union all select id + 1, weight_string(id + 1) from `user` union select user_id, weight_string(user_id) from user_extra", - "Table": "`user`" - } - ] - } - ] - }, "TablesUsed": [ "user.user", "user.user_extra" @@ -891,70 +642,20 @@ } }, { - "comment": "optimises away ORDER BY when it's safe to do", - "query": "(select id from user union select id from music order by id) union select 1 from unsharded", + "comment": "union distinct between a scatter query and a join (other side)", + "query": "select 'b','c' from user union (select user.id, user.name from user join user_extra where user_extra.extra = 'asdf')", "plan": { "QueryType": "SELECT", - "Original": "(select id from user union select id from music order by id) union select 1 from unsharded", + "Original": "select 'b','c' from user union (select user.id, user.name from user join user_extra where user_extra.extra = 'asdf')", "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "(0:1)" - ], - "ResultColumns": 1, + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "0 COLLATE utf8mb4_0900_ai_ci, 1 COLLATE utf8mb4_0900_ai_ci", "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1 union select id, weight_string(id) from music where 1 != 1", - "Query": "select id, weight_string(id) from `user` union select id, weight_string(id) from music", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1, weight_string(1) from unsharded where 1 != 1", - "Query": "select distinct 1, weight_string(1) from unsharded", - "Table": "unsharded" - } - ] - } - ] - }, - "TablesUsed": [ - "main.unsharded", - "user.music", - "user.user" - ] - } - }, - { - "comment": "push down the ::upper_limit to the sources, since we are doing DISTINCT on them, it's safe", - "query": "select id from user union select 3 limit 10", - "plan": { - "QueryType": "SELECT", - "Original": "select id from user union select 3 limit 10", - "Instructions": { - "OperatorType": "Limit", - "Count": "INT64(10)", - "Inputs": [ - { - "OperatorType": "Distinct", - "Collations": [ - "(0:1)" - ], - "ResultColumns": 1, + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "0 ASC COLLATE utf8mb4_0900_ai_ci, 1 ASC COLLATE utf8mb4_0900_ai_ci", "Inputs": [ { "OperatorType": "Concatenate", @@ -966,131 +667,152 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "Query": "select distinct id, weight_string(id) from `user` limit :__upper_limit", + "FieldQuery": "select 'b', 'c' from `user` where 1 != 1", + "Query": "select 'b', 'c' from `user`", "Table": "`user`" }, { - "OperatorType": "Route", - "Variant": "Reference", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 3, weight_string(3) from dual where 1 != 1", - "Query": "select distinct 3, weight_string(3) from dual limit :__upper_limit", - "Table": "dual" + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,L:1", + "TableName": "`user`_user_extra", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select `user`.id, `user`.`name` from `user` where 1 != 1", + "Query": "select `user`.id, `user`.`name` from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 1 from user_extra where 1 != 1", + "Query": "select 1 from user_extra where user_extra.extra = 'asdf'", + "Table": "user_extra" + } + ] } ] } ] } - ] - }, - "TablesUsed": [ - "main.dual", - "user.user" - ] - } - }, - { - "comment": "silly query that should be collapsed into a single unsharded UNION route", - "query": "(select 1 from unsharded union select 1 from unsharded union all select 1 from unsharded order by 1) union select 1 from unsharded union all select 1 from unsharded order by 1", - "plan": { - "QueryType": "SELECT", - "Original": "(select 1 from unsharded union select 1 from unsharded union all select 1 from unsharded order by 1) union select 1 from unsharded union all select 1 from unsharded order by 1", - "Instructions": { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "(select 1 from unsharded where 1 != 1 union select 1 from unsharded where 1 != 1 union all select 1 from unsharded where 1 != 1) union select 1 from unsharded where 1 != 1 union all select 1 from unsharded where 1 != 1", - "Query": "(select 1 from unsharded union select 1 from unsharded union all select 1 from unsharded order by 1 asc) union select 1 from unsharded union all select 1 from unsharded order by 1 asc", - "Table": "unsharded" + ] }, "TablesUsed": [ - "main.unsharded" + "user.user", + "user.user_extra" ] } }, { - "comment": "UNION that needs to be reordered to be merged more aggressively - able to get it down to 2 routes", - "query": "select col from unsharded union select id from user union select col2 from unsharded union select col from user_extra", + "comment": "unmergable because we are using aggregation", + "query": "select count(*) as s from user union select count(*) as s from music", "plan": { "QueryType": "SELECT", - "Original": "select col from unsharded union select id from user union select col2 from unsharded union select col from user_extra", + "Original": "select count(*) as s from user union select count(*) as s from music", "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "(0:1)" - ], - "ResultColumns": 1, + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "0", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "0 ASC", "Inputs": [ { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select col, weight_string(col) from unsharded where 1 != 1 union select col2, weight_string(col2) from unsharded where 1 != 1", - "Query": "select col, weight_string(col) from unsharded union select col2, weight_string(col2) from unsharded", - "Table": "unsharded" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1 union select col, weight_string(col) from user_extra where 1 != 1", - "Query": "select id, weight_string(id) from `user` union select col, weight_string(col) from user_extra", - "Table": "`user`" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "sum_count_star(0) AS s", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select count(*) as s from `user` where 1 != 1", + "Query": "select count(*) as s from `user`", + "Table": "`user`" + } + ] + }, + { + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "sum_count_star(0) AS s", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select count(*) as s from music where 1 != 1", + "Query": "select count(*) as s from music", + "Table": "music" + } + ] + } + ] } ] } ] }, "TablesUsed": [ - "main.unsharded", - "user.user", - "user.user_extra" + "user.music", + "user.user" ] } }, { - "comment": "derived table with union", - "query": "select tbl2.id FROM ((select id from user order by id limit 5) union all (select id from user order by id desc limit 5)) as tbl1 INNER JOIN user as tbl2 ON tbl1.id = tbl2.id", + "comment": "Union in derived table with first SELECT being an UNION", + "query": "select * from ((select id from user union select id+1 from user) union select user_id from user_extra) as t", + "plan": "VT13001: [BUG] index mismatch while pushing the column for 'user_id'" + }, + { + "comment": "optimises away ORDER BY when it's safe to do", + "query": "(select id from user union select id from music order by id) union select 1 from unsharded", + "plan": "VT13001: [BUG] index mismatch while pushing the column for '1'" + }, + { + "comment": "push down the ::upper_limit to the sources, since we are doing DISTINCT on them, it's safe", + "query": "select id from user union select 3 limit 10", "plan": { "QueryType": "SELECT", - "Original": "select tbl2.id FROM ((select id from user order by id limit 5) union all (select id from user order by id desc limit 5)) as tbl1 INNER JOIN user as tbl2 ON tbl1.id = tbl2.id", + "Original": "select id from user union select 3 limit 10", "Instructions": { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "R:0", - "JoinVars": { - "tbl1_id": 0 - }, - "TableName": "`user`_`user`", + "OperatorType": "Limit", + "Count": "INT64(10)", "Inputs": [ { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|1)", + "ResultColumns": 1, "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|1) ASC", "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(5)", + "OperatorType": "Concatenate", "Inputs": [ { "OperatorType": "Route", @@ -1100,58 +822,66 @@ "Sharded": true }, "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) ASC", - "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", - "ResultColumns": 1, + "Query": "select id, weight_string(id) from `user`", "Table": "`user`" - } - ] - }, - { - "OperatorType": "Limit", - "Count": "INT64(5)", - "Inputs": [ + }, { "OperatorType": "Route", - "Variant": "Scatter", + "Variant": "Reference", "Keyspace": { - "Name": "user", - "Sharded": true + "Name": "main", + "Sharded": false }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", - "ResultColumns": 1, - "Table": "`user`" + "FieldQuery": "select 3, weight_string(3) from dual where 1 != 1", + "Query": "select 3, weight_string(3) from dual", + "Table": "dual" } ] } ] } ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select tbl2.id from `user` as tbl2 where 1 != 1", - "Query": "select tbl2.id from `user` as tbl2 where tbl2.id = :tbl1_id", - "Table": "`user`", - "Values": [ - ":tbl1_id" - ], - "Vindex": "user_index" } ] }, "TablesUsed": [ + "main.dual", "user.user" ] } }, + { + "comment": "silly query that should be collapsed into a single unsharded UNION route", + "query": "(select 1 from unsharded union select 1 from unsharded union all select 1 from unsharded order by 1) union select 1 from unsharded union all select 1 from unsharded order by 1", + "plan": { + "QueryType": "SELECT", + "Original": "(select 1 from unsharded union select 1 from unsharded union all select 1 from unsharded order by 1) union select 1 from unsharded union all select 1 from unsharded order by 1", + "Instructions": { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "(select 1 from unsharded where 1 != 1 union select 1 from unsharded where 1 != 1 union all select 1 from unsharded where 1 != 1) union select 1 from unsharded where 1 != 1 union all select 1 from unsharded where 1 != 1", + "Query": "(select 1 from unsharded union select 1 from unsharded union all select 1 from unsharded order by 1 asc) union select 1 from unsharded union all select 1 from unsharded order by 1 asc", + "Table": "unsharded" + }, + "TablesUsed": [ + "main.unsharded" + ] + } + }, + { + "comment": "UNION that needs to be reordered to be merged more aggressively - able to get it down to 2 routes", + "query": "select col from unsharded union select id from user union select col2 from unsharded union select col from user_extra", + "plan": "VT13001: [BUG] index mismatch while pushing the column for 'col'" + }, + { + "comment": "derived table with union", + "query": "select tbl2.id FROM ((select id from user order by id limit 5) union all (select id from user order by id desc limit 5)) as tbl1 INNER JOIN user as tbl2 ON tbl1.id = tbl2.id", + "plan": "VT13001: [BUG] only weight_string function is expected - got tbl1.id" + }, { "comment": "ambiguous LIMIT", "query": "select id from user limit 1 union all select id from music limit 1", @@ -1175,25 +905,19 @@ { "comment": "union with invalid order by clause with table qualifier", "query": "select id from user union select 3 order by id", - "plan": "VT13001: [BUG] ORDER BY in complex query *planbuilder.distinct" - }, - { - "comment": "select 1 from (select id+42 as foo from user union select 1+id as foo from unsharded) as t", - "query": "select 1 from (select id+42 as foo from user union select 1+id as foo from unsharded) as t", "plan": { "QueryType": "SELECT", - "Original": "select 1 from (select id+42 as foo from user union select 1+id as foo from unsharded) as t", + "Original": "select id from user union select 3 order by id", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 2 - ], + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|1)", + "ResultColumns": 1, "Inputs": [ { - "OperatorType": "Distinct", - "Collations": [ - "(0:1)" - ], + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|1) ASC", "Inputs": [ { "OperatorType": "Concatenate", @@ -1205,20 +929,20 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id + 42 as foo, weight_string(id + 42), 1 from `user` where 1 != 1", - "Query": "select distinct id + 42 as foo, weight_string(id + 42), 1 from `user`", + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "Query": "select id, weight_string(id) from `user`", "Table": "`user`" }, { "OperatorType": "Route", - "Variant": "Unsharded", + "Variant": "Reference", "Keyspace": { "Name": "main", "Sharded": false }, - "FieldQuery": "select 1 + id as foo, weight_string(1 + id), 1 from unsharded where 1 != 1", - "Query": "select distinct 1 + id as foo, weight_string(1 + id), 1 from unsharded", - "Table": "unsharded" + "FieldQuery": "select 3, weight_string(3) from dual where 1 != 1", + "Query": "select 3, weight_string(3) from dual", + "Table": "dual" } ] } @@ -1227,79 +951,86 @@ ] }, "TablesUsed": [ - "main.unsharded", + "main.dual", "user.user" ] } }, { - "comment": "systable union query in derived table with constraint on outside (without star projection)", - "query": "select * from (select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `COLUMN_NAME` = 'primary'", - "plan": { - "QueryType": "SELECT", - "Original": "select * from (select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `COLUMN_NAME` = 'primary'", - "Instructions": { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select kcu.COLUMN_NAME from (select kcu.COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1 union select kcu.COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1) as kcu where 1 != 1", - "Query": "select kcu.COLUMN_NAME from (select kcu.COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name /* VARCHAR */ and COLUMN_NAME = 'primary' union select kcu.COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name1 /* VARCHAR */ and COLUMN_NAME = 'primary') as kcu", - "SysTableTableName": "[kcu_table_name1:VARCHAR(\"music\"), kcu_table_name:VARCHAR(\"user_extra\")]", - "SysTableTableSchema": "[VARCHAR(\"user\"), VARCHAR(\"user\")]", - "Table": "information_schema.key_column_usage" - } - } - }, - { - "comment": "pushes predicate on both sides of UNION", - "query": "select * from (select name, id as foo from user union select 'extra', user_id from user_extra) X where X.foo = 3", + "comment": "select 1 from (select id+42 as foo from user union select 1+id as foo from unsharded) as t", + "query": "select 1 from (select id+42 as foo from user union select 1+id as foo from unsharded) as t", "plan": { "QueryType": "SELECT", - "Original": "select * from (select name, id as foo from user union select 'extra', user_id from user_extra) X where X.foo = 3", + "Original": "select 1 from (select id+42 as foo from user union select 1+id as foo from unsharded) as t", "Instructions": { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select X.`name`, X.foo from (select `name`, id as foo from `user` where 1 != 1 union select 'extra', user_id from user_extra where 1 != 1) as X where 1 != 1", - "Query": "select X.`name`, X.foo from (select `name`, id as foo from `user` where id = 3 union select 'extra', user_id from user_extra where user_id = 3) as X", - "Table": "`user`", - "Values": [ - "INT64(3)" + "OperatorType": "Projection", + "Expressions": [ + "INT64(1) as 1" ], - "Vindex": "user_index" + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|1)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|1) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id + 42 as foo, weight_string(id + 42) from `user` where 1 != 1", + "Query": "select id + 42 as foo, weight_string(id + 42) from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 + id as foo, weight_string(1 + id) from unsharded where 1 != 1", + "Query": "select 1 + id as foo, weight_string(1 + id) from unsharded", + "Table": "unsharded" + } + ] + } + ] + } + ] + } + ] }, "TablesUsed": [ - "user.user", - "user.user_extra" + "main.unsharded", + "user.user" ] } }, + { + "comment": "systable union query in derived table with constraint on outside (without star projection)", + "query": "select * from (select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `COLUMN_NAME` = 'primary'", + "plan": "VT13001: [BUG] did not expect to add group by here" + }, + { + "comment": "pushes predicate on both sides of UNION", + "query": "select * from (select name, id as foo from user union select 'extra', user_id from user_extra) X where X.foo = 3", + "plan": "VT13001: [BUG] did not expect to add group by here" + }, { "comment": "systable union query in derived table with constraint on outside (star projection)", "query": "select * from (select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `constraint_name` = 'primary'", - "plan": { - "QueryType": "SELECT", - "Original": "select * from (select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `constraint_name` = 'primary'", - "Instructions": { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from (select kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1 union select kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1) as kcu where 1 != 1", - "Query": "select kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from (select kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name /* VARCHAR */ and CONSTRAINT_NAME = 'primary' union select kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name1 /* VARCHAR */ and CONSTRAINT_NAME = 'primary') as kcu", - "SysTableTableName": "[kcu_table_name1:VARCHAR(\"music\"), kcu_table_name:VARCHAR(\"user_extra\")]", - "SysTableTableSchema": "[VARCHAR(\"user\"), VARCHAR(\"user\")]", - "Table": "information_schema.key_column_usage" - } - } + "plan": "VT13001: [BUG] did not expect to add group by here" }, { "comment": "unknown columns are OK as long as the whole query is unsharded", @@ -1330,55 +1061,59 @@ "QueryType": "SELECT", "Original": "select id, foo, bar from unsharded union select user.intcol, user.textcol2, authoritative.col2 from user join authoritative", "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "(0:3)", - "(1:4)", - "(2:5)" - ], + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|3), (1|4), (2|5)", "ResultColumns": 3, "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|3) ASC, (1|4) ASC, (2|5) ASC", "Inputs": [ { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select id, foo, bar, weight_string(id), weight_string(foo), weight_string(bar) from unsharded where 1 != 1", - "Query": "select distinct id, foo, bar, weight_string(id), weight_string(foo), weight_string(bar) from unsharded", - "Table": "unsharded" - }, - { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "L:0,L:1,R:0,L:2,L:3,R:1", - "TableName": "`user`_authoritative", + "OperatorType": "Concatenate", "Inputs": [ { "OperatorType": "Route", - "Variant": "Scatter", + "Variant": "Unsharded", "Keyspace": { - "Name": "user", - "Sharded": true + "Name": "main", + "Sharded": false }, - "FieldQuery": "select `user`.intcol, `user`.textcol2, weight_string(`user`.intcol), weight_string(`user`.textcol2) from `user` where 1 != 1", - "Query": "select `user`.intcol, `user`.textcol2, weight_string(`user`.intcol), weight_string(`user`.textcol2) from `user`", - "Table": "`user`" + "FieldQuery": "select id, foo, bar, weight_string(id), weight_string(foo), weight_string(bar) from unsharded where 1 != 1", + "Query": "select id, foo, bar, weight_string(id), weight_string(foo), weight_string(bar) from unsharded", + "Table": "unsharded" }, { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select authoritative.col2, weight_string(authoritative.col2) from authoritative where 1 != 1", - "Query": "select authoritative.col2, weight_string(authoritative.col2) from authoritative", - "Table": "authoritative" + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,L:1,R:0,L:2,L:3,R:1", + "TableName": "`user`_authoritative", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select `user`.intcol, `user`.textcol2, weight_string(`user`.intcol), weight_string(`user`.textcol2) from `user` where 1 != 1", + "Query": "select `user`.intcol, `user`.textcol2, weight_string(`user`.intcol), weight_string(`user`.textcol2) from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select authoritative.col2, weight_string(authoritative.col2) from authoritative where 1 != 1", + "Query": "select authoritative.col2, weight_string(authoritative.col2) from authoritative", + "Table": "authoritative" + } + ] } ] } diff --git a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json index 40feb41c530..0f8ea9c7b5e 100644 --- a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json @@ -377,7 +377,7 @@ { "comment": "aggregation on union", "query": "select sum(col) from (select col from user union all select col from unsharded) t", - "plan": "VT12001: unsupported: using aggregation on top of a *planbuilder.concatenate plan" + "plan": "VT13001: [BUG] only weight_string function is expected - got col" }, { "comment": "insert having subquery in row values", From 7e89fdda7e66a841726743b6d2cb4c8abac8ca85 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Thu, 6 Jul 2023 15:46:48 +0200 Subject: [PATCH 02/44] rename the slices2 package to slice Signed-off-by: Andres Taylor --- go/{slices2/slices.go => slice/slice.go} | 4 ++-- go/test/endtoend/vtgate/queries/random/query_gen.go | 5 +++-- .../endtoend/vtgate/queries/random/random_expr_test.go | 5 +++-- go/viperutil/debug/handler.go | 4 ++-- go/vt/vtgate/engine/aggregations.go | 5 +++-- go/vt/vtgate/evalengine/compiler_asm.go | 5 +++-- go/vt/vtgate/evalengine/fn_json.go | 6 +++--- go/vt/vtgate/planbuilder/operator_transformers.go | 10 +++++----- go/vt/vtgate/planbuilder/operators/aggregator.go | 5 +++-- go/vt/vtgate/planbuilder/operators/apply_join.go | 9 +++++---- go/vt/vtgate/planbuilder/operators/operator.go | 4 ++-- go/vt/vtgate/planbuilder/operators/ordering.go | 5 +++-- go/vt/vtgate/planbuilder/operators/phases.go | 6 +++--- go/vt/vtgate/planbuilder/operators/sharded_routing.go | 5 +++-- go/vt/vtgate/planbuilder/operators/table.go | 4 ++-- go/vt/vtgate/planbuilder/operators/vindex.go | 4 ++-- 16 files changed, 47 insertions(+), 39 deletions(-) rename go/{slices2/slices.go => slice/slice.go} (95%) diff --git a/go/slices2/slices.go b/go/slice/slice.go similarity index 95% rename from go/slices2/slices.go rename to go/slice/slice.go index f5b091179cb..36130354c3d 100644 --- a/go/slices2/slices.go +++ b/go/slice/slice.go @@ -14,9 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Package slices2 contains generic Slice helpers; +// Package slice contains generic Slice helpers; // Some of this code is sourced from https://github.com/luraim/fun (Apache v2) -package slices2 +package slice // All returns true if all elements return true for given predicate func All[T any](s []T, fn func(T) bool) bool { diff --git a/go/test/endtoend/vtgate/queries/random/query_gen.go b/go/test/endtoend/vtgate/queries/random/query_gen.go index d673a904189..f8d9350bf5a 100644 --- a/go/test/endtoend/vtgate/queries/random/query_gen.go +++ b/go/test/endtoend/vtgate/queries/random/query_gen.go @@ -21,9 +21,10 @@ import ( "math/rand" "time" + "vitess.io/vitess/go/slice" + "golang.org/x/exp/slices" - "vitess.io/vitess/go/slices2" "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/sqlparser" ) @@ -459,7 +460,7 @@ func createLimit() *sqlparser.Limit { // returns a random expression and its type func getRandomExpr(tables []tableT) sqlparser.Expr { seed := time.Now().UnixNano() - g := sqlparser.NewGenerator(seed, 2, slices2.Map(tables, func(t tableT) sqlparser.ExprGenerator { return &t })...) + g := sqlparser.NewGenerator(seed, 2, slice.Map(tables, func(t tableT) sqlparser.ExprGenerator { return &t })...) return g.Expression() } diff --git a/go/test/endtoend/vtgate/queries/random/random_expr_test.go b/go/test/endtoend/vtgate/queries/random/random_expr_test.go index b4e1cfb9c2d..daa7ce851a9 100644 --- a/go/test/endtoend/vtgate/queries/random/random_expr_test.go +++ b/go/test/endtoend/vtgate/queries/random/random_expr_test.go @@ -20,7 +20,8 @@ import ( "testing" "time" - "vitess.io/vitess/go/slices2" + "vitess.io/vitess/go/slice" + "vitess.io/vitess/go/vt/sqlparser" ) @@ -47,6 +48,6 @@ func TestRandomExprWithTables(t *testing.T) { }...) seed := time.Now().UnixNano() - g := sqlparser.NewGenerator(seed, 3, slices2.Map(schemaTables, func(t tableT) sqlparser.ExprGenerator { return &t })...) + g := sqlparser.NewGenerator(seed, 3, slice.Map(schemaTables, func(t tableT) sqlparser.ExprGenerator { return &t })...) g.Expression() } diff --git a/go/viperutil/debug/handler.go b/go/viperutil/debug/handler.go index 43d83d235a4..b5730a2e41e 100644 --- a/go/viperutil/debug/handler.go +++ b/go/viperutil/debug/handler.go @@ -26,7 +26,7 @@ import ( "github.com/spf13/viper" "vitess.io/vitess/go/acl" - "vitess.io/vitess/go/slices2" + "vitess.io/vitess/go/slice" "vitess.io/vitess/go/viperutil/internal/registry" ) @@ -53,7 +53,7 @@ func HandlerFunc(w http.ResponseWriter, r *http.Request) { switch { case format == "": v.DebugTo(w) - case slices2.Any(viper.SupportedExts, func(ext string) bool { return ext == format }): + case slice.Any(viper.SupportedExts, func(ext string) bool { return ext == format }): // Got a supported format; write the config to a tempfile in that format, // then copy it to the response. // diff --git a/go/vt/vtgate/engine/aggregations.go b/go/vt/vtgate/engine/aggregations.go index 725e1882757..d8656d09d08 100644 --- a/go/vt/vtgate/engine/aggregations.go +++ b/go/vt/vtgate/engine/aggregations.go @@ -20,12 +20,13 @@ import ( "fmt" "strconv" + "vitess.io/vitess/go/slice" + "vitess.io/vitess/go/vt/vterrors" "google.golang.org/protobuf/proto" "vitess.io/vitess/go/mysql/collations" - "vitess.io/vitess/go/slices2" "vitess.io/vitess/go/sqltypes" binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" querypb "vitess.io/vitess/go/vt/proto/query" @@ -279,7 +280,7 @@ func convertFinal(current []sqltypes.Value, aggregates []*AggregateParams) ([]sq } func convertFields(fields []*querypb.Field, aggrs []*AggregateParams) []*querypb.Field { - fields = slices2.Map(fields, func(from *querypb.Field) *querypb.Field { + fields = slice.Map(fields, func(from *querypb.Field) *querypb.Field { return proto.Clone(from).(*querypb.Field) }) for _, aggr := range aggrs { diff --git a/go/vt/vtgate/evalengine/compiler_asm.go b/go/vt/vtgate/evalengine/compiler_asm.go index 544dacfdad0..b60f1150490 100644 --- a/go/vt/vtgate/evalengine/compiler_asm.go +++ b/go/vt/vtgate/evalengine/compiler_asm.go @@ -33,6 +33,8 @@ import ( "strconv" "time" + "vitess.io/vitess/go/slice" + "github.com/google/uuid" "vitess.io/vitess/go/mysql/hex" @@ -46,7 +48,6 @@ import ( "vitess.io/vitess/go/mysql/decimal" "vitess.io/vitess/go/mysql/fastparse" "vitess.io/vitess/go/mysql/json" - "vitess.io/vitess/go/slices2" "vitess.io/vitess/go/sqltypes" querypb "vitess.io/vitess/go/vt/proto/query" "vitess.io/vitess/go/vt/proto/vtrpc" @@ -2172,7 +2173,7 @@ func (asm *assembler) Fn_JSON_CONTAINS_PATH(match jsonMatch, paths []*json.Path) } func (asm *assembler) Fn_JSON_EXTRACT0(jp []*json.Path) { - multi := len(jp) > 1 || slices2.Any(jp, func(path *json.Path) bool { return path.ContainsWildcards() }) + multi := len(jp) > 1 || slice.Any(jp, func(path *json.Path) bool { return path.ContainsWildcards() }) if multi { asm.emit(func(env *ExpressionEnv) int { diff --git a/go/vt/vtgate/evalengine/fn_json.go b/go/vt/vtgate/evalengine/fn_json.go index 31f568a3df5..7c7c6a67f8d 100644 --- a/go/vt/vtgate/evalengine/fn_json.go +++ b/go/vt/vtgate/evalengine/fn_json.go @@ -19,7 +19,7 @@ package evalengine import ( "vitess.io/vitess/go/mysql/collations" "vitess.io/vitess/go/mysql/json" - "vitess.io/vitess/go/slices2" + "vitess.io/vitess/go/slice" "vitess.io/vitess/go/sqltypes" querypb "vitess.io/vitess/go/vt/proto/query" vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" @@ -131,7 +131,7 @@ func (call *builtinJSONExtract) compile(c *compiler) (ctype, error) { return ctype{}, err } - if slices2.All(call.Arguments[1:], func(expr Expr) bool { return expr.constant() }) { + if slice.All(call.Arguments[1:], func(expr Expr) bool { return expr.constant() }) { paths := make([]*json.Path, 0, len(call.Arguments[1:])) for _, arg := range call.Arguments[1:] { @@ -406,7 +406,7 @@ func (call *builtinJSONContainsPath) compile(c *compiler) (ctype, error) { return ctype{}, c.unsupported(call) } - if !slices2.All(call.Arguments[2:], func(expr Expr) bool { return expr.constant() }) { + if !slice.All(call.Arguments[2:], func(expr Expr) bool { return expr.constant() }) { return ctype{}, c.unsupported(call) } diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index c1e392e55eb..9b8d2086a2d 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -23,7 +23,7 @@ import ( "strconv" "strings" - "vitess.io/vitess/go/slices2" + "vitess.io/vitess/go/slice" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" @@ -163,12 +163,12 @@ func transformProjection(ctx *plancontext.PlanningContext, op *operators.Project return useSimpleProjection(op, cols, src) } - expressions := slices2.Map(op.Projections, func(from operators.ProjExpr) sqlparser.Expr { + expressions := slice.Map(op.Projections, func(from operators.ProjExpr) sqlparser.Expr { return from.GetExpr() }) failed := false - evalengineExprs := slices2.Map(op.Projections, func(from operators.ProjExpr) evalengine.Expr { + evalengineExprs := slice.Map(op.Projections, func(from operators.ProjExpr) evalengine.Expr { switch e := from.(type) { case operators.Eval: return e.EExpr @@ -181,7 +181,7 @@ func transformProjection(ctx *plancontext.PlanningContext, op *operators.Project } }) var primitive *engine.Projection - columnNames := slices2.Map(op.Columns, func(from *sqlparser.AliasedExpr) string { + columnNames := slice.Map(op.Columns, func(from *sqlparser.AliasedExpr) string { return from.ColumnName() }) @@ -637,7 +637,7 @@ func getAllTableNames(op *operators.Route) ([]string, error) { } func transformUnionPlan(ctx *plancontext.PlanningContext, op *operators.Union) (logicalPlan, error) { - sources, err := slices2.MapWithError(op.Sources, func(src ops.Operator) (logicalPlan, error) { + sources, err := slice.MapWithError(op.Sources, func(src ops.Operator) (logicalPlan, error) { plan, err := transformToLogicalPlan(ctx, src, false) if err != nil { return nil, err diff --git a/go/vt/vtgate/planbuilder/operators/aggregator.go b/go/vt/vtgate/planbuilder/operators/aggregator.go index b4210debd28..66a38a06b59 100644 --- a/go/vt/vtgate/planbuilder/operators/aggregator.go +++ b/go/vt/vtgate/planbuilder/operators/aggregator.go @@ -20,9 +20,10 @@ import ( "fmt" "strings" + "vitess.io/vitess/go/slice" + "golang.org/x/exp/slices" - "vitess.io/vitess/go/slices2" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine/opcode" @@ -230,7 +231,7 @@ func (a *Aggregator) GetSelectExprs() (sqlparser.SelectExprs, error) { } func (a *Aggregator) ShortDescription() string { - columns := slices2.Map(a.Columns, func(from *sqlparser.AliasedExpr) string { + columns := slice.Map(a.Columns, func(from *sqlparser.AliasedExpr) string { return sqlparser.String(from) }) if a.Alias != "" { diff --git a/go/vt/vtgate/planbuilder/operators/apply_join.go b/go/vt/vtgate/planbuilder/operators/apply_join.go index 41080e39902..d98780e6296 100644 --- a/go/vt/vtgate/planbuilder/operators/apply_join.go +++ b/go/vt/vtgate/planbuilder/operators/apply_join.go @@ -20,10 +20,11 @@ import ( "fmt" "strings" + "vitess.io/vitess/go/slice" + "golang.org/x/exp/maps" "golang.org/x/exp/slices" - "vitess.io/vitess/go/slices2" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" @@ -180,7 +181,7 @@ func (a *ApplyJoin) pushColRight(ctx *plancontext.PlanningContext, e *sqlparser. } func (a *ApplyJoin) GetColumns() ([]*sqlparser.AliasedExpr, error) { - return slices2.Map(a.ColumnsAST, joinColumnToAliasedExpr), nil + return slice.Map(a.ColumnsAST, joinColumnToAliasedExpr), nil } func (a *ApplyJoin) GetSelectExprs() (sqlparser.SelectExprs, error) { @@ -271,7 +272,7 @@ func (a *ApplyJoin) planOffsets(ctx *plancontext.PlanningContext) (err error) { } a.Vars[col.BvNames[i]] = offset } - lhsColumns := slices2.Map(col.LHSExprs, func(from sqlparser.Expr) *sqlparser.ColName { + lhsColumns := slice.Map(col.LHSExprs, func(from sqlparser.Expr) *sqlparser.ColName { col, ok := from.(*sqlparser.ColName) if !ok { // todo: there is no good reason to keep this limitation around @@ -293,7 +294,7 @@ func (a *ApplyJoin) addOffset(offset int) { func (a *ApplyJoin) ShortDescription() string { pred := sqlparser.String(a.Predicate) - columns := slices2.Map(a.ColumnsAST, func(from JoinColumn) string { + columns := slice.Map(a.ColumnsAST, func(from JoinColumn) string { return sqlparser.String(from.Original) }) return fmt.Sprintf("on %s columns: %s", pred, strings.Join(columns, ", ")) diff --git a/go/vt/vtgate/planbuilder/operators/operator.go b/go/vt/vtgate/planbuilder/operators/operator.go index 8fa73e882fe..1ba1de3b0fc 100644 --- a/go/vt/vtgate/planbuilder/operators/operator.go +++ b/go/vt/vtgate/planbuilder/operators/operator.go @@ -34,7 +34,7 @@ The operators go through a few phases while planning: package operators import ( - "vitess.io/vitess/go/slices2" + "vitess.io/vitess/go/slice" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" @@ -150,7 +150,7 @@ func transformColumnsToSelectExprs(op ops.Operator) (sqlparser.SelectExprs, erro if err != nil { return nil, err } - selExprs := slices2.Map(columns, func(from *sqlparser.AliasedExpr) sqlparser.SelectExpr { + selExprs := slice.Map(columns, func(from *sqlparser.AliasedExpr) sqlparser.SelectExpr { return from }) return selExprs, nil diff --git a/go/vt/vtgate/planbuilder/operators/ordering.go b/go/vt/vtgate/planbuilder/operators/ordering.go index 2ff0901c97b..14dec07c193 100644 --- a/go/vt/vtgate/planbuilder/operators/ordering.go +++ b/go/vt/vtgate/planbuilder/operators/ordering.go @@ -19,9 +19,10 @@ package operators import ( "strings" + "vitess.io/vitess/go/slice" + "golang.org/x/exp/slices" - "vitess.io/vitess/go/slices2" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" @@ -111,7 +112,7 @@ func (o *Ordering) planOffsets(ctx *plancontext.PlanningContext) error { } func (o *Ordering) ShortDescription() string { - ordering := slices2.Map(o.Order, func(o ops.OrderBy) string { + ordering := slice.Map(o.Order, func(o ops.OrderBy) string { return sqlparser.String(o.Inner) }) return strings.Join(ordering, ", ") diff --git a/go/vt/vtgate/planbuilder/operators/phases.go b/go/vt/vtgate/planbuilder/operators/phases.go index 4a8c1ca0067..3aaf5dcc7d9 100644 --- a/go/vt/vtgate/planbuilder/operators/phases.go +++ b/go/vt/vtgate/planbuilder/operators/phases.go @@ -17,7 +17,7 @@ limitations under the License. package operators import ( - "vitess.io/vitess/go/slices2" + "vitess.io/vitess/go/slice" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/rewrite" @@ -70,7 +70,7 @@ func addOrderBysForAggregations(ctx *plancontext.PlanningContext, root ops.Opera if !requireOrdering { return in, rewrite.SameTree, nil } - orderBys := slices2.Map(aggrOp.Grouping, func(from GroupBy) ops.OrderBy { + orderBys := slice.Map(aggrOp.Grouping, func(from GroupBy) ops.OrderBy { return from.AsOrderBy() }) if aggrOp.DistinctExpr != nil { @@ -92,7 +92,7 @@ func addOrderBysForAggregations(ctx *plancontext.PlanningContext, root ops.Opera } func needsOrdering(ctx *plancontext.PlanningContext, in *Aggregator) (bool, error) { - requiredOrder := slices2.Map(in.Grouping, func(from GroupBy) sqlparser.Expr { + requiredOrder := slice.Map(in.Grouping, func(from GroupBy) sqlparser.Expr { return from.SimplifiedExpr }) if in.DistinctExpr != nil { diff --git a/go/vt/vtgate/planbuilder/operators/sharded_routing.go b/go/vt/vtgate/planbuilder/operators/sharded_routing.go index ee411492838..6eaa30a86d5 100644 --- a/go/vt/vtgate/planbuilder/operators/sharded_routing.go +++ b/go/vt/vtgate/planbuilder/operators/sharded_routing.go @@ -19,8 +19,9 @@ package operators import ( "golang.org/x/exp/slices" + "vitess.io/vitess/go/slice" + "vitess.io/vitess/go/mysql/collations" - "vitess.io/vitess/go/slices2" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" @@ -155,7 +156,7 @@ func (tr *ShardedRouting) Clone() Routing { selected = &t } return &ShardedRouting{ - VindexPreds: slices2.Map(tr.VindexPreds, func(from *VindexPlusPredicates) *VindexPlusPredicates { + VindexPreds: slice.Map(tr.VindexPreds, func(from *VindexPlusPredicates) *VindexPlusPredicates { // we do this to create a copy of the struct p := *from return &p diff --git a/go/vt/vtgate/planbuilder/operators/table.go b/go/vt/vtgate/planbuilder/operators/table.go index 955120adf87..5fe54c3b488 100644 --- a/go/vt/vtgate/planbuilder/operators/table.go +++ b/go/vt/vtgate/planbuilder/operators/table.go @@ -19,7 +19,7 @@ package operators import ( "fmt" - "vitess.io/vitess/go/slices2" + "vitess.io/vitess/go/slice" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" @@ -78,7 +78,7 @@ func (to *Table) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.Ali } func (to *Table) GetColumns() ([]*sqlparser.AliasedExpr, error) { - return slices2.Map(to.Columns, colNameToExpr), nil + return slice.Map(to.Columns, colNameToExpr), nil } func (to *Table) GetSelectExprs() (sqlparser.SelectExprs, error) { diff --git a/go/vt/vtgate/planbuilder/operators/vindex.go b/go/vt/vtgate/planbuilder/operators/vindex.go index e39d245bb50..0b6ee6663e5 100644 --- a/go/vt/vtgate/planbuilder/operators/vindex.go +++ b/go/vt/vtgate/planbuilder/operators/vindex.go @@ -17,7 +17,7 @@ limitations under the License. package operators import ( - "vitess.io/vitess/go/slices2" + "vitess.io/vitess/go/slice" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" @@ -83,7 +83,7 @@ func colNameToExpr(c *sqlparser.ColName) *sqlparser.AliasedExpr { } func (v *Vindex) GetColumns() ([]*sqlparser.AliasedExpr, error) { - return slices2.Map(v.Columns, colNameToExpr), nil + return slice.Map(v.Columns, colNameToExpr), nil } func (v *Vindex) GetSelectExprs() (sqlparser.SelectExprs, error) { From 5b6b159de0fdfb1c6e3ed37776af26833b218cab Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Thu, 6 Jul 2023 15:56:31 +0200 Subject: [PATCH 03/44] rename Merge to MergeJoin to make place for MergeUnion Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/operators/merging.go | 14 +++++++------- .../vtgate/planbuilder/operators/route_planning.go | 2 +- .../planbuilder/operators/sharded_routing.go | 4 ++-- .../planbuilder/operators/subquery_planning.go | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/merging.go b/go/vt/vtgate/planbuilder/operators/merging.go index ef8da1ef280..adc2951d8cb 100644 --- a/go/vt/vtgate/planbuilder/operators/merging.go +++ b/go/vt/vtgate/planbuilder/operators/merging.go @@ -25,10 +25,10 @@ import ( "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" ) -// Merge checks whether two operators can be merged into a single one. +// MergeJoin checks whether two operators can be merged into a single one. // If they can be merged, a new operator with the merged routing is returned // If they cannot be merged, nil is returned. -func Merge(ctx *plancontext.PlanningContext, lhs, rhs ops.Operator, joinPredicates []sqlparser.Expr, m merger) (ops.Operator, error) { +func MergeJoin(ctx *plancontext.PlanningContext, lhs, rhs ops.Operator, joinPredicates []sqlparser.Expr, m merger) (ops.Operator, error) { lhsRoute, rhsRoute := operatorsToRoutes(lhs, rhs) if lhsRoute == nil || rhsRoute == nil { return nil, nil @@ -78,7 +78,7 @@ func Merge(ctx *plancontext.PlanningContext, lhs, rhs ops.Operator, joinPredicat type ( merger interface { - mergeTables(r1, r2 *ShardedRouting, op1, op2 *Route) (*Route, error) + mergeShardedRouting(r1, r2 *ShardedRouting, op1, op2 *Route) (*Route, error) merge(op1, op2 *Route, r Routing) (*Route, error) } @@ -188,7 +188,7 @@ func newJoinMerge(ctx *plancontext.PlanningContext, predicates []sqlparser.Expr, } } -func (jm *joinMerger) mergeTables(r1, r2 *ShardedRouting, op1, op2 *Route) (*Route, error) { +func (jm *joinMerger) mergeShardedRouting(r1, r2 *ShardedRouting, op1, op2 *Route) (*Route, error) { tr := &ShardedRouting{ VindexPreds: append(r1.VindexPreds, r2.VindexPreds...), keyspace: r1.keyspace, @@ -272,7 +272,7 @@ func (s *subQueryMerger) markPredicateInOuterRouting(outer *ShardedRouting, inne } } -func (s *subQueryMerger) mergeTables(outer, inner *ShardedRouting, op1, op2 *Route) (*Route, error) { +func (s *subQueryMerger) mergeShardedRouting(outer, inner *ShardedRouting, op1, op2 *Route) (*Route, error) { s.subq.ExtractedSubquery.Merged = true routing, err := s.markPredicateInOuterRouting(outer, inner) @@ -300,8 +300,8 @@ func (s *subQueryMerger) merge(outer, inner *Route, routing Routing) (*Route, er return outer, nil } -func (d *mergeDecorator) mergeTables(outer, inner *ShardedRouting, op1, op2 *Route) (*Route, error) { - merged, err := d.inner.mergeTables(outer, inner, op1, op2) +func (d *mergeDecorator) mergeShardedRouting(outer, inner *ShardedRouting, op1, op2 *Route) (*Route, error) { + merged, err := d.inner.mergeShardedRouting(outer, inner, op1, op2) if err != nil { return nil, err } diff --git a/go/vt/vtgate/planbuilder/operators/route_planning.go b/go/vt/vtgate/planbuilder/operators/route_planning.go index ac08b1fef62..afde39f366d 100644 --- a/go/vt/vtgate/planbuilder/operators/route_planning.go +++ b/go/vt/vtgate/planbuilder/operators/route_planning.go @@ -404,7 +404,7 @@ func requiresSwitchingSides(ctx *plancontext.PlanningContext, op ops.Operator) b } func mergeOrJoin(ctx *plancontext.PlanningContext, lhs, rhs ops.Operator, joinPredicates []sqlparser.Expr, inner bool) (ops.Operator, *rewrite.ApplyResult, error) { - newPlan, err := Merge(ctx, lhs, rhs, joinPredicates, newJoinMerge(ctx, joinPredicates, inner)) + newPlan, err := MergeJoin(ctx, lhs, rhs, joinPredicates, newJoinMerge(ctx, joinPredicates, inner)) if err != nil { return nil, nil, err } diff --git a/go/vt/vtgate/planbuilder/operators/sharded_routing.go b/go/vt/vtgate/planbuilder/operators/sharded_routing.go index 6eaa30a86d5..0a082c8460a 100644 --- a/go/vt/vtgate/planbuilder/operators/sharded_routing.go +++ b/go/vt/vtgate/planbuilder/operators/sharded_routing.go @@ -609,7 +609,7 @@ func tryMergeShardedRouting(ctx *plancontext.PlanningContext, routeA *Route, rou aExpr := tblA.VindexExpressions() bExpr := tblB.VindexExpressions() if aVdx == bVdx && gen4ValuesEqual(ctx, aExpr, bExpr) { - return m.mergeTables(tblA, tblB, routeA, routeB) + return m.mergeShardedRouting(tblA, tblB, routeA, routeB) } } @@ -633,7 +633,7 @@ func tryMergeShardedRouting(ctx *plancontext.PlanningContext, routeA *Route, rou if !canMerge { return nil, nil } - return m.mergeTables(tblA, tblB, routeA, routeB) + return m.mergeShardedRouting(tblA, tblB, routeA, routeB) } return nil, nil } diff --git a/go/vt/vtgate/planbuilder/operators/subquery_planning.go b/go/vt/vtgate/planbuilder/operators/subquery_planning.go index 28dd005e2f1..06437005611 100644 --- a/go/vt/vtgate/planbuilder/operators/subquery_planning.go +++ b/go/vt/vtgate/planbuilder/operators/subquery_planning.go @@ -183,7 +183,7 @@ func tryMergeSubqueryWithRoute( return nil, nil } - merged, err := Merge(ctx, outerOp, subq, joinPredicates, merger) + merged, err := MergeJoin(ctx, outerOp, subq, joinPredicates, merger) if err != nil { return nil, err } @@ -210,7 +210,7 @@ func tryMergeSubqueryWithRoute( if !ok { return nil, nil } - merged, err := merger.mergeTables(outerRouting, innerRouting, outerOp, subqueryRoute) + merged, err := merger.mergeShardedRouting(outerRouting, innerRouting, outerOp, subqueryRoute) mergedRouting := merged.Routing.(*ShardedRouting) mergedRouting.PickBestAvailableVindex() return merged, err From 5951c269dbad79bad8a02824c32b776b6c869e79 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Thu, 6 Jul 2023 16:31:39 +0200 Subject: [PATCH 04/44] rewrite the compact rules for UNION Signed-off-by: Andres Taylor --- .../planbuilder/operators/horizon_planning.go | 13 + .../vtgate/planbuilder/operators/operator.go | 4 - go/vt/vtgate/planbuilder/operators/union.go | 43 +- .../testdata/large_union_cases.json | 2200 ++++++++++++++++- .../planbuilder/testdata/union_cases.json | 538 +++- 5 files changed, 2729 insertions(+), 69 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/horizon_planning.go b/go/vt/vtgate/planbuilder/operators/horizon_planning.go index ae257f55330..b1d14e1f368 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_planning.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_planning.go @@ -36,6 +36,9 @@ type ( ) func errHorizonNotPlanned() error { + if rewrite.DebugOperatorTree { + fmt.Println("ERROR! Falling back on the old horizon planner") + } return _errHorizonNotPlanned } @@ -79,6 +82,11 @@ func tryHorizonPlanning(ctx *plancontext.PlanningContext, root ops.Operator) (ou return nil, err } + output, err = compact(ctx, output) + if err != nil { + return nil, err + } + return } @@ -104,6 +112,11 @@ func planHorizons(ctx *plancontext.PlanningContext, root ops.Operator) (op ops.O if err != nil { return nil, err } + + op, err = compact(ctx, op) + if err != nil { + return nil, err + } } return addGroupByOnRHSOfJoin(op) diff --git a/go/vt/vtgate/planbuilder/operators/operator.go b/go/vt/vtgate/planbuilder/operators/operator.go index 1ba1de3b0fc..9e0b63a4b7d 100644 --- a/go/vt/vtgate/planbuilder/operators/operator.go +++ b/go/vt/vtgate/planbuilder/operators/operator.go @@ -75,10 +75,6 @@ func PlanQuery(ctx *plancontext.PlanningContext, stmt sqlparser.Statement) (ops. return nil, err } - if op, err = compact(ctx, op); err != nil { - return nil, err - } - _, isRoute := op.(*Route) if !isRoute && ctx.SemTable.NotSingleRouteErr != nil { // If we got here, we don't have a single shard plan diff --git a/go/vt/vtgate/planbuilder/operators/union.go b/go/vt/vtgate/planbuilder/operators/union.go index f368c8052c5..01f3d029d2f 100644 --- a/go/vt/vtgate/planbuilder/operators/union.go +++ b/go/vt/vtgate/planbuilder/operators/union.go @@ -161,37 +161,30 @@ func (u *Union) GetSelectFor(source int) (*sqlparser.Select, error) { func (u *Union) Compact(*plancontext.PlanningContext) (ops.Operator, *rewrite.ApplyResult, error) { var newSources []ops.Operator - var anythingChanged *rewrite.ApplyResult - for _, source := range u.Sources { - var other *Union - horizon, ok := source.(*Horizon) - if ok { - union, ok := horizon.Source.(*Union) - if ok { - other = union - } - } - if other == nil { - newSources = append(newSources, source) + var newSelects []sqlparser.SelectExprs + merged := false + + for idx, source := range u.Sources { + other, ok := source.(*Union) + + if ok && (u.Distinct || len(other.Ordering) == 0 && !other.Distinct) { + newSources = append(newSources, other.Sources...) + newSelects = append(newSelects, other.Selects...) + merged = true continue } - anythingChanged = anythingChanged.Merge(rewrite.NewTree("merged UNIONs", other)) - switch { - case len(other.Ordering) == 0 && !other.Distinct: - fallthrough - case u.Distinct: - // if the current UNION is a DISTINCT, we can safely ignore everything from children UNIONs, except LIMIT - newSources = append(newSources, other.Sources...) - default: - newSources = append(newSources, other) - } + newSources = append(newSources, source) + newSelects = append(newSelects, u.Selects[idx]) } - if anythingChanged != rewrite.SameTree { - u.Sources = newSources + + if !merged { + return u, rewrite.SameTree, nil } - return u, anythingChanged, nil + u.Sources = newSources + u.Selects = newSelects + return u, rewrite.NewTree("merged UNIONs", u), nil } func (u *Union) AddColumn(ctx *plancontext.PlanningContext, ae *sqlparser.AliasedExpr, reuseExisting, addToGroupBy bool) (ops.Operator, int, error) { diff --git a/go/vt/vtgate/planbuilder/testdata/large_union_cases.json b/go/vt/vtgate/planbuilder/testdata/large_union_cases.json index 5679aa826eb..2f2ccf75f55 100644 --- a/go/vt/vtgate/planbuilder/testdata/large_union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/large_union_cases.json @@ -2,6 +2,2204 @@ { "comment": "this testcase breaks goland, so it lives on its own file", "query": "(SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270698330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270699497 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270703806 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270707364 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270714657 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270721330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270812079 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271011532 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271034164 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271034177 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271066849 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271098740 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271355000 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271924504 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272086055 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272127855 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272191137 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272468271 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270644941 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270650576 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270652906 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270660650 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270670201 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270698330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270699497 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270707364 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271799956 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271799956 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270644941 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270649256 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270653671 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270670201 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270717223 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270720898 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271346411 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271352121 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271354908 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271367516 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271472522 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271821733 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272068709 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272127855 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272191137 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272244005 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272468271 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272244005 ORDER BY created_at ASC, id ASC LIMIT 11)", - "plan": "VT13001: [BUG] index mismatch while pushing the column for 'content'" + "plan": { + "QueryType": "SELECT", + "Original": "(SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270698330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270699497 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270703806 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270707364 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270714657 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270721330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270812079 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271011532 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271034164 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271034177 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271066849 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271098740 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271355000 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271924504 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272086055 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272127855 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272191137 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272468271 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270644941 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270650576 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270652906 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270660650 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270670201 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270698330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270699497 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270707364 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271799956 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271799956 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270644941 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270649256 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270653671 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270670201 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270717223 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270720898 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271346411 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271352121 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271354908 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271367516 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271472522 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271821733 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272068709 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272127855 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272191137 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272244005 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272468271 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272244005 ORDER BY created_at ASC, id ASC LIMIT 11)", + "Instructions": { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "ResultColumns": 2, + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|2), (1|3)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270698330 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270698330)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270699497 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270699497)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270703806 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270703806)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270707364 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270707364)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270714657 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270714657)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270721330 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270721330)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270812079 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270812079)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271011532 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271011532)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271034164 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271034164)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271034177 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271034177)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271066849 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271066849)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271098740 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271098740)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271355000 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271355000)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271639345 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271639345)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271914117 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271914117)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271924504 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271924504)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1272086055 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272086055)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1272127855 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272127855)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1272191137 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272191137)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1272468271 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272468271)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270637436 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270637436)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270644941 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270644941)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270650576 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270650576)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270652906 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270652906)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270660650 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270660650)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270670201 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270670201)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270698330 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270698330)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270699497 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270699497)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270707364 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270707364)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271365691)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271799956 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271799956)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271914117 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271914117)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270637436 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270637436)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271799956 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271799956)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270637436 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270637436)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271639345 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271639345)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270644941 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270644941)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270649256 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270649256)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270653671 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270653671)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270670201 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270670201)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270717223 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270717223)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270720898 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270720898)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270982590 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270982590)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271346411 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271346411)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271352121 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271352121)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271354908 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271354908)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271365691)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271367516 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271367516)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271472522 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271472522)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271607757 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271607757)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271639345 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271639345)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271821733 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271821733)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271914117 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271914117)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1272068709 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272068709)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1272127855 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272127855)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1272191137 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272191137)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1272244005 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272244005)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1272468271 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272468271)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270982590 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270982590)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271365691)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271607757 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271607757)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1270982590 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270982590)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271365691)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1271607757 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271607757)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content) from music where user_id = 1272244005 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272244005)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] + }, + "TablesUsed": [ + "user.music" + ] + } } ] diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 0aeababca9b..4680bcc969f 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -316,53 +316,75 @@ "QueryType": "SELECT", "Original": "select id from user where id = 1 union select id from user where id = 1 union all select id from user", "Instructions": { - "OperatorType": "Concatenate", + "OperatorType": "SimpleProjection", + "Columns": [ + 0 + ], "Inputs": [ { "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id from `user` where 1 != 1", - "Query": "select id from `user` where id = 1", - "Table": "`user`", - "Values": [ - "INT64(1)" - ], - "Vindex": "user_index" + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|1)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|1) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "Query": "select id, weight_string(id) from `user` where id = 1", + "Table": "`user`", + "Values": [ + "INT64(1)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "Query": "select id, weight_string(id) from `user` where id = 1", + "Table": "`user`", + "Values": [ + "INT64(1)" + ], + "Vindex": "user_index" + } + ] + } + ] + } + ] }, { "OperatorType": "Route", - "Variant": "EqualUnique", + "Variant": "Scatter", "Keyspace": { "Name": "user", "Sharded": true }, "FieldQuery": "select id from `user` where 1 != 1", - "Query": "select id from `user` where id = 1", - "Table": "`user`", - "Values": [ - "INT64(1)" - ], - "Vindex": "user_index" + "Query": "select id from `user`", + "Table": "`user`" } ] - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id from `user` where 1 != 1", - "Query": "select id from `user`", - "Table": "`user`" } ] }, @@ -431,7 +453,87 @@ { "comment": "multi-shard union", "query": "(select id from user union select id from music) union select 1 from dual", - "plan": "VT13001: [BUG] index mismatch while pushing the column for '1'" + "plan": { + "QueryType": "SELECT", + "Original": "(select id from user union select id from music) union select 1 from dual", + "Instructions": { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|1)", + "ResultColumns": 1, + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|1) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|1)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|1) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "Query": "select id, weight_string(id) from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from music where 1 != 1", + "Query": "select id, weight_string(id) from music", + "Table": "music" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "Reference", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1, weight_string(1) from dual where 1 != 1", + "Query": "select 1, weight_string(1) from dual", + "Table": "dual" + } + ] + } + ] + } + ] + }, + "TablesUsed": [ + "main.dual", + "user.music", + "user.user" + ] + } }, { "comment": "multi-shard union", @@ -566,7 +668,175 @@ { "comment": "multiple unions", "query": "select 1 union select null union select 1.0 union select '1' union select 2 union select 2.0 from user", - "plan": "VT13001: [BUG] index mismatch while pushing the column for '2.0'" + "plan": { + "QueryType": "SELECT", + "Original": "select 1 union select null union select 1.0 union select '1' union select 2 union select 2.0 from user", + "Instructions": { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "0", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "0 ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "0", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "0 ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "0", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "0 ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "0", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "0 ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "0", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "0 ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Reference", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 from dual where 1 != 1", + "Query": "select 1 from dual", + "Table": "dual" + }, + { + "OperatorType": "Route", + "Variant": "Reference", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select null from dual where 1 != 1", + "Query": "select null from dual", + "Table": "dual" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "Reference", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1.0 from dual where 1 != 1", + "Query": "select 1.0 from dual", + "Table": "dual" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "Reference", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select '1' from dual where 1 != 1", + "Query": "select '1' from dual", + "Table": "dual" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "Reference", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 2 from dual where 1 != 1", + "Query": "select 2 from dual", + "Table": "dual" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 2.0 from `user` where 1 != 1", + "Query": "select 2.0 from `user`", + "Table": "`user`" + } + ] + } + ] + } + ] + }, + "TablesUsed": [ + "main.dual", + "user.user" + ] + } }, { "comment": "union distinct between a scatter query and a join (other side)", @@ -783,12 +1053,92 @@ { "comment": "Union in derived table with first SELECT being an UNION", "query": "select * from ((select id from user union select id+1 from user) union select user_id from user_extra) as t", - "plan": "VT13001: [BUG] index mismatch while pushing the column for 'user_id'" + "plan": "VT13001: [BUG] did not expect to add group by here" }, { - "comment": "optimises away ORDER BY when it's safe to do", + "comment": "gen4 optimises away ORDER BY when it's safe to do", "query": "(select id from user union select id from music order by id) union select 1 from unsharded", - "plan": "VT13001: [BUG] index mismatch while pushing the column for '1'" + "plan": { + "QueryType": "SELECT", + "Original": "(select id from user union select id from music order by id) union select 1 from unsharded", + "Instructions": { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|1)", + "ResultColumns": 1, + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|1) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|1)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|1) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "Query": "select id, weight_string(id) from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from music where 1 != 1", + "Query": "select id, weight_string(id) from music", + "Table": "music" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1, weight_string(1) from unsharded where 1 != 1", + "Query": "select 1, weight_string(1) from unsharded", + "Table": "unsharded" + } + ] + } + ] + } + ] + }, + "TablesUsed": [ + "main.unsharded", + "user.music", + "user.user" + ] + } }, { "comment": "push down the ::upper_limit to the sources, since we are doing DISTINCT on them, it's safe", @@ -873,9 +1223,119 @@ } }, { - "comment": "UNION that needs to be reordered to be merged more aggressively - able to get it down to 2 routes", + "comment": "UNION that needs to be reordered to be merged more aggressively. Gen4 is able to get it down to 2 routes", "query": "select col from unsharded union select id from user union select col2 from unsharded union select col from user_extra", - "plan": "VT13001: [BUG] index mismatch while pushing the column for 'col'" + "plan": { + "QueryType": "SELECT", + "Original": "select col from unsharded union select id from user union select col2 from unsharded union select col from user_extra", + "Instructions": { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|1)", + "ResultColumns": 1, + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|1) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|1)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|1) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "GroupBy": "(0|1)", + "Inputs": [ + { + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|1) ASC", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select col, weight_string(col) from unsharded where 1 != 1", + "Query": "select col, weight_string(col) from unsharded", + "Table": "unsharded" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "Query": "select id, weight_string(id) from `user`", + "Table": "`user`" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select col2, weight_string(col2) from unsharded where 1 != 1", + "Query": "select col2, weight_string(col2) from unsharded", + "Table": "unsharded" + } + ] + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select col, weight_string(col) from user_extra where 1 != 1", + "Query": "select col, weight_string(col) from user_extra", + "Table": "user_extra" + } + ] + } + ] + } + ] + }, + "TablesUsed": [ + "main.unsharded", + "user.user", + "user.user_extra" + ] + } }, { "comment": "derived table with union", From 21793424dd24b8b28030009f5f5db8cbd152e2d5 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 7 Jul 2023 11:53:03 +0200 Subject: [PATCH 05/44] Make UNION compact more efficient In order to achieve this, I changed how we handle UNION [DISTINCT]. Distinct is now a field until the first pass of pushing down and compacting has had a chance to run. After this, the distinct:ification is extracted from the UNION op into a separate DISTINCT op. Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/operators/ast2op.go | 2 +- .../operators/horizon_expanding.go | 11 +- .../planbuilder/operators/offset_planning.go | 17 + .../vtgate/planbuilder/operators/operator.go | 8 + go/vt/vtgate/planbuilder/operators/phases.go | 7 + .../planbuilder/operators/queryprojection.go | 3 + go/vt/vtgate/planbuilder/operators/union.go | 9 +- .../testdata/large_union_cases.json | 3133 +++++------------ .../planbuilder/testdata/union_cases.json | 345 +- 9 files changed, 1115 insertions(+), 2420 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/ast2op.go b/go/vt/vtgate/planbuilder/operators/ast2op.go index 916e71c650d..2194625520c 100644 --- a/go/vt/vtgate/planbuilder/operators/ast2op.go +++ b/go/vt/vtgate/planbuilder/operators/ast2op.go @@ -103,7 +103,7 @@ func createOperatorFromUnion(ctx *plancontext.PlanningContext, node *sqlparser.U lexprs := sqlparser.GetFirstSelect(node.Left).SelectExprs rexprs := sqlparser.GetFirstSelect(node.Right).SelectExprs union := &Union{ - Distinct: node.Distinct, + distinct: node.Distinct, Sources: []ops.Operator{opLHS, opRHS}, Selects: []sqlparser.SelectExprs{lexprs, rexprs}, } diff --git a/go/vt/vtgate/planbuilder/operators/horizon_expanding.go b/go/vt/vtgate/planbuilder/operators/horizon_expanding.go index 3e991641178..ce615e580ed 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_expanding.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_expanding.go @@ -46,13 +46,6 @@ func expandUnionHorizon(ctx *plancontext.PlanningContext, horizon *Horizon, unio return nil, nil, err } - if union.Distinct { - op = &Distinct{ - Source: op, - QP: qp, - } - } - if len(qp.OrderExprs) > 0 { op = &Ordering{ Source: op, @@ -67,7 +60,7 @@ func expandUnionHorizon(ctx *plancontext.PlanningContext, horizon *Horizon, unio } } - return op, rewrite.NewTree("expand horizon into smaller components", op), nil + return op, rewrite.NewTree("expand UNION horizon into smaller components", op), nil } func expandSelectHorizon(ctx *plancontext.PlanningContext, horizon *Horizon, sel *sqlparser.Select) (ops.Operator, *rewrite.ApplyResult, error) { @@ -110,7 +103,7 @@ func expandSelectHorizon(ctx *plancontext.PlanningContext, horizon *Horizon, sel } } - return op, rewrite.NewTree("expand horizon into smaller components", op), nil + return op, rewrite.NewTree("expand SELECT horizon into smaller components", op), nil } func createProjectionFromSelect(ctx *plancontext.PlanningContext, horizon *Horizon) (out ops.Operator, err error) { diff --git a/go/vt/vtgate/planbuilder/operators/offset_planning.go b/go/vt/vtgate/planbuilder/operators/offset_planning.go index f4762404bba..fcd35055b20 100644 --- a/go/vt/vtgate/planbuilder/operators/offset_planning.go +++ b/go/vt/vtgate/planbuilder/operators/offset_planning.go @@ -161,6 +161,23 @@ func addColumnsToInput(ctx *plancontext.PlanningContext, root ops.Operator) (ops return rewrite.TopDown(root, TableID, visitor, stopAtRoute) } +// addColumnsToInput adds columns needed by an operator to its input. +// This happens only when the filter expression can be retrieved as an offset from the underlying mysql. +func pullDistinctFromUNION(root ops.Operator) (ops.Operator, error) { + visitor := func(in ops.Operator, _ semantics.TableSet, isRoot bool) (ops.Operator, *rewrite.ApplyResult, error) { + union, ok := in.(*Union) + if !ok || !union.distinct { + return in, rewrite.SameTree, nil + } + + union.distinct = false + + return &Distinct{Source: union}, rewrite.NewTree("pulled out DISTINCT from union", union), nil + } + + return rewrite.TopDown(root, TableID, visitor, stopAtRoute) +} + func getVisitor( ctx *plancontext.PlanningContext, findCol func(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error), diff --git a/go/vt/vtgate/planbuilder/operators/operator.go b/go/vt/vtgate/planbuilder/operators/operator.go index 9e0b63a4b7d..6e771f6bb97 100644 --- a/go/vt/vtgate/planbuilder/operators/operator.go +++ b/go/vt/vtgate/planbuilder/operators/operator.go @@ -34,10 +34,13 @@ The operators go through a few phases while planning: package operators import ( + "fmt" + "vitess.io/vitess/go/slice" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" + "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/rewrite" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" ) @@ -59,6 +62,11 @@ func PlanQuery(ctx *plancontext.PlanningContext, stmt sqlparser.Statement) (ops. return nil, err } + if rewrite.DebugOperatorTree { + fmt.Println("Initial tree:") + fmt.Println(ops.ToTree(op)) + } + if op, err = compact(ctx, op); err != nil { return nil, err } diff --git a/go/vt/vtgate/planbuilder/operators/phases.go b/go/vt/vtgate/planbuilder/operators/phases.go index 3aaf5dcc7d9..e2e4bb85736 100644 --- a/go/vt/vtgate/planbuilder/operators/phases.go +++ b/go/vt/vtgate/planbuilder/operators/phases.go @@ -38,6 +38,13 @@ func getPhases() []Phase { return []Phase{{ // Initial optimization Name: "initial horizon planning optimization phase", + }, { + Name: "pull distinct from UNION", + // to make it easier to compact UNIONs together, we keep the `distinct` flag in the UNION op until this + // phase. Here we will place a DISTINCT op on top of the UNION, and turn the UNION into a UNION ALL + action: func(ctx *plancontext.PlanningContext, op ops.Operator) (ops.Operator, error) { + return pullDistinctFromUNION(op) + }, }, { // after the initial pushing down of aggregations and filtering, we add columns for the filter ops that // need it their inputs, and then we start splitting the aggregation diff --git a/go/vt/vtgate/planbuilder/operators/queryprojection.go b/go/vt/vtgate/planbuilder/operators/queryprojection.go index 58f447901f7..6e12d306849 100644 --- a/go/vt/vtgate/planbuilder/operators/queryprojection.go +++ b/go/vt/vtgate/planbuilder/operators/queryprojection.go @@ -788,6 +788,9 @@ func (qp *QueryProjection) OldAlignGroupByAndOrderBy(ctx *plancontext.PlanningCo // We are also free to add more ORDER BY columns than the user asked for which we leverage, // so the input is already ordered according to the GROUP BY columns used func (qp *QueryProjection) AlignGroupByAndOrderBy(ctx *plancontext.PlanningContext) bool { + if qp == nil { + return false + } if qp.hasCheckedAlignment { return false } diff --git a/go/vt/vtgate/planbuilder/operators/union.go b/go/vt/vtgate/planbuilder/operators/union.go index 01f3d029d2f..bbb833e8353 100644 --- a/go/vt/vtgate/planbuilder/operators/union.go +++ b/go/vt/vtgate/planbuilder/operators/union.go @@ -31,10 +31,7 @@ import ( type Union struct { Sources []ops.Operator Selects []sqlparser.SelectExprs - Distinct bool - - // TODO this should be removed. For now it's used to fail queries - Ordering []ops.OrderBy + distinct bool offsetPlanned bool } @@ -48,7 +45,7 @@ func (u *Union) Clone(inputs []ops.Operator) ops.Operator { } func (u *Union) GetOrdering() ([]ops.OrderBy, error) { - return u.Ordering, nil + return nil, nil } // Inputs implements the Operator interface @@ -167,7 +164,7 @@ func (u *Union) Compact(*plancontext.PlanningContext) (ops.Operator, *rewrite.Ap for idx, source := range u.Sources { other, ok := source.(*Union) - if ok && (u.Distinct || len(other.Ordering) == 0 && !other.Distinct) { + if ok && (u.distinct || !other.distinct) { newSources = append(newSources, other.Sources...) newSelects = append(newSelects, other.Selects...) merged = true diff --git a/go/vt/vtgate/planbuilder/testdata/large_union_cases.json b/go/vt/vtgate/planbuilder/testdata/large_union_cases.json index 2f2ccf75f55..557301a9a10 100644 --- a/go/vt/vtgate/planbuilder/testdata/large_union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/large_union_cases.json @@ -20,2171 +20,974 @@ "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270698330 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270698330)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270699497 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270699497)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270703806 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270703806)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270707364 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270707364)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270714657 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270714657)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270721330 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270721330)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270812079 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270812079)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271011532 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271011532)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271034164 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271034164)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271034177 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271034177)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271066849 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271066849)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271098740 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271098740)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271355000 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271355000)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271639345 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271639345)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271914117 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271914117)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271924504 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271924504)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1272086055 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272086055)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1272127855 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272127855)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1272191137 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272191137)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1272468271 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272468271)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270637436 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270637436)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270644941 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270644941)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270650576 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270650576)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270652906 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270652906)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270660650 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270660650)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270670201 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270670201)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270698330 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270698330)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270699497 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270699497)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270707364 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270707364)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271365691)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271799956 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271799956)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271914117 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271914117)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270637436 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270637436)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271799956 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271799956)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270637436 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270637436)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271639345 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271639345)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270644941 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270644941)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270649256 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270649256)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270653671 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270653671)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270670201 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270670201)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270717223 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270717223)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270720898 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270720898)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270982590 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270982590)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271346411 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271346411)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271352121 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271352121)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271354908 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271354908)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271365691)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271367516 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271367516)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271472522 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271472522)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271607757 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271607757)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271639345 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271639345)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271821733 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271821733)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271914117 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271914117)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1272068709 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272068709)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1272127855 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272127855)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1272191137 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272191137)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1272244005 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272244005)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1272468271 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272468271)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270982590 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270982590)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271365691)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271607757 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271607757)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1270982590 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270982590)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271365691)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1271607757 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271607757)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content) from music where user_id = 1272244005 order by created_at asc, id asc limit 11", + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270698330 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270698330)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270699497 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270699497)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270703806 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270703806)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270707364 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270707364)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270714657 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270714657)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270721330 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270721330)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270812079 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270812079)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271011532 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271011532)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271034164 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271034164)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271034177 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271034177)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271066849 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271066849)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271098740 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271098740)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271355000 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271355000)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271639345 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271639345)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271914117 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271914117)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271924504 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271924504)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272086055 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272086055)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272127855 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272127855)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272191137 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272191137)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272468271 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272468271)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270637436 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270637436)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270644941 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270644941)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270650576 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270650576)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270652906 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270652906)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270660650 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270660650)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270670201 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270670201)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270698330 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270698330)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270699497 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270699497)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270707364 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270707364)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271365691)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271799956 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271799956)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271914117 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271914117)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270637436 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270637436)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271799956 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271799956)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270637436 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270637436)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271639345 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271639345)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270644941 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270644941)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270649256 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270649256)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270653671 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270653671)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270670201 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270670201)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270717223 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270717223)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270720898 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270720898)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270982590 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270982590)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271346411 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271346411)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271352121 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271352121)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271354908 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271354908)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271365691)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271367516 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271367516)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271472522 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271472522)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271607757 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271607757)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271639345 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271639345)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271821733 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271821733)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271914117 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271914117)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272068709 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272068709)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272127855 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272127855)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272191137 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272191137)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272244005 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272244005)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272468271 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272468271)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270982590 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270982590)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271365691)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271607757 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271607757)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270982590 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270982590)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271365691)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271607757 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271607757)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272244005 order by created_at asc, id asc limit 11", "Table": "music", "Values": [ "INT64(1272244005)" diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 4680bcc969f..be80edc38b0 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -471,45 +471,26 @@ "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|1)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|1) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "Query": "select id, weight_string(id) from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from music where 1 != 1", - "Query": "select id, weight_string(id) from music", - "Table": "music" - } - ] - } - ] - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "Query": "select id, weight_string(id) from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from music where 1 != 1", + "Query": "select id, weight_string(id) from music", + "Table": "music" }, { "OperatorType": "Route", @@ -685,135 +666,59 @@ "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "0", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "0 ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "0", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "0 ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "0", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "0 ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "0", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "0 ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Reference", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 from dual where 1 != 1", - "Query": "select 1 from dual", - "Table": "dual" - }, - { - "OperatorType": "Route", - "Variant": "Reference", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select null from dual where 1 != 1", - "Query": "select null from dual", - "Table": "dual" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "Reference", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1.0 from dual where 1 != 1", - "Query": "select 1.0 from dual", - "Table": "dual" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "Reference", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select '1' from dual where 1 != 1", - "Query": "select '1' from dual", - "Table": "dual" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "Reference", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 2 from dual where 1 != 1", - "Query": "select 2 from dual", - "Table": "dual" - } - ] - } - ] - } - ] + "OperatorType": "Route", + "Variant": "Reference", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 from dual where 1 != 1", + "Query": "select 1 from dual", + "Table": "dual" + }, + { + "OperatorType": "Route", + "Variant": "Reference", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select null from dual where 1 != 1", + "Query": "select null from dual", + "Table": "dual" + }, + { + "OperatorType": "Route", + "Variant": "Reference", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1.0 from dual where 1 != 1", + "Query": "select 1.0 from dual", + "Table": "dual" + }, + { + "OperatorType": "Route", + "Variant": "Reference", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select '1' from dual where 1 != 1", + "Query": "select '1' from dual", + "Table": "dual" + }, + { + "OperatorType": "Route", + "Variant": "Reference", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 2 from dual where 1 != 1", + "Query": "select 2 from dual", + "Table": "dual" }, { "OperatorType": "Route", @@ -1172,7 +1077,7 @@ "Sharded": true }, "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "Query": "select id, weight_string(id) from `user`", + "Query": "select id, weight_string(id) from `user` limit :__upper_limit", "Table": "`user`" }, { @@ -1183,7 +1088,7 @@ "Sharded": false }, "FieldQuery": "select 3, weight_string(3) from dual where 1 != 1", - "Query": "select 3, weight_string(3) from dual", + "Query": "select 3, weight_string(3) from dual limit :__upper_limit", "Table": "dual" } ] @@ -1243,75 +1148,37 @@ "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|1)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|1) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|1)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|1) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select col, weight_string(col) from unsharded where 1 != 1", - "Query": "select col, weight_string(col) from unsharded", - "Table": "unsharded" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "Query": "select id, weight_string(id) from `user`", - "Table": "`user`" - } - ] - } - ] - } - ] - }, - { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select col2, weight_string(col2) from unsharded where 1 != 1", - "Query": "select col2, weight_string(col2) from unsharded", - "Table": "unsharded" - } - ] - } - ] - } - ] + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select col, weight_string(col) from unsharded where 1 != 1", + "Query": "select col, weight_string(col) from unsharded", + "Table": "unsharded" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "Query": "select id, weight_string(id) from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select col2, weight_string(col2) from unsharded where 1 != 1", + "Query": "select col2, weight_string(col2) from unsharded", + "Table": "unsharded" }, { "OperatorType": "Route", From 6ea5eda915a01fc763776439373c83d8ad24c6a3 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 7 Jul 2023 13:30:12 +0200 Subject: [PATCH 06/44] another attempt at offset planning for UNION Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/operators/union.go | 31 +-- .../planbuilder/testdata/union_cases.json | 190 ++++++++++++++++++ 2 files changed, 191 insertions(+), 30 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/union.go b/go/vt/vtgate/planbuilder/operators/union.go index bbb833e8353..bfc72c18d87 100644 --- a/go/vt/vtgate/planbuilder/operators/union.go +++ b/go/vt/vtgate/planbuilder/operators/union.go @@ -185,10 +185,6 @@ func (u *Union) Compact(*plancontext.PlanningContext) (ops.Operator, *rewrite.Ap } func (u *Union) AddColumn(ctx *plancontext.PlanningContext, ae *sqlparser.AliasedExpr, reuseExisting, addToGroupBy bool) (ops.Operator, int, error) { - err := u.planOffsets(ctx) - if err != nil { - return nil, 0, err - } cols, err := u.GetColumns() if err != nil { return nil, 0, err @@ -235,7 +231,7 @@ func (u *Union) AddColumn(ctx *plancontext.PlanningContext, ae *sqlparser.Aliase return nil, 0, err } if this != offset { - panic("uh oh") + return nil, 0, vterrors.VT12001("offsets did not line up for UNION") } u.Sources[i] = newSrc } @@ -255,28 +251,3 @@ func (u *Union) NoLHSTableSet() {} func (u *Union) ShortDescription() string { return "" } - -func (u *Union) planOffsets(ctx *plancontext.PlanningContext) error { - if u.offsetPlanned { - return nil - } - u.offsetPlanned = true - - for idx, source := range u.Sources { - for eIdx, expr := range u.Selects[idx] { - ae, ok := expr.(*sqlparser.AliasedExpr) - if !ok { - return vterrors.VT09015() - } - newOp, offset, err := source.AddColumn(ctx, ae, false, false) - if err != nil { - return err - } - if offset != eIdx { - return vterrors.VT13001(fmt.Sprintf("index mismatch while pushing the column for '%s'", sqlparser.String(ae))) - } - u.Sources[idx] = newOp - } - } - return nil -} diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index be80edc38b0..708cff1617d 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -1454,5 +1454,195 @@ "user.user" ] } + }, + { + "comment": "UNION ALL with repeating column on the LHS", + "query": "select foo, foo, foo from user union all select bar, baz, toto from music", + "v3-plan": { + "QueryType": "SELECT", + "Original": "select foo, foo, foo from user union all select bar, baz, toto from music", + "Instructions": { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select foo, foo, foo from `user` where 1 != 1 union all select bar, baz, toto from music where 1 != 1", + "Query": "select foo, foo, foo from `user` union all select bar, baz, toto from music", + "Table": "`user`" + } + }, + "gen4-plan": { + "QueryType": "SELECT", + "Original": "select foo, foo, foo from user union all select bar, baz, toto from music", + "Instructions": { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select foo, foo, foo from `user` where 1 != 1", + "Query": "select foo, foo, foo from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select bar, baz, toto from music where 1 != 1", + "Query": "select bar, baz, toto from music", + "Table": "music" + } + ] + }, + "TablesUsed": [ + "user.music", + "user.user" + ] + } + }, + { + "comment": "UNION ALL with repeating column on the RHS", + "query": "select bar, baz, toto from music union all select foo, foo, foo from user", + "v3-plan": { + "QueryType": "SELECT", + "Original": "select bar, baz, toto from music union all select foo, foo, foo from user", + "Instructions": { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select bar, baz, toto from music where 1 != 1 union all select foo, foo, foo from `user` where 1 != 1", + "Query": "select bar, baz, toto from music union all select foo, foo, foo from `user`", + "Table": "music" + } + }, + "gen4-plan": { + "QueryType": "SELECT", + "Original": "select bar, baz, toto from music union all select foo, foo, foo from user", + "Instructions": { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select bar, baz, toto from music where 1 != 1", + "Query": "select bar, baz, toto from music", + "Table": "music" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select foo, foo, foo from `user` where 1 != 1", + "Query": "select foo, foo, foo from `user`", + "Table": "`user`" + } + ] + }, + "TablesUsed": [ + "user.music", + "user.user" + ] + } + }, + { + "comment": "UNION with repeating column on the LHS", + "query": "select foo, foo, foo from user union select bar, baz, toto from music", + "v3-plan": { + "QueryType": "SELECT", + "Original": "select foo, foo, foo from user union select bar, baz, toto from music", + "Instructions": { + "OperatorType": "Distinct", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select foo, foo, foo from `user` where 1 != 1", + "Query": "select foo, foo, foo from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select bar, baz, toto from music where 1 != 1", + "Query": "select bar, baz, toto from music", + "Table": "music" + } + ] + } + ] + } + }, + "gen4-plan": "VT13001: [BUG] grouping column on wrong index: want: 1, got: 0" + }, + { + "comment": "UNION with repeating column on the RHS", + "query": "select bar, baz, toto from music union select foo, foo, foo from user", + "v3-plan": { + "QueryType": "SELECT", + "Original": "select bar, baz, toto from music union select foo, foo, foo from user", + "Instructions": { + "OperatorType": "Distinct", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select bar, baz, toto from music where 1 != 1", + "Query": "select bar, baz, toto from music", + "Table": "music" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select foo, foo, foo from `user` where 1 != 1", + "Query": "select foo, foo, foo from `user`", + "Table": "`user`" + } + ] + } + ] + } + }, + "gen4-plan": "VT12001: unsupported: offsets did not line up for UNION" } ] From e0b79bb8814ca0e1a55551fff244a9404f251cb9 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Sat, 8 Jul 2023 07:07:30 +0200 Subject: [PATCH 07/44] wip - start of merging UNION Signed-off-by: Andres Taylor --- .../planbuilder/operators/SQL_builder.go | 34 ++++++++ .../planbuilder/operators/horizon_planning.go | 25 ++++++ .../operators/{merging.go => join_merging.go} | 37 +++++--- .../planbuilder/operators/route_planning.go | 2 +- .../operators/subquery_planning.go | 2 +- go/vt/vtgate/planbuilder/operators/union.go | 3 + .../planbuilder/operators/union_merging.go | 86 +++++++++++++++++++ 7 files changed, 173 insertions(+), 16 deletions(-) rename go/vt/vtgate/planbuilder/operators/{merging.go => join_merging.go} (94%) create mode 100644 go/vt/vtgate/planbuilder/operators/union_merging.go diff --git a/go/vt/vtgate/planbuilder/operators/SQL_builder.go b/go/vt/vtgate/planbuilder/operators/SQL_builder.go index 573f101471c..fad3d408bab 100644 --- a/go/vt/vtgate/planbuilder/operators/SQL_builder.go +++ b/go/vt/vtgate/planbuilder/operators/SQL_builder.go @@ -114,6 +114,14 @@ func (qb *queryBuilder) clearProjections() { sel.SelectExprs = nil } +func (qb *queryBuilder) unionWith(other *queryBuilder, distinct bool) { + qb.sel = &sqlparser.Union{ + Left: qb.sel, + Right: other.sel, + Distinct: distinct, + } +} + func (qb *queryBuilder) joinInnerWith(other *queryBuilder, onCondition sqlparser.Expr) { sel := qb.sel.(*sqlparser.Select) otherSel := other.sel.(*sqlparser.Select) @@ -329,6 +337,8 @@ func buildQuery(op ops.Operator, qb *queryBuilder) error { return buildOrdering(op, qb) case *Aggregator: return buildAggregation(op, qb) + case *Union: + return buildUnion(op, qb) default: return vterrors.VT13001(fmt.Sprintf("do not know how to turn %T into SQL", op)) } @@ -447,6 +457,30 @@ func buildApplyJoin(op *ApplyJoin, qb *queryBuilder) error { return nil } +func buildUnion(op *Union, qb *queryBuilder) error { + // the first input is built first + err := buildQuery(op.Sources[0], qb) + if err != nil { + return err + } + + for i, src := range op.Sources { + if i == 0 { + continue + } + + // now we can go over the remaining inputs and UNION them together + qbOther := &queryBuilder{ctx: qb.ctx} + err = buildQuery(src, qbOther) + if err != nil { + return err + } + qb.unionWith(qbOther, op.distinct) + } + + return nil +} + func buildFilter(op *Filter, qb *queryBuilder) error { err := buildQuery(op.Source, qb) if err != nil { diff --git a/go/vt/vtgate/planbuilder/operators/horizon_planning.go b/go/vt/vtgate/planbuilder/operators/horizon_planning.go index b1d14e1f368..e8612a42984 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_planning.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_planning.go @@ -139,6 +139,8 @@ func optimizeHorizonPlanning(ctx *plancontext.PlanningContext, root ops.Operator return tryPushingDownFilter(ctx, in) case *Distinct: return tryPushingDownDistinct(in) + case *Union: + return tryPushDownUnion(ctx, in) default: return in, rewrite.SameTree, nil } @@ -618,6 +620,29 @@ func tryPushingDownDistinct(in *Distinct) (ops.Operator, *rewrite.ApplyResult, e return aggr, rewrite.NewTree("replace distinct with aggregator", in), nil } +func tryPushDownUnion(ctx *plancontext.PlanningContext, op *Union) (ops.Operator, *rewrite.ApplyResult, error) { + if op.distinct { + sources, selects, err := mergeUnionInputInAnyOrder(ctx, op) + if err != nil { + return nil, nil, err + } + if len(sources) == 1 { + return sources[0], rewrite.NewTree("pushed union under route", op), nil + } + var result *rewrite.ApplyResult + if len(sources) != len(op.Sources) { + result = rewrite.NewTree("merged union inputs", op) + } + return &Union{ + Sources: sources, + Selects: selects, + distinct: true, + }, result, nil + } + + return op, rewrite.SameTree, nil +} + // makeSureOutputIsCorrect uses the original Horizon to make sure that the output columns line up with what the user asked for func makeSureOutputIsCorrect(ctx *plancontext.PlanningContext, oldHorizon ops.Operator, output ops.Operator) (ops.Operator, error) { cols, err := output.GetSelectExprs() diff --git a/go/vt/vtgate/planbuilder/operators/merging.go b/go/vt/vtgate/planbuilder/operators/join_merging.go similarity index 94% rename from go/vt/vtgate/planbuilder/operators/merging.go rename to go/vt/vtgate/planbuilder/operators/join_merging.go index adc2951d8cb..4c4b1c815b4 100644 --- a/go/vt/vtgate/planbuilder/operators/merging.go +++ b/go/vt/vtgate/planbuilder/operators/join_merging.go @@ -25,25 +25,15 @@ import ( "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" ) -// MergeJoin checks whether two operators can be merged into a single one. +// mergeJoinInputs checks whether two operators can be merged into a single one. // If they can be merged, a new operator with the merged routing is returned // If they cannot be merged, nil is returned. -func MergeJoin(ctx *plancontext.PlanningContext, lhs, rhs ops.Operator, joinPredicates []sqlparser.Expr, m merger) (ops.Operator, error) { - lhsRoute, rhsRoute := operatorsToRoutes(lhs, rhs) - if lhsRoute == nil || rhsRoute == nil { +func mergeJoinInputs(ctx *plancontext.PlanningContext, lhs, rhs ops.Operator, joinPredicates []sqlparser.Expr, m merger) (ops.Operator, error) { + lhsRoute, rhsRoute, routingA, routingB, a, b, sameKeyspace := prepareInputRoutes(lhs, rhs) + if lhsRoute == nil { return nil, nil } - lhsRoute, rhsRoute, routingA, routingB, sameKeyspace := getRoutesOrAlternates(lhsRoute, rhsRoute) - - a, b := getRoutingType(routingA), getRoutingType(routingB) - if getTypeName(routingA) < getTypeName(routingB) { - // while deciding if two routes can be merged, the LHS/RHS order of the routes is not important. - // for the actual merging, we still need to remember which side was inner and which was outer for subqueries - a, b = b, a - routingA, routingB = routingB, routingA - } - switch { // if either side is a dual query, we can always merge them together case a == dual: @@ -76,6 +66,25 @@ func MergeJoin(ctx *plancontext.PlanningContext, lhs, rhs ops.Operator, joinPred } } +func prepareInputRoutes(lhs ops.Operator, rhs ops.Operator) (*Route, *Route, Routing, Routing, routingType, routingType, bool) { + lhsRoute, rhsRoute := operatorsToRoutes(lhs, rhs) + if lhsRoute == nil || rhsRoute == nil { + return nil, nil, nil, nil, 0, 0, false + } + + lhsRoute, rhsRoute, routingA, routingB, sameKeyspace := getRoutesOrAlternates(lhsRoute, rhsRoute) + + a, b := getRoutingType(routingA), getRoutingType(routingB) + if getTypeName(routingA) < getTypeName(routingB) { + // while deciding if two routes can be merged, the LHS/RHS order of the routes is not important. + // for the actual merging, we still need to remember which side was inner and which was outer for subqueries + a, b = b, a + routingA, routingB = routingB, routingA + } + + return lhsRoute, rhsRoute, routingA, routingB, a, b, sameKeyspace +} + type ( merger interface { mergeShardedRouting(r1, r2 *ShardedRouting, op1, op2 *Route) (*Route, error) diff --git a/go/vt/vtgate/planbuilder/operators/route_planning.go b/go/vt/vtgate/planbuilder/operators/route_planning.go index afde39f366d..fa8a12d97ac 100644 --- a/go/vt/vtgate/planbuilder/operators/route_planning.go +++ b/go/vt/vtgate/planbuilder/operators/route_planning.go @@ -404,7 +404,7 @@ func requiresSwitchingSides(ctx *plancontext.PlanningContext, op ops.Operator) b } func mergeOrJoin(ctx *plancontext.PlanningContext, lhs, rhs ops.Operator, joinPredicates []sqlparser.Expr, inner bool) (ops.Operator, *rewrite.ApplyResult, error) { - newPlan, err := MergeJoin(ctx, lhs, rhs, joinPredicates, newJoinMerge(ctx, joinPredicates, inner)) + newPlan, err := mergeJoinInputs(ctx, lhs, rhs, joinPredicates, newJoinMerge(ctx, joinPredicates, inner)) if err != nil { return nil, nil, err } diff --git a/go/vt/vtgate/planbuilder/operators/subquery_planning.go b/go/vt/vtgate/planbuilder/operators/subquery_planning.go index 06437005611..86c7e29efb8 100644 --- a/go/vt/vtgate/planbuilder/operators/subquery_planning.go +++ b/go/vt/vtgate/planbuilder/operators/subquery_planning.go @@ -183,7 +183,7 @@ func tryMergeSubqueryWithRoute( return nil, nil } - merged, err := MergeJoin(ctx, outerOp, subq, joinPredicates, merger) + merged, err := mergeJoinInputs(ctx, outerOp, subq, joinPredicates, merger) if err != nil { return nil, err } diff --git a/go/vt/vtgate/planbuilder/operators/union.go b/go/vt/vtgate/planbuilder/operators/union.go index bfc72c18d87..4e154f602e1 100644 --- a/go/vt/vtgate/planbuilder/operators/union.go +++ b/go/vt/vtgate/planbuilder/operators/union.go @@ -249,5 +249,8 @@ func (u *Union) GetSelectExprs() (sqlparser.SelectExprs, error) { func (u *Union) NoLHSTableSet() {} func (u *Union) ShortDescription() string { + if u.distinct { + return "DISTINCT" + } return "" } diff --git a/go/vt/vtgate/planbuilder/operators/union_merging.go b/go/vt/vtgate/planbuilder/operators/union_merging.go new file mode 100644 index 00000000000..36ef44f09dd --- /dev/null +++ b/go/vt/vtgate/planbuilder/operators/union_merging.go @@ -0,0 +1,86 @@ +package operators + +import ( + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" + "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" +) + +// mergeUnionInputInAnyOrder merges sources the sources of the union in any order +// can be used for UNION DISTINCT +func mergeUnionInputInAnyOrder(ctx *plancontext.PlanningContext, op *Union) ([]ops.Operator, []sqlparser.SelectExprs, error) { + sources := op.Sources + + // next we'll go over all the plans from and check if any two can be merged. if they can, they are merged, + // and we continue checking for pairs of plans that can be merged into a single route + idx := 0 + for idx < len(sources) { + keep := make([]bool, len(sources)) + srcA := sources[idx] + merged := false + for j, srcB := range sources { + if j <= idx { + continue + } + newPlan, err := mergeUnionInputs(ctx, srcA, srcB, nil, nil, op.distinct) + if err != nil { + return nil, nil, err + } + if newPlan != nil { + sources[idx] = newPlan + srcA = newPlan + merged = true + } else { + keep[j] = true + } + } + if !merged { + return sources, nil, nil + } + + var phase []ops.Operator + for i, source := range sources { + if keep[i] || i <= idx { + phase = append(phase, source) + } + } + idx++ + sources = phase + } + + return sources, nil, nil +} + +// mergeUnionInputs checks whether two operators can be merged into a single one. +// If they can be merged, a new operator with the merged routing is returned +// If they cannot be merged, nil is returned. +// this function is very similar to mergeJoinInputs +func mergeUnionInputs(ctx *plancontext.PlanningContext, lhs, rhs ops.Operator, lhsExprs, rhsExprs sqlparser.SelectExprs, distinct bool) (ops.Operator, error) { + lhsRoute, rhsRoute, routingA, _, _, b, _ := prepareInputRoutes(lhs, rhs) + if lhsRoute == nil { + return nil, nil + } + + switch { + // if either side is a dual query, we can always merge them together + case b == dual: + //rhsRoute.Source = &Union{ + // Sources: []ops.Operator{lhsRoute.Source, rhsRoute.Source}, + // Selects: []sqlparser.SelectExprs{lhsExprs, rhsExprs}, + // distinct: false, + //} + //rhsRoute.MergedWith = append(rhsRoute.MergedWith, lhsRoute) + //return rhsRoute, nil + return &Route{ + Source: &Union{ + Sources: []ops.Operator{lhsRoute.Source, rhsRoute.Source}, + Selects: []sqlparser.SelectExprs{lhsExprs, rhsExprs}, + distinct: distinct, + }, + MergedWith: []*Route{rhsRoute}, + Routing: routingA, + }, nil + default: + return nil, nil + } +} From 78c7422d042ae719f378080f480b53f00772ad84 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Wed, 12 Jul 2023 14:13:11 +0200 Subject: [PATCH 08/44] wip - continue with merging of UNION Signed-off-by: Andres Taylor --- .../planbuilder/operator_transformers.go | 6 +- .../planbuilder/operators/SQL_builder.go | 24 +- .../planbuilder/operators/aggregator.go | 8 +- .../planbuilder/operators/apply_join.go | 6 +- .../vtgate/planbuilder/operators/distinct.go | 10 +- go/vt/vtgate/planbuilder/operators/filter.go | 8 +- go/vt/vtgate/planbuilder/operators/horizon.go | 4 +- .../planbuilder/operators/horizon_planning.go | 53 +- go/vt/vtgate/planbuilder/operators/limit.go | 8 +- .../planbuilder/operators/offset_planning.go | 4 +- .../vtgate/planbuilder/operators/operator.go | 8 +- go/vt/vtgate/planbuilder/operators/ops/op.go | 5 +- .../vtgate/planbuilder/operators/ordering.go | 8 +- .../planbuilder/operators/projection.go | 12 +- .../planbuilder/operators/queryprojection.go | 3 + go/vt/vtgate/planbuilder/operators/route.go | 89 +- go/vt/vtgate/planbuilder/operators/table.go | 6 +- go/vt/vtgate/planbuilder/operators/union.go | 83 +- .../planbuilder/operators/union_merging.go | 53 +- go/vt/vtgate/planbuilder/operators/vindex.go | 6 +- .../planbuilder/testdata/aggr_cases.json | 162 +- .../ddl_cases_no_default_keyspace.json | 2 +- .../planbuilder/testdata/from_cases.json | 3 +- .../testdata/info_schema57_cases.json | 215 ++- .../testdata/info_schema80_cases.json | 215 ++- .../testdata/large_union_cases.json | 1003 +----------- .../testdata/memory_sort_cases.json | 23 +- .../planbuilder/testdata/oltp_cases.json | 33 +- .../testdata/postprocess_cases.json | 88 +- .../planbuilder/testdata/select_cases.json | 11 +- .../planbuilder/testdata/union_cases.json | 1347 +++++------------ 31 files changed, 1108 insertions(+), 2398 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index 9b8d2086a2d..df40770daf3 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -160,7 +160,7 @@ func transformProjection(ctx *plancontext.PlanningContext, op *operators.Project if cols := op.AllOffsets(); cols != nil { // if all this op is doing is passing through columns from the input, we // can use the faster SimpleProjection - return useSimpleProjection(op, cols, src) + return useSimpleProjection(ctx, op, cols, src) } expressions := slice.Map(op.Projections, func(from operators.ProjExpr) sqlparser.Expr { @@ -202,8 +202,8 @@ func transformProjection(ctx *plancontext.PlanningContext, op *operators.Project // useSimpleProjection uses nothing at all if the output is already correct, // or SimpleProjection when we have to reorder or truncate the columns -func useSimpleProjection(op *operators.Projection, cols []int, src logicalPlan) (logicalPlan, error) { - columns, err := op.Source.GetColumns() +func useSimpleProjection(ctx *plancontext.PlanningContext, op *operators.Projection, cols []int, src logicalPlan) (logicalPlan, error) { + columns, err := op.Source.GetColumns(ctx) if err != nil { return nil, err } diff --git a/go/vt/vtgate/planbuilder/operators/SQL_builder.go b/go/vt/vtgate/planbuilder/operators/SQL_builder.go index fad3d408bab..4226695bd1f 100644 --- a/go/vt/vtgate/planbuilder/operators/SQL_builder.go +++ b/go/vt/vtgate/planbuilder/operators/SQL_builder.go @@ -110,7 +110,10 @@ func (qb *queryBuilder) addProjection(projection *sqlparser.AliasedExpr) { } func (qb *queryBuilder) clearProjections() { - sel := qb.sel.(*sqlparser.Select) + sel, isSel := qb.sel.(*sqlparser.Select) + if !isSel { + return + } sel.SelectExprs = nil } @@ -353,7 +356,7 @@ func buildAggregation(op *Aggregator, qb *queryBuilder) error { qb.clearProjections() - cols, err := op.GetColumns() + cols, err := op.GetColumns(qb.ctx) if err != nil { return err } @@ -414,22 +417,31 @@ func buildProjection(op *Projection, qb *queryBuilder) error { return err } - qb.clearProjections() + _, isSel := qb.sel.(*sqlparser.Select) + if isSel { + qb.clearProjections() - for _, column := range op.Columns { - qb.addProjection(column) + for _, column := range op.Columns { + qb.addProjection(column) + } } // if the projection is on derived table, we use the select we have // created above and transform it into a derived table if op.TableID != nil { - sel := qb.sel.(*sqlparser.Select) + sel := qb.sel qb.sel = nil qb.addTableExpr(op.Alias, op.Alias, TableID(op), &sqlparser.DerivedTable{ Select: sel, }, nil, nil) } + if !isSel { + for _, column := range op.Columns { + qb.addProjection(column) + } + } + return nil } diff --git a/go/vt/vtgate/planbuilder/operators/aggregator.go b/go/vt/vtgate/planbuilder/operators/aggregator.go index 66a38a06b59..bc60daf3df5 100644 --- a/go/vt/vtgate/planbuilder/operators/aggregator.go +++ b/go/vt/vtgate/planbuilder/operators/aggregator.go @@ -205,7 +205,7 @@ func (a *Aggregator) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser return a, offset, nil } -func (a *Aggregator) GetColumns() ([]*sqlparser.AliasedExpr, error) { +func (a *Aggregator) GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { if _, isSourceDerived := a.Source.(*Horizon); isSourceDerived { return a.Columns, nil } @@ -213,7 +213,7 @@ func (a *Aggregator) GetColumns() ([]*sqlparser.AliasedExpr, error) { // we update the incoming columns, so we know about any new columns that have been added // in the optimization phase, other operators could be pushed down resulting in additional columns for aggregator. // Aggregator should be made aware of these to truncate them in final result. - columns, err := a.Source.GetColumns() + columns, err := a.Source.GetColumns(ctx) if err != nil { return nil, err } @@ -226,8 +226,8 @@ func (a *Aggregator) GetColumns() ([]*sqlparser.AliasedExpr, error) { return a.Columns, nil } -func (a *Aggregator) GetSelectExprs() (sqlparser.SelectExprs, error) { - return transformColumnsToSelectExprs(a) +func (a *Aggregator) GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.SelectExprs, error) { + return transformColumnsToSelectExprs(ctx, a) } func (a *Aggregator) ShortDescription() string { diff --git a/go/vt/vtgate/planbuilder/operators/apply_join.go b/go/vt/vtgate/planbuilder/operators/apply_join.go index d98780e6296..2e4106524d3 100644 --- a/go/vt/vtgate/planbuilder/operators/apply_join.go +++ b/go/vt/vtgate/planbuilder/operators/apply_join.go @@ -180,12 +180,12 @@ func (a *ApplyJoin) pushColRight(ctx *plancontext.PlanningContext, e *sqlparser. return offset, nil } -func (a *ApplyJoin) GetColumns() ([]*sqlparser.AliasedExpr, error) { +func (a *ApplyJoin) GetColumns(*plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { return slice.Map(a.ColumnsAST, joinColumnToAliasedExpr), nil } -func (a *ApplyJoin) GetSelectExprs() (sqlparser.SelectExprs, error) { - return transformColumnsToSelectExprs(a) +func (a *ApplyJoin) GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.SelectExprs, error) { + return transformColumnsToSelectExprs(ctx, a) } func (a *ApplyJoin) GetOrdering() ([]ops.OrderBy, error) { diff --git a/go/vt/vtgate/planbuilder/operators/distinct.go b/go/vt/vtgate/planbuilder/operators/distinct.go index ae54672c353..b3a20afb0ea 100644 --- a/go/vt/vtgate/planbuilder/operators/distinct.go +++ b/go/vt/vtgate/planbuilder/operators/distinct.go @@ -39,7 +39,7 @@ type ( ) func (d *Distinct) planOffsets(ctx *plancontext.PlanningContext) error { - columns, err := d.GetColumns() + columns, err := d.GetColumns(ctx) if err != nil { return err } @@ -110,12 +110,12 @@ func (d *Distinct) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.A return d, offset, nil } -func (d *Distinct) GetColumns() ([]*sqlparser.AliasedExpr, error) { - return d.Source.GetColumns() +func (d *Distinct) GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { + return d.Source.GetColumns(ctx) } -func (d *Distinct) GetSelectExprs() (sqlparser.SelectExprs, error) { - return d.Source.GetSelectExprs() +func (d *Distinct) GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.SelectExprs, error) { + return d.Source.GetSelectExprs(ctx) } func (d *Distinct) ShortDescription() string { diff --git a/go/vt/vtgate/planbuilder/operators/filter.go b/go/vt/vtgate/planbuilder/operators/filter.go index 1c0751f47ad..11678dd171b 100644 --- a/go/vt/vtgate/planbuilder/operators/filter.go +++ b/go/vt/vtgate/planbuilder/operators/filter.go @@ -96,12 +96,12 @@ func (f *Filter) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.Ali return f, offset, nil } -func (f *Filter) GetColumns() ([]*sqlparser.AliasedExpr, error) { - return f.Source.GetColumns() +func (f *Filter) GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { + return f.Source.GetColumns(ctx) } -func (f *Filter) GetSelectExprs() (sqlparser.SelectExprs, error) { - return f.Source.GetSelectExprs() +func (f *Filter) GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.SelectExprs, error) { + return f.Source.GetSelectExprs(ctx) } func (f *Filter) GetOrdering() ([]ops.OrderBy, error) { diff --git a/go/vt/vtgate/planbuilder/operators/horizon.go b/go/vt/vtgate/planbuilder/operators/horizon.go index d95e3244cff..28a99d7c847 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon.go +++ b/go/vt/vtgate/planbuilder/operators/horizon.go @@ -196,7 +196,7 @@ func canReuseColumn[T any]( return } -func (h *Horizon) GetColumns() (exprs []*sqlparser.AliasedExpr, err error) { +func (h *Horizon) GetColumns(*plancontext.PlanningContext) (exprs []*sqlparser.AliasedExpr, err error) { for _, expr := range sqlparser.GetFirstSelect(h.Query).SelectExprs { ae, ok := expr.(*sqlparser.AliasedExpr) if !ok { @@ -207,7 +207,7 @@ func (h *Horizon) GetColumns() (exprs []*sqlparser.AliasedExpr, err error) { return } -func (h *Horizon) GetSelectExprs() (sqlparser.SelectExprs, error) { +func (h *Horizon) GetSelectExprs(*plancontext.PlanningContext) (sqlparser.SelectExprs, error) { return sqlparser.GetFirstSelect(h.Query).SelectExprs, nil } diff --git a/go/vt/vtgate/planbuilder/operators/horizon_planning.go b/go/vt/vtgate/planbuilder/operators/horizon_planning.go index e8612a42984..8083e055a4c 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_planning.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_planning.go @@ -138,7 +138,7 @@ func optimizeHorizonPlanning(ctx *plancontext.PlanningContext, root ops.Operator case *Filter: return tryPushingDownFilter(ctx, in) case *Distinct: - return tryPushingDownDistinct(in) + return tryPushingDownDistinct(ctx, in) case *Union: return tryPushDownUnion(ctx, in) default: @@ -255,12 +255,12 @@ func pushDownProjectionInApplyJoin( var err error // Create and update the Projection operators for the left and right children, if needed. - src.LHS, err = createProjectionWithTheseColumns(src.LHS, lhs, p.TableID, p.Alias) + src.LHS, err = createProjectionWithTheseColumns(ctx, src.LHS, lhs, p.TableID, p.Alias) if err != nil { return nil, nil, err } - src.RHS, err = createProjectionWithTheseColumns(src.RHS, rhs, p.TableID, p.Alias) + src.RHS, err = createProjectionWithTheseColumns(ctx, src.RHS, rhs, p.TableID, p.Alias) if err != nil { return nil, nil, err } @@ -369,6 +369,7 @@ func prefixColNames(tblName sqlparser.TableName, e sqlparser.Expr) (out sqlparse } func createProjectionWithTheseColumns( + ctx *plancontext.PlanningContext, src ops.Operator, p *projector, tableID *semantics.TableSet, @@ -377,7 +378,7 @@ func createProjectionWithTheseColumns( if len(p.cols) == 0 { return src, nil } - proj, err := createProjection(src) + proj, err := createProjection(ctx, src) if err != nil { return nil, err } @@ -587,7 +588,7 @@ func pushFilterUnderProjection(ctx *plancontext.PlanningContext, filter *Filter, } -func tryPushingDownDistinct(in *Distinct) (ops.Operator, *rewrite.ApplyResult, error) { +func tryPushingDownDistinct(ctx *plancontext.PlanningContext, in *Distinct) (ops.Operator, *rewrite.ApplyResult, error) { if in.Pushed { return in, rewrite.SameTree, nil } @@ -602,22 +603,27 @@ func tryPushingDownDistinct(in *Distinct) (ops.Operator, *rewrite.ApplyResult, e return in, rewrite.SameTree, nil } - cols, err := in.Source.GetColumns() - if err != nil { - return nil, nil, err - } - - aggr := &Aggregator{ - Source: in.Source, - QP: in.QP, - Original: true, - } + // TODO: tell the inputs from here we only need distinct inputs + in.Pushed = true - for _, col := range cols { - aggr.addColumnWithoutPushing(col, true) - } + return in, rewrite.SameTree, nil - return aggr, rewrite.NewTree("replace distinct with aggregator", in), nil + //cols, err := in.Source.GetColumns(ctx) + //if err != nil { + // return nil, nil, err + //} + // + //aggr := &Aggregator{ + // Source: in.Source, + // QP: in.QP, + // Original: true, + //} + // + //for _, col := range cols { + // aggr.addColumnWithoutPushing(col, true) + //} + // + //return aggr, rewrite.NewTree("replace distinct with aggregator", in), nil } func tryPushDownUnion(ctx *plancontext.PlanningContext, op *Union) (ops.Operator, *rewrite.ApplyResult, error) { @@ -627,7 +633,12 @@ func tryPushDownUnion(ctx *plancontext.PlanningContext, op *Union) (ops.Operator return nil, nil, err } if len(sources) == 1 { - return sources[0], rewrite.NewTree("pushed union under route", op), nil + result := sources[0] + if op.distinct { + result = &Distinct{Source: result} + } + + return result, rewrite.NewTree("pushed union under route", op), nil } var result *rewrite.ApplyResult if len(sources) != len(op.Sources) { @@ -645,7 +656,7 @@ func tryPushDownUnion(ctx *plancontext.PlanningContext, op *Union) (ops.Operator // makeSureOutputIsCorrect uses the original Horizon to make sure that the output columns line up with what the user asked for func makeSureOutputIsCorrect(ctx *plancontext.PlanningContext, oldHorizon ops.Operator, output ops.Operator) (ops.Operator, error) { - cols, err := output.GetSelectExprs() + cols, err := output.GetSelectExprs(ctx) if err != nil { return nil, err } diff --git a/go/vt/vtgate/planbuilder/operators/limit.go b/go/vt/vtgate/planbuilder/operators/limit.go index 24f6af9ec7c..27ff0f933cc 100644 --- a/go/vt/vtgate/planbuilder/operators/limit.go +++ b/go/vt/vtgate/planbuilder/operators/limit.go @@ -65,12 +65,12 @@ func (l *Limit) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.Alia return l, offset, nil } -func (l *Limit) GetColumns() ([]*sqlparser.AliasedExpr, error) { - return l.Source.GetColumns() +func (l *Limit) GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { + return l.Source.GetColumns(ctx) } -func (l *Limit) GetSelectExprs() (sqlparser.SelectExprs, error) { - return l.Source.GetSelectExprs() +func (l *Limit) GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.SelectExprs, error) { + return l.Source.GetSelectExprs(ctx) } func (l *Limit) GetOrdering() ([]ops.OrderBy, error) { diff --git a/go/vt/vtgate/planbuilder/operators/offset_planning.go b/go/vt/vtgate/planbuilder/operators/offset_planning.go index fcd35055b20..e7477f94aac 100644 --- a/go/vt/vtgate/planbuilder/operators/offset_planning.go +++ b/go/vt/vtgate/planbuilder/operators/offset_planning.go @@ -75,7 +75,7 @@ func planOffsetsOnJoins(ctx *plancontext.PlanningContext, op ops.Operator) error // useOffsets rewrites an expression to use values from the input func useOffsets(ctx *plancontext.PlanningContext, expr sqlparser.Expr, op ops.Operator) (sqlparser.Expr, error) { in := op.Inputs()[0] - columns, err := in.GetColumns() + columns, err := in.GetColumns(ctx) if err != nil { return nil, err } @@ -92,7 +92,7 @@ func useOffsets(ctx *plancontext.PlanningContext, expr sqlparser.Expr, op ops.Op return err } op.SetInputs([]ops.Operator{in}) - columns, err = in.GetColumns() + columns, err = in.GetColumns(ctx) if err != nil { return err } diff --git a/go/vt/vtgate/planbuilder/operators/operator.go b/go/vt/vtgate/planbuilder/operators/operator.go index 6e771f6bb97..9ae3f232ad3 100644 --- a/go/vt/vtgate/planbuilder/operators/operator.go +++ b/go/vt/vtgate/planbuilder/operators/operator.go @@ -109,11 +109,11 @@ func (noColumns) AddColumn(*plancontext.PlanningContext, *sqlparser.AliasedExpr, return nil, 0, vterrors.VT13001("noColumns operators have no column") } -func (noColumns) GetColumns() ([]*sqlparser.AliasedExpr, error) { +func (noColumns) GetColumns(*plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { return nil, vterrors.VT13001("noColumns operators have no column") } -func (noColumns) GetSelectExprs() (sqlparser.SelectExprs, error) { +func (noColumns) GetSelectExprs(*plancontext.PlanningContext) (sqlparser.SelectExprs, error) { return nil, vterrors.VT13001("noColumns operators have no column") } @@ -149,8 +149,8 @@ func tryTruncateColumnsAt(op ops.Operator, truncateAt int) bool { return tryTruncateColumnsAt(inputs[0], truncateAt) } -func transformColumnsToSelectExprs(op ops.Operator) (sqlparser.SelectExprs, error) { - columns, err := op.GetColumns() +func transformColumnsToSelectExprs(ctx *plancontext.PlanningContext, op ops.Operator) (sqlparser.SelectExprs, error) { + columns, err := op.GetColumns(ctx) if err != nil { return nil, err } diff --git a/go/vt/vtgate/planbuilder/operators/ops/op.go b/go/vt/vtgate/planbuilder/operators/ops/op.go index a0a350633a2..baf95f93cd0 100644 --- a/go/vt/vtgate/planbuilder/operators/ops/op.go +++ b/go/vt/vtgate/planbuilder/operators/ops/op.go @@ -47,9 +47,8 @@ type ( // The offset to the column is returned. AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, reuseExisting, addToGroupBy bool) (Operator, int, error) - GetColumns() ([]*sqlparser.AliasedExpr, error) - - GetSelectExprs() (sqlparser.SelectExprs, error) + GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) + GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.SelectExprs, error) ShortDescription() string diff --git a/go/vt/vtgate/planbuilder/operators/ordering.go b/go/vt/vtgate/planbuilder/operators/ordering.go index 14dec07c193..d47cbcafeca 100644 --- a/go/vt/vtgate/planbuilder/operators/ordering.go +++ b/go/vt/vtgate/planbuilder/operators/ordering.go @@ -73,12 +73,12 @@ func (o *Ordering) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.A return o, offset, nil } -func (o *Ordering) GetColumns() ([]*sqlparser.AliasedExpr, error) { - return o.Source.GetColumns() +func (o *Ordering) GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { + return o.Source.GetColumns(ctx) } -func (o *Ordering) GetSelectExprs() (sqlparser.SelectExprs, error) { - return o.Source.GetSelectExprs() +func (o *Ordering) GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.SelectExprs, error) { + return o.Source.GetSelectExprs(ctx) } func (o *Ordering) GetOrdering() ([]ops.OrderBy, error) { diff --git a/go/vt/vtgate/planbuilder/operators/projection.go b/go/vt/vtgate/planbuilder/operators/projection.go index f99b6456670..d4a84f0bce3 100644 --- a/go/vt/vtgate/planbuilder/operators/projection.go +++ b/go/vt/vtgate/planbuilder/operators/projection.go @@ -182,15 +182,15 @@ func (p *Projection) AddPredicate(ctx *plancontext.PlanningContext, expr sqlpars return p, nil } -func (p *Projection) GetColumns() ([]*sqlparser.AliasedExpr, error) { +func (p *Projection) GetColumns(*plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { if p.TableID != nil { return nil, nil } return p.Columns, nil } -func (p *Projection) GetSelectExprs() (sqlparser.SelectExprs, error) { - return transformColumnsToSelectExprs(p) +func (p *Projection) GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.SelectExprs, error) { + return transformColumnsToSelectExprs(ctx, p) } func (p *Projection) GetOrdering() ([]ops.OrderBy, error) { @@ -230,7 +230,7 @@ func (p *Projection) ShortDescription() string { func (p *Projection) Compact(ctx *plancontext.PlanningContext) (ops.Operator, *rewrite.ApplyResult, error) { switch src := p.Source.(type) { case *Route: - return p.compactWithRoute(src) + return p.compactWithRoute(ctx, src) case *ApplyJoin: return p.compactWithJoin(ctx, src) } @@ -269,14 +269,14 @@ func (p *Projection) compactWithJoin(ctx *plancontext.PlanningContext, src *Appl return src, rewrite.NewTree("remove projection from before join", src), nil } -func (p *Projection) compactWithRoute(rb *Route) (ops.Operator, *rewrite.ApplyResult, error) { +func (p *Projection) compactWithRoute(ctx *plancontext.PlanningContext, rb *Route) (ops.Operator, *rewrite.ApplyResult, error) { for i, col := range p.Projections { offset, ok := col.(Offset) if !ok || offset.Offset != i { return p, rewrite.SameTree, nil } } - columns, err := rb.GetColumns() + columns, err := rb.GetColumns(ctx) if err != nil { return nil, nil, err } diff --git a/go/vt/vtgate/planbuilder/operators/queryprojection.go b/go/vt/vtgate/planbuilder/operators/queryprojection.go index 6e12d306849..a5d83057453 100644 --- a/go/vt/vtgate/planbuilder/operators/queryprojection.go +++ b/go/vt/vtgate/planbuilder/operators/queryprojection.go @@ -453,6 +453,9 @@ func (qp *QueryProjection) isExprInGroupByExprs(ctx *plancontext.PlanningContext // GetSimplifiedExpr takes an expression used in ORDER BY or GROUP BY, and returns an expression that is simpler to evaluate func (qp *QueryProjection) GetSimplifiedExpr(e sqlparser.Expr) sqlparser.Expr { + if qp == nil { + return e + } // If the ORDER BY is against a column alias, we need to remember the expression // behind the alias. The weightstring(.) calls needs to be done against that expression and not the alias. // Eg - select music.foo as bar, weightstring(music.foo) from music order by bar diff --git a/go/vt/vtgate/planbuilder/operators/route.go b/go/vt/vtgate/planbuilder/operators/route.go index b73fa51a510..9383d8bdbd8 100644 --- a/go/vt/vtgate/planbuilder/operators/route.go +++ b/go/vt/vtgate/planbuilder/operators/route.go @@ -531,9 +531,9 @@ func (r *Route) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Ex return r, err } -func createProjection(src ops.Operator) (*Projection, error) { +func createProjection(ctx *plancontext.PlanningContext, src ops.Operator) (*Projection, error) { proj := &Projection{Source: src} - cols, err := src.GetColumns() + cols, err := src.GetColumns(ctx) if err != nil { return nil, err } @@ -548,7 +548,7 @@ func (r *Route) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.Alia if reuseExisting { // check if columns is already added. - cols, err := r.GetColumns() + cols, err := r.GetColumns(ctx) if err != nil { return nil, 0, err } @@ -561,12 +561,13 @@ func (r *Route) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.Alia } // if column is not already present, we check if we can easily find a projection // or aggregation in our source that we can add to - if ok, offset := addColumnToInput(r.Source, expr, addToGroupBy); ok { + if op, ok, offset := addColumnToInput(ctx, r.Source, expr, addToGroupBy); ok { + r.Source = op return r, offset, nil } // If no-one could be found, we probably don't have one yet, so we add one here - src, err := createProjection(r.Source) + src, err := createProjection(ctx, r.Source) if err != nil { return nil, 0, err } @@ -587,33 +588,87 @@ type selectExpressions interface { findCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) } -func addColumnToInput(operator ops.Operator, expr *sqlparser.AliasedExpr, addToGroupBy bool) (bool, int) { +// addColumnToInput adds a column to an operator without pushing it down. +// It will return a bool indicating whether the addition was succesful or not, and an offset to where the column can be found +func addColumnToInput(ctx *plancontext.PlanningContext, operator ops.Operator, expr *sqlparser.AliasedExpr, addToGroupBy bool) (ops.Operator, bool, int) { switch op := operator.(type) { case *CorrelatedSubQueryOp: - return addColumnToInput(op.Outer, expr, addToGroupBy) + return addColumnToInput(ctx, op.Outer, expr, addToGroupBy) case *Limit: - return addColumnToInput(op.Source, expr, addToGroupBy) + return addColumnToInput(ctx, op.Source, expr, addToGroupBy) case *Ordering: - return addColumnToInput(op.Source, expr, addToGroupBy) + return addColumnToInput(ctx, op.Source, expr, addToGroupBy) case selectExpressions: if op.isDerived() { // if the only thing we can push to is a derived table, // we have to add a new projection and can't build on this one - return false, 0 + return op, false, 0 } offset := op.addColumnWithoutPushing(expr, addToGroupBy) - return true, offset + return op, true, offset + case *Union: + tableID := semantics.SingleTableSet(len(ctx.SemTable.Tables)) + ctx.SemTable.Tables = append(ctx.SemTable.Tables, nil) + return &Projection{ + Source: op, + Columns: append(op.columns, expr), + Projections: nil, + TableID: &tableID, + Alias: "dt", + }, true, len(op.columns) + //wsExpr, isWeightString := expr.Expr.(*sqlparser.WeightStringFuncExpr) + //if !isWeightString { + // return false, 0, vterrors.VT12001("Pushing columns in union that isn't a weight string") + //} + //columnOffset := -1 + //for idx, column := range op.columns { + // if ctx.SemTable.EqualsExpr(column.Expr, wsExpr.Expr) { + // columnOffset = idx + // break + // } + //} + //if columnOffset == -1 { + // return false, 0, vterrors.VT13001("Couldn't find the offset of the weight string argument in Union") + //} + // + //idx := -1 + //for i, source := range op.Sources { + // cols, err := source.GetColumns(ctx) + // if err != nil { + // return false, 0, err + // } + // ok, offset, err := addColumnToInput(ctx, source, aeWrap(weightStringFor(cols[columnOffset].Expr)), false) + // if err != nil { + // return ok, offset, err + // } + // if !ok { + // if i == 0 { + // return false, 0, nil + // } + // // if we succeeded on one input, and failed later, we are kind of screwed + // return false, 0, vterrors.VT12001("could not push down to all inputs") + // } + // if idx == -1 { + // idx = offset + // continue + // } + // if idx != offset { + // return false, 0, vterrors.VT12001("union columns did not line up") + // } + //} + //return true, idx, nil + default: - return false, 0 + return op, false, 0 } } -func (r *Route) GetColumns() ([]*sqlparser.AliasedExpr, error) { - return r.Source.GetColumns() +func (r *Route) GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { + return r.Source.GetColumns(ctx) } -func (r *Route) GetSelectExprs() (sqlparser.SelectExprs, error) { - return r.Source.GetSelectExprs() +func (r *Route) GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.SelectExprs, error) { + return r.Source.GetSelectExprs(ctx) } func (r *Route) GetOrdering() ([]ops.OrderBy, error) { @@ -652,7 +707,7 @@ func (r *Route) planOffsets(ctx *plancontext.PlanningContext) (err error) { return err } - columns, err := r.Source.GetColumns() + columns, err := r.Source.GetColumns(ctx) if err != nil { return err } diff --git a/go/vt/vtgate/planbuilder/operators/table.go b/go/vt/vtgate/planbuilder/operators/table.go index 5fe54c3b488..820b0250c51 100644 --- a/go/vt/vtgate/planbuilder/operators/table.go +++ b/go/vt/vtgate/planbuilder/operators/table.go @@ -77,12 +77,12 @@ func (to *Table) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.Ali return to, offset, nil } -func (to *Table) GetColumns() ([]*sqlparser.AliasedExpr, error) { +func (to *Table) GetColumns(*plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { return slice.Map(to.Columns, colNameToExpr), nil } -func (to *Table) GetSelectExprs() (sqlparser.SelectExprs, error) { - return transformColumnsToSelectExprs(to) +func (to *Table) GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.SelectExprs, error) { + return transformColumnsToSelectExprs(ctx, to) } func (to *Table) GetOrdering() ([]ops.OrderBy, error) { diff --git a/go/vt/vtgate/planbuilder/operators/union.go b/go/vt/vtgate/planbuilder/operators/union.go index 4e154f602e1..296c59d6a9f 100644 --- a/go/vt/vtgate/planbuilder/operators/union.go +++ b/go/vt/vtgate/planbuilder/operators/union.go @@ -26,6 +26,7 @@ import ( "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/rewrite" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" + "vitess.io/vitess/go/vt/vtgate/semantics" ) type Union struct { @@ -33,6 +34,7 @@ type Union struct { Selects []sqlparser.SelectExprs distinct bool + columns []*sqlparser.AliasedExpr offsetPlanned bool } @@ -184,8 +186,8 @@ func (u *Union) Compact(*plancontext.PlanningContext) (ops.Operator, *rewrite.Ap return u, rewrite.NewTree("merged UNIONs", u), nil } -func (u *Union) AddColumn(ctx *plancontext.PlanningContext, ae *sqlparser.AliasedExpr, reuseExisting, addToGroupBy bool) (ops.Operator, int, error) { - cols, err := u.GetColumns() +func (u *Union) AddColumn(ctx *plancontext.PlanningContext, ae *sqlparser.AliasedExpr, _, addToGroupBy bool) (ops.Operator, int, error) { + cols, err := u.GetColumns(ctx) if err != nil { return nil, 0, err } @@ -200,50 +202,79 @@ func (u *Union) AddColumn(ctx *plancontext.PlanningContext, ae *sqlparser.Aliase return nil, 0, vterrors.VT13001(fmt.Sprintf("only weight_string function is expected - got %s", sqlparser.String(ae))) } - newSrc, offset, err := u.Sources[0].AddColumn(ctx, ae, true, false) - if err != nil { - return nil, 0, err - } - u.Sources[0] = newSrc - - // we are adding a weight_string function. let's find the offset of the argument to it - argIdx := slices.IndexFunc(u.Selects[0], func(se sqlparser.SelectExpr) bool { - ae, ok := se.(*sqlparser.AliasedExpr) - if !ok { - err = vterrors.VT12001("can't handle star expressions inside UNION") - return false - } - return ctx.SemTable.EqualsExprWithDeps(ae.Expr, ws.Expr) + wsArg := ws.Expr + argIdx := slices.IndexFunc(cols, func(expr *sqlparser.AliasedExpr) bool { + return ctx.SemTable.EqualsExprWithDeps(wsArg, expr.Expr) }) + if argIdx == -1 { - return nil, 0, vterrors.VT13001(fmt.Sprintf("could not find the actual expression to add weight_string function: %s", sqlparser.String(ws.Expr))) + return nil, 0, vterrors.VT13001(fmt.Sprintf("could not find the argument to the weight_string function: %s", sqlparser.String(wsArg))) } - for i := 1; i < len(u.Sources); i++ { + var outputOffset int + + for i, src := range u.Sources { exprs := u.Selects[i] selectExpr := exprs[argIdx] ae, ok := selectExpr.(*sqlparser.AliasedExpr) if !ok { return nil, 0, vterrors.VT09015() } - newSrc, this, err := u.Sources[i].AddColumn(ctx, aeWrap(weightStringFor(ae.Expr)), true, false) + newSrc, thisOffset, err := src.AddColumn(ctx, aeWrap(weightStringFor(ae.Expr)), false, addToGroupBy) if err != nil { return nil, 0, err } - if this != offset { - return nil, 0, vterrors.VT12001("offsets did not line up for UNION") + + // all offsets for the newly added ws need to line up + if i == 0 { + outputOffset = thisOffset + } else { + if thisOffset != outputOffset { + return nil, 0, vterrors.VT12001("weight_string offsets did not line up for UNION") + } } + u.Sources[i] = newSrc } - return u, offset, nil + + return u, outputOffset, nil } -func (u *Union) GetColumns() ([]*sqlparser.AliasedExpr, error) { - return u.Sources[0].GetColumns() +func (u *Union) GetColumns(ctx *plancontext.PlanningContext) (result []*sqlparser.AliasedExpr, err error) { + if u.columns != nil { + return u.columns, nil + } + + var columns [][]*sqlparser.AliasedExpr + for _, source := range u.Sources { + getColumns, err := source.GetColumns(ctx) + if err != nil { + return nil, err + } + columns = append(columns, getColumns) + } + + for idx, column := range columns[0] { + col := sqlparser.NewColName(column.ColumnName()) + result = append(result, aeWrap(col)) + + dd := semantics.EmptyTableSet() + rd := semantics.EmptyTableSet() + for _, cols := range columns { + e := cols[idx].Expr + dd = dd.Merge(ctx.SemTable.DirectDeps(e)) + rd = rd.Merge(ctx.SemTable.RecursiveDeps(e)) + } + + ctx.SemTable.Direct[col] = dd + ctx.SemTable.Recursive[col] = rd + } + u.columns = result + return } -func (u *Union) GetSelectExprs() (sqlparser.SelectExprs, error) { - return u.Sources[0].GetSelectExprs() +func (u *Union) GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.SelectExprs, error) { + return u.Sources[0].GetSelectExprs(ctx) } func (u *Union) NoLHSTableSet() {} diff --git a/go/vt/vtgate/planbuilder/operators/union_merging.go b/go/vt/vtgate/planbuilder/operators/union_merging.go index 36ef44f09dd..cb126043c4b 100644 --- a/go/vt/vtgate/planbuilder/operators/union_merging.go +++ b/go/vt/vtgate/planbuilder/operators/union_merging.go @@ -10,6 +10,7 @@ import ( // can be used for UNION DISTINCT func mergeUnionInputInAnyOrder(ctx *plancontext.PlanningContext, op *Union) ([]ops.Operator, []sqlparser.SelectExprs, error) { sources := op.Sources + selects := op.Selects // next we'll go over all the plans from and check if any two can be merged. if they can, they are merged, // and we continue checking for pairs of plans that can be merged into a single route @@ -35,20 +36,23 @@ func mergeUnionInputInAnyOrder(ctx *plancontext.PlanningContext, op *Union) ([]o } } if !merged { - return sources, nil, nil + return sources, selects, nil } - var phase []ops.Operator + var newSources []ops.Operator + var newSelects []sqlparser.SelectExprs for i, source := range sources { if keep[i] || i <= idx { - phase = append(phase, source) + newSources = append(newSources, source) + newSelects = append(newSelects, selects[i]) } } idx++ - sources = phase + sources = newSources + selects = newSelects } - return sources, nil, nil + return sources, selects, nil } // mergeUnionInputs checks whether two operators can be merged into a single one. @@ -56,7 +60,7 @@ func mergeUnionInputInAnyOrder(ctx *plancontext.PlanningContext, op *Union) ([]o // If they cannot be merged, nil is returned. // this function is very similar to mergeJoinInputs func mergeUnionInputs(ctx *plancontext.PlanningContext, lhs, rhs ops.Operator, lhsExprs, rhsExprs sqlparser.SelectExprs, distinct bool) (ops.Operator, error) { - lhsRoute, rhsRoute, routingA, _, _, b, _ := prepareInputRoutes(lhs, rhs) + lhsRoute, rhsRoute, routingA, routingB, a, b, sameKeyspace := prepareInputRoutes(lhs, rhs) if lhsRoute == nil { return nil, nil } @@ -64,23 +68,28 @@ func mergeUnionInputs(ctx *plancontext.PlanningContext, lhs, rhs ops.Operator, l switch { // if either side is a dual query, we can always merge them together case b == dual: - //rhsRoute.Source = &Union{ - // Sources: []ops.Operator{lhsRoute.Source, rhsRoute.Source}, - // Selects: []sqlparser.SelectExprs{lhsExprs, rhsExprs}, - // distinct: false, - //} - //rhsRoute.MergedWith = append(rhsRoute.MergedWith, lhsRoute) - //return rhsRoute, nil - return &Route{ - Source: &Union{ - Sources: []ops.Operator{lhsRoute.Source, rhsRoute.Source}, - Selects: []sqlparser.SelectExprs{lhsExprs, rhsExprs}, - distinct: distinct, - }, - MergedWith: []*Route{rhsRoute}, - Routing: routingA, - }, nil + return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingA), nil + case a == dual: + return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB), nil + case a == sharded && b == sharded && sameKeyspace: + return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB), nil default: return nil, nil } } + +func createMergedUnion( + lhsRoute, rhsRoute *Route, + lhsExprs, rhsExprs sqlparser.SelectExprs, + distinct bool, + routing Routing) *Route { + return &Route{ + Source: &Union{ + Sources: []ops.Operator{lhsRoute.Source, rhsRoute.Source}, + Selects: []sqlparser.SelectExprs{lhsExprs, rhsExprs}, + distinct: distinct, + }, + MergedWith: []*Route{rhsRoute}, + Routing: routing, + } +} diff --git a/go/vt/vtgate/planbuilder/operators/vindex.go b/go/vt/vtgate/planbuilder/operators/vindex.go index 0b6ee6663e5..36b6002d1d6 100644 --- a/go/vt/vtgate/planbuilder/operators/vindex.go +++ b/go/vt/vtgate/planbuilder/operators/vindex.go @@ -82,12 +82,12 @@ func colNameToExpr(c *sqlparser.ColName) *sqlparser.AliasedExpr { } } -func (v *Vindex) GetColumns() ([]*sqlparser.AliasedExpr, error) { +func (v *Vindex) GetColumns(*plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { return slice.Map(v.Columns, colNameToExpr), nil } -func (v *Vindex) GetSelectExprs() (sqlparser.SelectExprs, error) { - return transformColumnsToSelectExprs(v) +func (v *Vindex) GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.SelectExprs, error) { + return transformColumnsToSelectExprs(ctx, v) } func (v *Vindex) GetOrdering() ([]ops.OrderBy, error) { diff --git a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json index 071b3972f18..f24949de3a2 100644 --- a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json @@ -370,9 +370,10 @@ "QueryType": "SELECT", "Original": "select distinct col from user", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "0", + "OperatorType": "Distinct", + "Collations": [ + "0" + ], "Inputs": [ { "OperatorType": "Route", @@ -381,9 +382,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select col from `user` where 1 != 1 group by col", - "OrderBy": "0 ASC", - "Query": "select col from `user` group by col order by col asc", + "FieldQuery": "select col from `user` where 1 != 1", + "Query": "select col from `user`", "Table": "`user`" } ] @@ -497,8 +497,7 @@ "Sharded": true }, "FieldQuery": "select col1, col2, weight_string(col1), weight_string(col2) from `user` where 1 != 1 group by col1, col2, weight_string(col1), weight_string(col2)", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2) order by col1 asc, col2 asc", + "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2)", "Table": "`user`" } ] @@ -528,8 +527,7 @@ "Sharded": true }, "FieldQuery": "select col2, weight_string(col2) from `user` where 1 != 1 group by col2, weight_string(col2)", - "OrderBy": "(0|1) ASC", - "Query": "select col2, weight_string(col2) from `user` group by col2, weight_string(col2) order by col2 asc", + "Query": "select col2, weight_string(col2) from `user` group by col2, weight_string(col2)", "Table": "`user`" } ] @@ -560,8 +558,7 @@ "Sharded": true }, "FieldQuery": "select col1, col2, weight_string(col1), weight_string(col2) from `user` where 1 != 1 group by col1, col2, weight_string(col1), weight_string(col2)", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2) order by col1 asc, col2 asc", + "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2)", "Table": "`user`" } ] @@ -592,8 +589,7 @@ "Sharded": true }, "FieldQuery": "select col1, col2, weight_string(col1), weight_string(col2) from `user` where 1 != 1 group by col1, col2, weight_string(col1), weight_string(col2)", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2) order by col1 asc, col2 asc", + "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2)", "Table": "`user`" } ] @@ -624,8 +620,7 @@ "Sharded": true }, "FieldQuery": "select col1, min(col2) as `min(distinct col2)`, weight_string(col1), weight_string(col2) from `user` where 1 != 1 group by col1, weight_string(col1), weight_string(col2)", - "OrderBy": "(0|2) ASC", - "Query": "select col1, min(col2) as `min(distinct col2)`, weight_string(col1), weight_string(col2) from `user` group by col1, weight_string(col1), weight_string(col2) order by col1 asc", + "Query": "select col1, min(col2) as `min(distinct col2)`, weight_string(col1), weight_string(col2) from `user` group by col1, weight_string(col1), weight_string(col2)", "Table": "`user`" } ] @@ -661,8 +656,7 @@ "Sharded": true }, "FieldQuery": "select col1, col2, weight_string(col1), weight_string(col2) from `user` where 1 != 1 group by col1, col2, weight_string(col1), weight_string(col2)", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2) order by col1 asc, col2 asc", + "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2)", "Table": "`user`" } ] @@ -700,8 +694,7 @@ "Sharded": true }, "FieldQuery": "select a, b, count(*), weight_string(a), weight_string(b) from `user` where 1 != 1 group by a, b, weight_string(a), weight_string(b)", - "OrderBy": "(0|3) ASC, (1|4) ASC", - "Query": "select a, b, count(*), weight_string(a), weight_string(b) from `user` group by a, b, weight_string(a), weight_string(b) order by a asc, b asc", + "Query": "select a, b, count(*), weight_string(a), weight_string(b) from `user` group by a, b, weight_string(a), weight_string(b)", "Table": "`user`" } ] @@ -732,8 +725,7 @@ "Sharded": true }, "FieldQuery": "select a, b, count(*), weight_string(b), weight_string(a) from `user` where 1 != 1 group by b, a, weight_string(b), weight_string(a)", - "OrderBy": "(1|3) ASC, (0|4) ASC", - "Query": "select a, b, count(*), weight_string(b), weight_string(a) from `user` group by b, a, weight_string(b), weight_string(a) order by b asc, a asc", + "Query": "select a, b, count(*), weight_string(b), weight_string(a) from `user` group by b, a, weight_string(b), weight_string(a)", "Table": "`user`" } ] @@ -764,8 +756,7 @@ "Sharded": true }, "FieldQuery": "select a, b, count(*), weight_string(b), weight_string(a) from `user` where 1 != 1 group by b, a, weight_string(b), weight_string(a)", - "OrderBy": "(1|3) ASC, (0|4) ASC", - "Query": "select a, b, count(*), weight_string(b), weight_string(a) from `user` group by b, a, weight_string(b), weight_string(a) order by b asc, a asc", + "Query": "select a, b, count(*), weight_string(b), weight_string(a) from `user` group by b, a, weight_string(b), weight_string(a)", "Table": "`user`" } ] @@ -1161,8 +1152,7 @@ "Sharded": true }, "FieldQuery": "select a, count(*), weight_string(a) from `user` where 1 != 1 group by a, weight_string(a)", - "OrderBy": "(0|2) ASC", - "Query": "select a, count(*), weight_string(a) from `user` group by a, weight_string(a) order by a asc", + "Query": "select a, count(*), weight_string(a) from `user` group by a, weight_string(a)", "Table": "`user`" } ] @@ -1193,8 +1183,7 @@ "Sharded": true }, "FieldQuery": "select id, 1.1 from `user` where 1 != 1 group by 1.1", - "OrderBy": "1 ASC", - "Query": "select id, 1.1 from `user` group by 1.1 order by 1.1 asc", + "Query": "select id, 1.1 from `user` group by 1.1", "Table": "`user`" } ] @@ -1301,9 +1290,11 @@ "QueryType": "SELECT", "Original": "select distinct col1, col2 from user group by col1, col2", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", + "OperatorType": "Distinct", + "Collations": [ + "(0:2)", + "(1:3)" + ], "ResultColumns": 2, "Inputs": [ { @@ -1313,9 +1304,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select col1, col2, weight_string(col1), weight_string(col2) from `user` where 1 != 1 group by col1, col2, weight_string(col1), weight_string(col2)", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2) order by col1 asc, col2 asc", + "FieldQuery": "select col1, col2, weight_string(col1), weight_string(col2) from `user` where 1 != 1", + "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user`", "Table": "`user`" } ] @@ -1380,8 +1370,7 @@ "Sharded": true }, "FieldQuery": "select `user`.a, weight_string(`user`.a) from `user` where 1 != 1 group by `user`.a, weight_string(`user`.a)", - "OrderBy": "(0|1) ASC", - "Query": "select `user`.a, weight_string(`user`.a) from `user` group by `user`.a, weight_string(`user`.a) order by `user`.a asc", + "Query": "select `user`.a, weight_string(`user`.a) from `user` group by `user`.a, weight_string(`user`.a)", "Table": "`user`" }, { @@ -1431,8 +1420,7 @@ "Sharded": true }, "FieldQuery": "select col1, col2, col2, weight_string(col1), weight_string(col2) from `user` where 1 != 1 group by col1, col2, weight_string(col1), weight_string(col2)", - "OrderBy": "(0|3) ASC, (1|4) ASC", - "Query": "select col1, col2, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2) order by col1 asc, col2 asc", + "Query": "select col1, col2, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2)", "Table": "`user`" } ] @@ -1607,8 +1595,7 @@ "Sharded": true }, "FieldQuery": "select lower(textcol1) as v, count(*), weight_string(lower(textcol1)) from `user` where 1 != 1 group by v, weight_string(lower(textcol1))", - "OrderBy": "(0|2) ASC", - "Query": "select lower(textcol1) as v, count(*), weight_string(lower(textcol1)) from `user` group by v, weight_string(lower(textcol1)) order by v asc", + "Query": "select lower(textcol1) as v, count(*), weight_string(lower(textcol1)) from `user` group by v, weight_string(lower(textcol1))", "Table": "`user`" } ] @@ -1669,7 +1656,7 @@ }, "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", + "Query": "select id, weight_string(id) from `user`", "ResultColumns": 1, "Table": "`user`" } @@ -2077,8 +2064,7 @@ "Sharded": true }, "FieldQuery": "select count(*) as a, val1, weight_string(val1) from `user` where 1 != 1 group by val1, weight_string(val1)", - "OrderBy": "(1|2) ASC", - "Query": "select count(*) as a, val1, weight_string(val1) from `user` group by val1, weight_string(val1) order by val1 asc", + "Query": "select count(*) as a, val1, weight_string(val1) from `user` group by val1, weight_string(val1)", "Table": "`user`" } ] @@ -2330,8 +2316,7 @@ "Sharded": true }, "FieldQuery": "select count(*), `user`.a, weight_string(`user`.a) from `user` where 1 != 1 group by `user`.a, weight_string(`user`.a)", - "OrderBy": "(1|2) ASC", - "Query": "select count(*), `user`.a, weight_string(`user`.a) from `user` group by `user`.a, weight_string(`user`.a) order by `user`.a asc", + "Query": "select count(*), `user`.a, weight_string(`user`.a) from `user` group by `user`.a, weight_string(`user`.a)", "Table": "`user`" }, { @@ -2392,8 +2377,7 @@ "Sharded": true }, "FieldQuery": "select count(*), `user`.a, weight_string(`user`.a) from `user` where 1 != 1 group by `user`.a, weight_string(`user`.a)", - "OrderBy": "(1|2) ASC", - "Query": "select count(*), `user`.a, weight_string(`user`.a) from `user` group by `user`.a, weight_string(`user`.a) order by `user`.a asc", + "Query": "select count(*), `user`.a, weight_string(`user`.a) from `user` group by `user`.a, weight_string(`user`.a)", "Table": "`user`" }, { @@ -2546,8 +2530,7 @@ "Sharded": true }, "FieldQuery": "select col1, min(id) as `min(distinct id)`, col3, weight_string(col1), weight_string(id), weight_string(col3) from `user` where 1 != 1 group by col1, col3, weight_string(col1), weight_string(id), weight_string(col3)", - "OrderBy": "(0|3) ASC, (2|5) ASC", - "Query": "select col1, min(id) as `min(distinct id)`, col3, weight_string(col1), weight_string(id), weight_string(col3) from `user` group by col1, col3, weight_string(col1), weight_string(id), weight_string(col3) order by col1 asc, col3 asc", + "Query": "select col1, min(id) as `min(distinct id)`, col3, weight_string(col1), weight_string(id), weight_string(col3) from `user` group by col1, col3, weight_string(col1), weight_string(id), weight_string(col3)", "Table": "`user`" } ] @@ -2636,8 +2619,7 @@ "Sharded": true }, "FieldQuery": "select val2, val1, count(*), weight_string(val2), weight_string(val1) from `user` where 1 != 1 group by val2, val1, weight_string(val2), weight_string(val1)", - "OrderBy": "(0|3) ASC, (1|4) ASC", - "Query": "select val2, val1, count(*), weight_string(val2), weight_string(val1) from `user` group by val2, val1, weight_string(val2), weight_string(val1) order by val2 asc, val1 asc", + "Query": "select val2, val1, count(*), weight_string(val2), weight_string(val1) from `user` group by val2, val1, weight_string(val2), weight_string(val1)", "Table": "`user`" } ] @@ -2668,8 +2650,7 @@ "Sharded": true }, "FieldQuery": "select ascii(val1) as a, count(*), weight_string(ascii(val1)) from `user` where 1 != 1 group by a, weight_string(ascii(val1))", - "OrderBy": "(0|2) ASC", - "Query": "select ascii(val1) as a, count(*), weight_string(ascii(val1)) from `user` group by a, weight_string(ascii(val1)) order by a asc", + "Query": "select ascii(val1) as a, count(*), weight_string(ascii(val1)) from `user` group by a, weight_string(ascii(val1))", "Table": "`user`" } ] @@ -2700,8 +2681,7 @@ "Sharded": true }, "FieldQuery": "select tcol1, tcol2, tcol2, weight_string(tcol1), weight_string(tcol2) from `user` where 1 != 1 group by tcol1, tcol2, weight_string(tcol1), weight_string(tcol2)", - "OrderBy": "(0|3) ASC, (1|4) ASC", - "Query": "select tcol1, tcol2, tcol2, weight_string(tcol1), weight_string(tcol2) from `user` group by tcol1, tcol2, weight_string(tcol1), weight_string(tcol2) order by tcol1 asc, tcol2 asc", + "Query": "select tcol1, tcol2, tcol2, weight_string(tcol1), weight_string(tcol2) from `user` group by tcol1, tcol2, weight_string(tcol1), weight_string(tcol2)", "Table": "`user`" } ] @@ -2732,8 +2712,7 @@ "Sharded": true }, "FieldQuery": "select tcol2, tcol1, count(*), tcol2, weight_string(tcol1), weight_string(tcol2) from `user` where 1 != 1 group by tcol1, tcol2, weight_string(tcol1), weight_string(tcol2)", - "OrderBy": "(1|4) ASC, (0|5) ASC", - "Query": "select tcol2, tcol1, count(*), tcol2, weight_string(tcol1), weight_string(tcol2) from `user` group by tcol1, tcol2, weight_string(tcol1), weight_string(tcol2) order by tcol1 asc, tcol2 asc", + "Query": "select tcol2, tcol1, count(*), tcol2, weight_string(tcol1), weight_string(tcol2) from `user` group by tcol1, tcol2, weight_string(tcol1), weight_string(tcol2)", "Table": "`user`" } ] @@ -2965,8 +2944,7 @@ "Sharded": true }, "FieldQuery": "select foo, count(*), weight_string(foo) from `user` where 1 != 1 group by foo, weight_string(foo)", - "OrderBy": "(0|2) ASC", - "Query": "select foo, count(*), weight_string(foo) from `user` group by foo, weight_string(foo) order by foo asc", + "Query": "select foo, count(*), weight_string(foo) from `user` group by foo, weight_string(foo)", "Table": "`user`" } ] @@ -3012,8 +2990,7 @@ "Sharded": true }, "FieldQuery": "select foo, sum(foo), sum(bar), weight_string(foo) from `user` where 1 != 1 group by foo, weight_string(foo)", - "OrderBy": "(0|3) ASC", - "Query": "select foo, sum(foo), sum(bar), weight_string(foo) from `user` group by foo, weight_string(foo) order by foo asc", + "Query": "select foo, sum(foo), sum(bar), weight_string(foo) from `user` group by foo, weight_string(foo)", "Table": "`user`" } ] @@ -3059,8 +3036,7 @@ "Sharded": true }, "FieldQuery": "select foo, sum(foo) as fooSum, sum(bar) as barSum, weight_string(foo) from `user` where 1 != 1 group by foo, weight_string(foo)", - "OrderBy": "(0|3) ASC", - "Query": "select foo, sum(foo) as fooSum, sum(bar) as barSum, weight_string(foo) from `user` group by foo, weight_string(foo) order by foo asc", + "Query": "select foo, sum(foo) as fooSum, sum(bar) as barSum, weight_string(foo) from `user` group by foo, weight_string(foo)", "Table": "`user`" } ] @@ -3104,8 +3080,7 @@ "Sharded": true }, "FieldQuery": "select foo, count(*), weight_string(foo) from `user` where 1 != 1 group by foo, weight_string(foo)", - "OrderBy": "(0|2) ASC", - "Query": "select foo, count(*), weight_string(foo) from `user` group by foo, weight_string(foo) order by foo asc", + "Query": "select foo, count(*), weight_string(foo) from `user` group by foo, weight_string(foo)", "Table": "`user`" } ] @@ -3412,8 +3387,7 @@ "Sharded": true }, "FieldQuery": "select `user`.col, `user`.id, weight_string(`user`.id) from `user` where 1 != 1 group by `user`.id, `user`.col, weight_string(`user`.id)", - "OrderBy": "(1|2) ASC", - "Query": "select `user`.col, `user`.id, weight_string(`user`.id) from `user` group by `user`.id, `user`.col, weight_string(`user`.id) order by `user`.id asc", + "Query": "select `user`.col, `user`.id, weight_string(`user`.id) from `user` group by `user`.id, `user`.col, weight_string(`user`.id)", "Table": "`user`" }, { @@ -3529,8 +3503,7 @@ "Sharded": true }, "FieldQuery": "select `user`.id, weight_string(id) from `user` where 1 != 1 group by id, weight_string(id)", - "OrderBy": "(0|1) ASC", - "Query": "select `user`.id, weight_string(id) from `user` group by id, weight_string(id) order by id asc", + "Query": "select `user`.id, weight_string(id) from `user` group by id, weight_string(id)", "Table": "`user`" }, { @@ -4096,8 +4069,7 @@ "Sharded": true }, "FieldQuery": "select foo, max(baz) as bazo, weight_string(foo), weight_string(baz) from (select foo, baz from `user` where 1 != 1) as f where 1 != 1 group by foo, weight_string(foo), weight_string(baz)", - "OrderBy": "(0|2) ASC", - "Query": "select foo, max(baz) as bazo, weight_string(foo), weight_string(baz) from (select foo, baz from `user`) as f group by foo, weight_string(foo), weight_string(baz) order by foo asc", + "Query": "select foo, max(baz) as bazo, weight_string(foo), weight_string(baz) from (select foo, baz from `user`) as f group by foo, weight_string(foo), weight_string(baz)", "Table": "`user`" } ] @@ -4141,8 +4113,7 @@ "Sharded": true }, "FieldQuery": "select foo, count(baz) as bazo, weight_string(foo) from (select foo, baz from `user` where 1 != 1) as f where 1 != 1 group by foo, weight_string(foo)", - "OrderBy": "(0|2) ASC", - "Query": "select foo, count(baz) as bazo, weight_string(foo) from (select foo, baz from `user`) as f group by foo, weight_string(foo) order by foo asc", + "Query": "select foo, count(baz) as bazo, weight_string(foo) from (select foo, baz from `user`) as f group by foo, weight_string(foo)", "Table": "`user`" } ] @@ -4182,8 +4153,7 @@ "Sharded": true }, "FieldQuery": "select col, count(*), col + 1, weight_string(col + 1) from `user` where 1 != 1 group by col", - "OrderBy": "0 ASC", - "Query": "select col, count(*), col + 1, weight_string(col + 1) from `user` group by col order by col asc", + "Query": "select col, count(*), col + 1, weight_string(col + 1) from `user` group by col", "Table": "`user`" } ] @@ -4210,7 +4180,7 @@ }, "FieldQuery": "select id, id + 1, weight_string(id + 1) from `user` where 1 != 1 group by id", "OrderBy": "(1|2) ASC", - "Query": "select id, id + 1, weight_string(id + 1) from `user` group by id order by id + 1 asc", + "Query": "select id, id + 1, weight_string(id + 1) from `user` group by id", "ResultColumns": 1, "Table": "`user`" }, @@ -4240,8 +4210,7 @@ "Sharded": true }, "FieldQuery": "select a, a + 1, weight_string(a + 1) from `user` where 1 != 1 group by a + 1, weight_string(a + 1)", - "OrderBy": "(1|2) ASC", - "Query": "select a, a + 1, weight_string(a + 1) from `user` group by a + 1, weight_string(a + 1) order by a + 1 asc", + "Query": "select a, a + 1, weight_string(a + 1) from `user` group by a + 1, weight_string(a + 1)", "Table": "`user`" } ] @@ -4914,9 +4883,11 @@ "QueryType": "SELECT", "Original": "select distinct a, b as a from user", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", + "OperatorType": "Distinct", + "Collations": [ + "(0:2)", + "(1:2)" + ], "ResultColumns": 2, "Inputs": [ { @@ -4926,9 +4897,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select a, b as a, weight_string(a), weight_string(b) from `user` where 1 != 1 group by a, b, weight_string(a), weight_string(b)", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Query": "select a, b as a, weight_string(a), weight_string(b) from `user` group by a, b, weight_string(a), weight_string(b) order by a asc, b asc", + "FieldQuery": "select a, b as a, weight_string(b) from `user` where 1 != 1", + "Query": "select a, b as a, weight_string(b) from `user`", "Table": "`user`" } ] @@ -4945,9 +4915,10 @@ "QueryType": "SELECT", "Original": "select distinct a+1 from user", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|1)", + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], "ResultColumns": 1, "Inputs": [ { @@ -4957,9 +4928,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select a + 1, weight_string(a + 1) from `user` where 1 != 1 group by a + 1, weight_string(a + 1)", - "OrderBy": "(0|1) ASC", - "Query": "select a + 1, weight_string(a + 1) from `user` group by a + 1, weight_string(a + 1) order by a + 1 asc", + "FieldQuery": "select a + 1, weight_string(a + 1) from `user` where 1 != 1", + "Query": "select a + 1, weight_string(a + 1) from `user`", "Table": "`user`" } ] @@ -4996,8 +4966,7 @@ "Sharded": true }, "FieldQuery": "select count(*), col from `user` where 1 != 1 group by col", - "OrderBy": "1 ASC", - "Query": "select count(*), col from `user` group by col order by col asc", + "Query": "select count(*), col from `user` group by col", "Table": "`user`" } ] @@ -5218,8 +5187,7 @@ "Sharded": true }, "FieldQuery": "select `user`.col, `user`.bar, weight_string(`user`.bar) from `user` where 1 != 1 group by `user`.col, `user`.bar, weight_string(`user`.bar)", - "OrderBy": "0 ASC, (1|2) ASC", - "Query": "select `user`.col, `user`.bar, weight_string(`user`.bar) from `user` group by `user`.col, `user`.bar, weight_string(`user`.bar) order by `user`.col asc, `user`.bar asc", + "Query": "select `user`.col, `user`.bar, weight_string(`user`.bar) from `user` group by `user`.col, `user`.bar, weight_string(`user`.bar)", "Table": "`user`" }, { @@ -5821,8 +5789,7 @@ "Sharded": true }, "FieldQuery": "select u.col1, weight_string(u.col1) from `user` as u where 1 != 1 group by u.col1, weight_string(u.col1)", - "OrderBy": "(0|1) ASC", - "Query": "select u.col1, weight_string(u.col1) from `user` as u group by u.col1, weight_string(u.col1) order by u.col1 asc", + "Query": "select u.col1, weight_string(u.col1) from `user` as u group by u.col1, weight_string(u.col1)", "Table": "`user`" }, { @@ -5867,8 +5834,7 @@ "Sharded": true }, "FieldQuery": "select foo, min(bar) as `min(distinct bar)`, baz, baz, max(toto) as `max(distinct toto)`, weight_string(foo), weight_string(bar), weight_string(baz), weight_string(toto) from `user` where 1 != 1 group by foo, baz, weight_string(foo), weight_string(bar), weight_string(baz), weight_string(toto)", - "OrderBy": "(0|5) ASC, (2|7) ASC", - "Query": "select foo, min(bar) as `min(distinct bar)`, baz, baz, max(toto) as `max(distinct toto)`, weight_string(foo), weight_string(bar), weight_string(baz), weight_string(toto) from `user` group by foo, baz, weight_string(foo), weight_string(bar), weight_string(baz), weight_string(toto) order by foo asc, baz asc", + "Query": "select foo, min(bar) as `min(distinct bar)`, baz, baz, max(toto) as `max(distinct toto)`, weight_string(foo), weight_string(bar), weight_string(baz), weight_string(toto) from `user` group by foo, baz, weight_string(foo), weight_string(bar), weight_string(baz), weight_string(toto)", "Table": "`user`" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json b/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json index db815ad46bb..8fe0b4e838b 100644 --- a/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json +++ b/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json @@ -501,7 +501,7 @@ { "comment": "create view with union with the same target shard", "query": "create view user.view_a as select * from music where user_id = 1 union select * from user where id = 1", - "plan": "VT09015: schema tracking required" + "plan": "VT13001: [BUG] do not know how to turn *operators.Distinct into SQL" }, { "comment": "create view with testing SingleRow Projection", diff --git a/go/vt/vtgate/planbuilder/testdata/from_cases.json b/go/vt/vtgate/planbuilder/testdata/from_cases.json index 533521881be..ca352638d22 100644 --- a/go/vt/vtgate/planbuilder/testdata/from_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/from_cases.json @@ -3751,8 +3751,7 @@ "Sharded": true }, "FieldQuery": "select col1, count(*), weight_string(col1) from (select colC + colD as col1 from `user` where 1 != 1) as tbl where 1 != 1 group by col1, weight_string(col1)", - "OrderBy": "(0|2) ASC", - "Query": "select col1, count(*), weight_string(col1) from (select colC + colD as col1 from `user`) as tbl group by col1, weight_string(col1) order by col1 asc", + "Query": "select col1, count(*), weight_string(col1) from (select colC + colD as col1 from `user`) as tbl group by col1, weight_string(col1)", "Table": "`user`" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json index 413e0a91bd1..7c7c49b6ae8 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json @@ -101,41 +101,36 @@ "QueryType": "SELECT", "Original": "select TABLE_NAME from information_schema.columns union select table_schema from information_schema.tables", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "0 COLLATE utf8mb4_0900_ai_ci", + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], + "ResultColumns": 1, "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "0 ASC COLLATE utf8mb4_0900_ai_ci", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_NAME from information_schema.`columns` where 1 != 1", - "Query": "select TABLE_NAME from information_schema.`columns`", - "Table": "information_schema.`columns`" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select table_schema from information_schema.`tables` where 1 != 1", - "Query": "select table_schema from information_schema.`tables`", - "Table": "information_schema.`tables`" - } - ] + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns` where 1 != 1", + "Query": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns`", + "Table": "information_schema.`columns`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select table_schema, weight_string(table_schema) from information_schema.`tables` where 1 != 1", + "Query": "select table_schema, weight_string(table_schema) from information_schema.`tables`", + "Table": "information_schema.`tables`" } ] } @@ -150,43 +145,58 @@ "QueryType": "SELECT", "Original": "select * from information_schema.tables where table_schema = 'user' union select * from information_schema.tables where table_schema = 'main'", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "0 COLLATE utf8mb4_0900_ai_ci, 1 COLLATE utf8mb4_0900_ai_ci, 2 COLLATE utf8mb4_0900_ai_ci, 3 COLLATE utf8mb4_0900_ai_ci, 4 COLLATE utf8mb4_0900_ai_ci, 5, 6 COLLATE utf8mb4_0900_ai_ci, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 COLLATE utf8mb4_0900_ai_ci, 18, 19 COLLATE utf8mb4_0900_ai_ci, 20 COLLATE utf8mb4_0900_ai_ci", + "OperatorType": "Distinct", + "Collations": [ + "(0:21)", + "(1:22)", + "(2:23)", + "(3:24)", + "(4:25)", + "(5:26)", + "(6:27)", + "(7:28)", + "(8:29)", + "(9:30)", + "(10:31)", + "(11:32)", + "(12:33)", + "(13:34)", + "(14:35)", + "(15:36)", + "(16:37)", + "(17:38)", + "(18:39)", + "(19:40)", + "(20:41)" + ], + "ResultColumns": 21, "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "0 ASC COLLATE utf8mb4_0900_ai_ci, 1 ASC COLLATE utf8mb4_0900_ai_ci, 2 ASC COLLATE utf8mb4_0900_ai_ci, 3 ASC COLLATE utf8mb4_0900_ai_ci, 4 ASC COLLATE utf8mb4_0900_ai_ci, 5 ASC, 6 ASC COLLATE utf8mb4_0900_ai_ci, 7 ASC, 8 ASC, 9 ASC, 10 ASC, 11 ASC, 12 ASC, 13 ASC, 14 ASC, 15 ASC, 16 ASC, 17 ASC COLLATE utf8mb4_0900_ai_ci, 18 ASC, 19 ASC COLLATE utf8mb4_0900_ai_ci, 20 ASC COLLATE utf8mb4_0900_ai_ci", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where 1 != 1", - "Query": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", - "SysTableTableSchema": "[VARCHAR(\"user\")]", - "Table": "information_schema.`tables`" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where 1 != 1", - "Query": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", - "SysTableTableSchema": "[VARCHAR(\"main\")]", - "Table": "information_schema.`tables`" - } - ] + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where 1 != 1", + "Query": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"user\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where 1 != 1", + "Query": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"main\")]", + "Table": "information_schema.`tables`" } ] } @@ -771,12 +781,83 @@ { "comment": "select sum(found) from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", "query": "select sum(found) from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", - "plan": "VT13001: [BUG] only weight_string function is expected - got found" + "plan": { + "QueryType": "SELECT", + "Original": "select sum(found) from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", + "Instructions": { + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "sum(0) AS sum(found)", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", + "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"music\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.views where 1 != 1", + "Query": "select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1", + "SysTableTableSchema": "[VARCHAR(\"music\")]", + "Table": "information_schema.views" + } + ] + } + ] + } + } }, { "comment": "union as a derived table", "query": "select found from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", - "plan": "VT13001: [BUG] only weight_string function is expected - got found" + "plan": { + "QueryType": "SELECT", + "Original": "select found from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", + "Instructions": { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", + "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"music\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.views where 1 != 1", + "Query": "select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1", + "SysTableTableSchema": "[VARCHAR(\"music\")]", + "Table": "information_schema.views" + } + ] + } + } }, { "comment": "merge system schema queries as long as they have any same table_schema", @@ -913,7 +994,7 @@ { "comment": "merge even one side have schema name in derived table", "query": "select * from (select TABLE_NAME from information_schema.tables t where t.TABLE_SCHEMA = 'a' union select TABLE_NAME from information_schema.columns) dt", - "plan": "VT13001: [BUG] did not expect to add group by here" + "plan": "VT13001: [BUG] only weight_string function is expected - got dt.TABLE_NAME" }, { "comment": "merge even one side have schema name in subquery", diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json index b676dc78f22..d326e98830a 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json @@ -101,41 +101,36 @@ "QueryType": "SELECT", "Original": "select TABLE_NAME from information_schema.columns union select table_schema from information_schema.tables", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "0 COLLATE utf8mb4_0900_ai_ci", + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], + "ResultColumns": 1, "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "0 ASC COLLATE utf8mb4_0900_ai_ci", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_NAME from information_schema.`columns` where 1 != 1", - "Query": "select TABLE_NAME from information_schema.`columns`", - "Table": "information_schema.`columns`" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select table_schema from information_schema.`tables` where 1 != 1", - "Query": "select table_schema from information_schema.`tables`", - "Table": "information_schema.`tables`" - } - ] + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns` where 1 != 1", + "Query": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns`", + "Table": "information_schema.`columns`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select table_schema, weight_string(table_schema) from information_schema.`tables` where 1 != 1", + "Query": "select table_schema, weight_string(table_schema) from information_schema.`tables`", + "Table": "information_schema.`tables`" } ] } @@ -150,43 +145,58 @@ "QueryType": "SELECT", "Original": "select * from information_schema.tables where table_schema = 'user' union select * from information_schema.tables where table_schema = 'main'", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "0 COLLATE utf8mb4_0900_ai_ci, 1 COLLATE utf8mb4_0900_ai_ci, 2 COLLATE utf8mb4_0900_ai_ci, 3, 4 COLLATE utf8mb4_0900_ai_ci, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 COLLATE utf8mb4_0900_ai_ci, 18, 19 COLLATE utf8mb4_0900_ai_ci, 20 COLLATE utf8mb4_0900_ai_ci", + "OperatorType": "Distinct", + "Collations": [ + "(0:21)", + "(1:22)", + "(2:23)", + "(3:24)", + "(4:25)", + "(5:26)", + "(6:27)", + "(7:28)", + "(8:29)", + "(9:30)", + "(10:31)", + "(11:32)", + "(12:33)", + "(13:34)", + "(14:35)", + "(15:36)", + "(16:37)", + "(17:38)", + "(18:39)", + "(19:40)", + "(20:41)" + ], + "ResultColumns": 21, "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "0 ASC COLLATE utf8mb4_0900_ai_ci, 1 ASC COLLATE utf8mb4_0900_ai_ci, 2 ASC COLLATE utf8mb4_0900_ai_ci, 3 ASC, 4 ASC COLLATE utf8mb4_0900_ai_ci, 5 ASC, 6 ASC, 7 ASC, 8 ASC, 9 ASC, 10 ASC, 11 ASC, 12 ASC, 13 ASC, 14 ASC, 15 ASC, 16 ASC, 17 ASC COLLATE utf8mb4_0900_ai_ci, 18 ASC, 19 ASC COLLATE utf8mb4_0900_ai_ci, 20 ASC COLLATE utf8mb4_0900_ai_ci", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where 1 != 1", - "Query": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", - "SysTableTableSchema": "[VARCHAR(\"user\")]", - "Table": "information_schema.`tables`" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where 1 != 1", - "Query": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", - "SysTableTableSchema": "[VARCHAR(\"main\")]", - "Table": "information_schema.`tables`" - } - ] + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where 1 != 1", + "Query": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"user\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where 1 != 1", + "Query": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"main\")]", + "Table": "information_schema.`tables`" } ] } @@ -836,12 +846,83 @@ { "comment": "select sum(found) from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", "query": "select sum(found) from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", - "plan": "VT13001: [BUG] only weight_string function is expected - got found" + "plan": { + "QueryType": "SELECT", + "Original": "select sum(found) from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", + "Instructions": { + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "sum(0) AS sum(found)", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", + "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"music\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.views where 1 != 1", + "Query": "select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1", + "SysTableTableSchema": "[VARCHAR(\"music\")]", + "Table": "information_schema.views" + } + ] + } + ] + } + } }, { "comment": "union as a derived table", "query": "select found from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", - "plan": "VT13001: [BUG] only weight_string function is expected - got found" + "plan": { + "QueryType": "SELECT", + "Original": "select found from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", + "Instructions": { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", + "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"music\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.views where 1 != 1", + "Query": "select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1", + "SysTableTableSchema": "[VARCHAR(\"music\")]", + "Table": "information_schema.views" + } + ] + } + } }, { "comment": "merge system schema queries as long as they have any same table_schema", @@ -978,7 +1059,7 @@ { "comment": "merge even one side have schema name in derived table", "query": "select * from (select TABLE_NAME from information_schema.tables t where t.TABLE_SCHEMA = 'a' union select TABLE_NAME from information_schema.columns) dt", - "plan": "VT13001: [BUG] did not expect to add group by here" + "plan": "VT13001: [BUG] only weight_string function is expected - got dt.TABLE_NAME" }, { "comment": "merge even one side have schema name in subquery", diff --git a/go/vt/vtgate/planbuilder/testdata/large_union_cases.json b/go/vt/vtgate/planbuilder/testdata/large_union_cases.json index 557301a9a10..fde34dfe5fa 100644 --- a/go/vt/vtgate/planbuilder/testdata/large_union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/large_union_cases.json @@ -2,1007 +2,6 @@ { "comment": "this testcase breaks goland, so it lives on its own file", "query": "(SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270698330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270699497 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270703806 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270707364 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270714657 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270721330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270812079 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271011532 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271034164 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271034177 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271066849 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271098740 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271355000 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271924504 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272086055 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272127855 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272191137 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272468271 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270644941 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270650576 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270652906 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270660650 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270670201 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270698330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270699497 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270707364 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271799956 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271799956 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270644941 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270649256 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270653671 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270670201 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270717223 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270720898 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271346411 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271352121 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271354908 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271367516 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271472522 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271821733 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272068709 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272127855 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272191137 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272244005 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272468271 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272244005 ORDER BY created_at ASC, id ASC LIMIT 11)", - "plan": { - "QueryType": "SELECT", - "Original": "(SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270698330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270699497 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270703806 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270707364 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270714657 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270721330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270812079 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271011532 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271034164 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271034177 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271066849 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271098740 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271355000 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271924504 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272086055 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272127855 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272191137 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272468271 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270644941 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270650576 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270652906 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270660650 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270670201 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270698330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270699497 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270707364 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271799956 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271799956 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270644941 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270649256 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270653671 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270670201 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270717223 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270720898 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271346411 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271352121 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271354908 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271367516 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271472522 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271821733 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272068709 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272127855 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272191137 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272244005 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272468271 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272244005 ORDER BY created_at ASC, id ASC LIMIT 11)", - "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "ResultColumns": 2, - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270698330 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270698330)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270699497 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270699497)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270703806 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270703806)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270707364 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270707364)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270714657 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270714657)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270721330 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270721330)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270812079 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270812079)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271011532 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271011532)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271034164 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271034164)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271034177 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271034177)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271066849 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271066849)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271098740 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271098740)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271355000 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271355000)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271639345 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271639345)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271914117 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271914117)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271924504 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271924504)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272086055 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272086055)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272127855 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272127855)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272191137 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272191137)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272468271 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272468271)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270637436 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270637436)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270644941 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270644941)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270650576 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270650576)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270652906 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270652906)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270660650 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270660650)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270670201 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270670201)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270698330 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270698330)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270699497 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270699497)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270707364 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270707364)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271365691)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271799956 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271799956)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271914117 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271914117)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270637436 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270637436)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271799956 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271799956)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270637436 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270637436)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271639345 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271639345)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270644941 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270644941)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270649256 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270649256)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270653671 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270653671)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270670201 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270670201)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270717223 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270717223)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270720898 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270720898)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270982590 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270982590)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271346411 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271346411)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271352121 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271352121)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271354908 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271354908)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271365691)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271367516 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271367516)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271472522 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271472522)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271607757 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271607757)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271639345 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271639345)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271821733 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271821733)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271914117 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271914117)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272068709 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272068709)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272127855 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272127855)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272191137 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272191137)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272244005 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272244005)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272468271 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272468271)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270982590 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270982590)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271365691)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271607757 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271607757)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270982590 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1270982590)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271365691)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271607757 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1271607757)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", - "Query": "select content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272244005 order by created_at asc, id asc limit 11", - "Table": "music", - "Values": [ - "INT64(1272244005)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] - }, - "TablesUsed": [ - "user.music" - ] - } + "plan": "VT13001: [BUG] do not know how to turn *operators.Distinct into SQL" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json b/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json index 58e6744f1a6..fdaa73f5e25 100644 --- a/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json @@ -25,8 +25,7 @@ "Sharded": true }, "FieldQuery": "select a, b, count(*), weight_string(a), weight_string(b) from `user` where 1 != 1 group by a, weight_string(a)", - "OrderBy": "(0|3) ASC", - "Query": "select a, b, count(*), weight_string(a), weight_string(b) from `user` group by a, weight_string(a) order by a asc", + "Query": "select a, b, count(*), weight_string(a), weight_string(b) from `user` group by a, weight_string(a)", "Table": "`user`" } ] @@ -64,8 +63,7 @@ "Sharded": true }, "FieldQuery": "select a, b, count(*) as k, weight_string(a) from `user` where 1 != 1 group by a, weight_string(a)", - "OrderBy": "(0|3) ASC", - "Query": "select a, b, count(*) as k, weight_string(a) from `user` group by a, weight_string(a) order by a asc", + "Query": "select a, b, count(*) as k, weight_string(a) from `user` group by a, weight_string(a)", "Table": "`user`" } ] @@ -103,8 +101,7 @@ "Sharded": true }, "FieldQuery": "select a, b, count(*) as k, weight_string(a), weight_string(b) from `user` where 1 != 1 group by a, weight_string(a)", - "OrderBy": "(0|3) ASC", - "Query": "select a, b, count(*) as k, weight_string(a), weight_string(b) from `user` group by a, weight_string(a) order by a asc", + "Query": "select a, b, count(*) as k, weight_string(a), weight_string(b) from `user` group by a, weight_string(a)", "Table": "`user`" } ] @@ -146,8 +143,7 @@ "Sharded": true }, "FieldQuery": "select a, b, count(*) as k, weight_string(a) from `user` where 1 != 1 group by a, weight_string(a)", - "OrderBy": "(0|3) ASC", - "Query": "select a, b, count(*) as k, weight_string(a) from `user` group by a, weight_string(a) order by a asc limit :__upper_limit", + "Query": "select a, b, count(*) as k, weight_string(a) from `user` group by a, weight_string(a) limit :__upper_limit", "Table": "`user`" } ] @@ -187,8 +183,7 @@ "Sharded": true }, "FieldQuery": "select a, b, count(*) as k, weight_string(a) from `user` where 1 != 1 group by a, weight_string(a)", - "OrderBy": "(0|3) ASC", - "Query": "select a, b, count(*) as k, weight_string(a) from `user` group by a, weight_string(a) order by a asc", + "Query": "select a, b, count(*) as k, weight_string(a) from `user` group by a, weight_string(a)", "Table": "`user`" } ] @@ -259,7 +254,7 @@ }, "FieldQuery": "select id, weight_string(id) from (select `user`.id, `user`.col from `user` where 1 != 1) as t where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select id, weight_string(id) from (select `user`.id, `user`.col from `user`) as t order by id asc", + "Query": "select id, weight_string(id) from (select `user`.id, `user`.col from `user`) as t", "Table": "`user`" }, { @@ -554,7 +549,7 @@ }, "FieldQuery": "select a, convert(a, binary), weight_string(convert(a, binary)) from `user` where 1 != 1", "OrderBy": "(1|2) DESC", - "Query": "select a, convert(a, binary), weight_string(convert(a, binary)) from `user` order by convert(a, binary) desc", + "Query": "select a, convert(a, binary), weight_string(convert(a, binary)) from `user`", "ResultColumns": 1, "Table": "`user`" }, @@ -587,7 +582,7 @@ }, "FieldQuery": "select u.a, convert(a, binary), weight_string(convert(a, binary)) from `user` as u where 1 != 1", "OrderBy": "(1|2) DESC", - "Query": "select u.a, convert(a, binary), weight_string(convert(a, binary)) from `user` as u order by convert(a, binary) desc", + "Query": "select u.a, convert(a, binary), weight_string(convert(a, binary)) from `user` as u", "Table": "`user`" }, { @@ -647,7 +642,7 @@ }, "FieldQuery": "select col, id, weight_string(id) from `user` where 1 != 1", "OrderBy": "(1|2) ASC", - "Query": "select col, id, weight_string(id) from `user` order by id asc", + "Query": "select col, id, weight_string(id) from `user`", "ResultColumns": 1, "Table": "`user`" }, diff --git a/go/vt/vtgate/planbuilder/testdata/oltp_cases.json b/go/vt/vtgate/planbuilder/testdata/oltp_cases.json index b366f1a8f04..5708628eca9 100644 --- a/go/vt/vtgate/planbuilder/testdata/oltp_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/oltp_cases.json @@ -106,21 +106,28 @@ "QueryType": "SELECT", "Original": "SELECT DISTINCT c FROM sbtest30 WHERE id BETWEEN 1 AND 10 ORDER BY c", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "0 COLLATE latin1_swedish_ci", + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "0 ASC COLLATE latin1_swedish_ci", "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select c from sbtest30 where 1 != 1 group by c", - "OrderBy": "0 ASC COLLATE latin1_swedish_ci", - "Query": "select c from sbtest30 where id between 1 and 10 group by c order by c asc", - "Table": "sbtest30" + "OperatorType": "Distinct", + "Collations": [ + "0: latin1_swedish_ci" + ], + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select c from sbtest30 where 1 != 1", + "Query": "select c from sbtest30 where id between 1 and 10", + "Table": "sbtest30" + } + ] } ] }, diff --git a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json index bdbd665bbac..40ac155f0ae 100644 --- a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json @@ -267,7 +267,7 @@ }, "FieldQuery": "select user_id, col1, col2, weight_string(user_id) from authoritative where 1 != 1", "OrderBy": "(0|3) ASC", - "Query": "select user_id, col1, col2, weight_string(user_id) from authoritative order by user_id asc", + "Query": "select user_id, col1, col2, weight_string(user_id) from authoritative", "ResultColumns": 3, "Table": "authoritative" }, @@ -314,7 +314,7 @@ }, "FieldQuery": "select a, textcol1, b, weight_string(a), weight_string(b) from `user` where 1 != 1", "OrderBy": "(0|3) ASC, 1 ASC COLLATE latin1_swedish_ci, (2|4) ASC", - "Query": "select a, textcol1, b, weight_string(a), weight_string(b) from `user` order by a asc, textcol1 asc, b asc", + "Query": "select a, textcol1, b, weight_string(a), weight_string(b) from `user`", "ResultColumns": 3, "Table": "`user`" }, @@ -338,7 +338,7 @@ }, "FieldQuery": "select a, `user`.textcol1, b, weight_string(a), weight_string(b) from `user` where 1 != 1", "OrderBy": "(0|3) ASC, 1 ASC COLLATE latin1_swedish_ci, (2|4) ASC", - "Query": "select a, `user`.textcol1, b, weight_string(a), weight_string(b) from `user` order by a asc, textcol1 asc, b asc", + "Query": "select a, `user`.textcol1, b, weight_string(a), weight_string(b) from `user`", "ResultColumns": 3, "Table": "`user`" }, @@ -362,7 +362,7 @@ }, "FieldQuery": "select a, textcol1, b, textcol2, weight_string(a), weight_string(b) from `user` where 1 != 1", "OrderBy": "(0|4) ASC, 1 ASC COLLATE latin1_swedish_ci, (2|5) ASC, 3 ASC COLLATE latin1_swedish_ci", - "Query": "select a, textcol1, b, textcol2, weight_string(a), weight_string(b) from `user` order by a asc, textcol1 asc, b asc, textcol2 asc", + "Query": "select a, textcol1, b, textcol2, weight_string(a), weight_string(b) from `user`", "ResultColumns": 4, "Table": "`user`" }, @@ -391,7 +391,7 @@ }, "FieldQuery": "select id as foo, weight_string(id) from music where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select id as foo, weight_string(id) from music order by foo asc", + "Query": "select id as foo, weight_string(id) from music", "ResultColumns": 1, "Table": "music" }, @@ -542,7 +542,7 @@ "Sharded": true }, "FieldQuery": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where 1 != 1", - "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1 order by a asc", + "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1", "Table": "`user`", "Values": [ "INT64(1)" @@ -595,7 +595,7 @@ "Sharded": true }, "FieldQuery": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where 1 != 1", - "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1 order by a asc", + "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1", "Table": "`user`", "Values": [ "INT64(1)" @@ -713,7 +713,7 @@ "Sharded": true }, "FieldQuery": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where 1 != 1", - "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1 order by RAND()", + "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1", "Table": "`user`", "Values": [ "INT64(1)" @@ -1375,7 +1375,7 @@ }, "FieldQuery": "select id as foo, weight_string(id) from music where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select id as foo, weight_string(id) from music order by foo asc", + "Query": "select id as foo, weight_string(id) from music", "ResultColumns": 1, "Table": "music" }, @@ -1399,7 +1399,7 @@ }, "FieldQuery": "select id as foo, id2 as id, weight_string(id2) from music where 1 != 1", "OrderBy": "(1|2) ASC", - "Query": "select id as foo, id2 as id, weight_string(id2) from music order by id asc", + "Query": "select id as foo, id2 as id, weight_string(id2) from music", "ResultColumns": 2, "Table": "music" }, @@ -1429,7 +1429,7 @@ }, "FieldQuery": "select `name`, weight_string(`name`) from `user` where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select `name`, weight_string(`name`) from `user` order by `name` asc", + "Query": "select `name`, weight_string(`name`) from `user`", "Table": "`user`" }, { @@ -1538,8 +1538,7 @@ "Sharded": true }, "FieldQuery": "select count(id), num, weight_string(num) from `user` where 1 != 1 group by num, weight_string(num)", - "OrderBy": "(1|2) ASC", - "Query": "select count(id), num, weight_string(num) from `user` group by num, weight_string(num) order by num asc", + "Query": "select count(id), num, weight_string(num) from `user` group by num, weight_string(num)", "Table": "`user`" } ] @@ -1575,8 +1574,7 @@ "Sharded": true }, "FieldQuery": "select count(id), num, weight_string(num) from `user` where 1 != 1 group by num, weight_string(num)", - "OrderBy": "(1|2) ASC", - "Query": "select count(id), num, weight_string(num) from `user` group by num, weight_string(num) order by num asc", + "Query": "select count(id), num, weight_string(num) from `user` group by num, weight_string(num)", "Table": "`user`" } ] @@ -1609,7 +1607,7 @@ }, "FieldQuery": "select `name`, weight_string(`name`) from `user` where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select `name`, weight_string(`name`) from `user` order by `name` asc", + "Query": "select `name`, weight_string(`name`) from `user`", "Table": "`user`" }, { @@ -1646,7 +1644,7 @@ }, "FieldQuery": "select id, id, weight_string(id) from `user` where 1 != 1", "OrderBy": "(0|2) ASC", - "Query": "select id, id, weight_string(id) from `user` order by id asc", + "Query": "select id, id, weight_string(id) from `user`", "ResultColumns": 2, "Table": "`user`" }, @@ -1681,8 +1679,7 @@ "Sharded": true }, "FieldQuery": "select col, count(*), c1, weight_string(c1) from `user` where 1 != 1 group by col", - "OrderBy": "0 ASC", - "Query": "select col, count(*), c1, weight_string(c1) from `user` group by col order by col asc", + "Query": "select col, count(*), c1, weight_string(c1) from `user` group by col", "Table": "`user`" } ] @@ -1701,9 +1698,10 @@ "QueryType": "SELECT", "Original": "select distinct user.a from user join user_extra", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|1)", + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], "ResultColumns": 1, "Inputs": [ { @@ -1719,9 +1717,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select `user`.a, weight_string(`user`.a) from `user` where 1 != 1 group by `user`.a, weight_string(`user`.a)", - "OrderBy": "(0|1) ASC", - "Query": "select `user`.a, weight_string(`user`.a) from `user` group by `user`.a, weight_string(`user`.a) order by `user`.a asc", + "FieldQuery": "select `user`.a, weight_string(`user`.a) from `user` where 1 != 1", + "Query": "select `user`.a, weight_string(`user`.a) from `user`", "Table": "`user`" }, { @@ -1731,8 +1728,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select 1 from user_extra where 1 != 1 group by .0", - "Query": "select 1 from user_extra group by .0", + "FieldQuery": "select 1 from user_extra where 1 != 1", + "Query": "select 1 from user_extra", "Table": "user_extra" } ] @@ -1752,9 +1749,11 @@ "QueryType": "SELECT", "Original": "select distinct a as c, a from user", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|2)", + "OperatorType": "Distinct", + "Collations": [ + "(0:2)", + "(0:2)" + ], "ResultColumns": 2, "Inputs": [ { @@ -1764,9 +1763,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select a as c, a, weight_string(a) from `user` where 1 != 1 group by a, a, weight_string(a)", - "OrderBy": "(0|2) ASC, (0|2) ASC", - "Query": "select a as c, a, weight_string(a) from `user` group by a, a, weight_string(a) order by a asc, a asc", + "FieldQuery": "select a as c, a, weight_string(a) from `user` where 1 != 1", + "Query": "select a as c, a, weight_string(a) from `user`", "Table": "`user`" } ] @@ -1783,9 +1781,11 @@ "QueryType": "SELECT", "Original": "select distinct a, a from user", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|2)", + "OperatorType": "Distinct", + "Collations": [ + "(0:2)", + "(0:2)" + ], "ResultColumns": 2, "Inputs": [ { @@ -1795,9 +1795,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select a, a, weight_string(a) from `user` where 1 != 1 group by a, a, weight_string(a)", - "OrderBy": "(0|2) ASC, (0|2) ASC", - "Query": "select a, a, weight_string(a) from `user` group by a, a, weight_string(a) order by a asc, a asc", + "FieldQuery": "select a, a, weight_string(a) from `user` where 1 != 1", + "Query": "select a, a, weight_string(a) from `user`", "Table": "`user`" } ] @@ -1879,7 +1878,7 @@ }, "FieldQuery": "select id, id + 1, weight_string(id + 1) from `user` where 1 != 1", "OrderBy": "(1|2) ASC", - "Query": "select id, id + 1, weight_string(id + 1) from `user` order by id + 1 asc", + "Query": "select id, id + 1, weight_string(id + 1) from `user`", "ResultColumns": 1, "Table": "`user`" }, @@ -1903,7 +1902,7 @@ }, "FieldQuery": "select `user`.col1 as a, a collate utf8_general_ci, weight_string(a collate utf8_general_ci) from `user` where 1 != 1", "OrderBy": "(1|2) ASC", - "Query": "select `user`.col1 as a, a collate utf8_general_ci, weight_string(a collate utf8_general_ci) from `user` order by a collate utf8_general_ci asc", + "Query": "select `user`.col1 as a, a collate utf8_general_ci, weight_string(a collate utf8_general_ci) from `user`", "ResultColumns": 1, "Table": "`user`" }, @@ -1927,7 +1926,7 @@ }, "FieldQuery": "select id, id + 1, weight_string(id + 1) from `user` where 1 != 1", "OrderBy": "(1|2) ASC", - "Query": "select id, id + 1, weight_string(id + 1) from `user` order by id + 1 asc", + "Query": "select id, id + 1, weight_string(id + 1) from `user`", "ResultColumns": 1, "Table": "`user`" }, @@ -1951,7 +1950,7 @@ }, "FieldQuery": "select `user`.col1 as a, a collate utf8_general_ci, weight_string(a collate utf8_general_ci) from `user` where 1 != 1", "OrderBy": "(1|2) ASC", - "Query": "select `user`.col1 as a, a collate utf8_general_ci, weight_string(a collate utf8_general_ci) from `user` order by a collate utf8_general_ci asc", + "Query": "select `user`.col1 as a, a collate utf8_general_ci, weight_string(a collate utf8_general_ci) from `user`", "ResultColumns": 1, "Table": "`user`" }, @@ -2052,8 +2051,7 @@ "Sharded": true }, "FieldQuery": "select min(a.id), a.tcol1, weight_string(a.tcol1), weight_string(a.id) from `user` as a where 1 != 1 group by a.tcol1, weight_string(a.tcol1), weight_string(a.id)", - "OrderBy": "(1|2) ASC", - "Query": "select min(a.id), a.tcol1, weight_string(a.tcol1), weight_string(a.id) from `user` as a group by a.tcol1, weight_string(a.tcol1), weight_string(a.id) order by a.tcol1 asc", + "Query": "select min(a.id), a.tcol1, weight_string(a.tcol1), weight_string(a.id) from `user` as a group by a.tcol1, weight_string(a.tcol1), weight_string(a.id)", "Table": "`user`" }, { diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.json b/go/vt/vtgate/planbuilder/testdata/select_cases.json index d19799c16e0..e7615789b92 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.json @@ -1000,7 +1000,7 @@ }, "FieldQuery": "select user_id, weight_string(user_id) from music where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select user_id, weight_string(user_id) from music order by user_id asc limit :__upper_limit", + "Query": "select user_id, weight_string(user_id) from music", "ResultColumns": 1, "Table": "music" } @@ -1360,12 +1360,12 @@ { "comment": "union with the same target shard", "query": "select * from music where user_id = 1 union select * from user where id = 1", - "plan": "VT09015: schema tracking required" + "plan": "VT13001: [BUG] do not know how to turn *operators.Distinct into SQL" }, { "comment": "union with the same target shard last_insert_id", "query": "select *, last_insert_id() from music where user_id = 1 union select * from user where id = 1", - "plan": "VT09015: schema tracking required" + "plan": "VT13001: [BUG] do not know how to turn *operators.Distinct into SQL" }, { "comment": "unsharded union in derived table", @@ -3134,7 +3134,7 @@ }, "FieldQuery": "select id, `name`, weight_string(id) from `user` where 1 != 1", "OrderBy": "(0|2) ASC", - "Query": "select id, `name`, weight_string(id) from `user` where `name` = 'aa' order by id asc limit :__upper_limit", + "Query": "select id, `name`, weight_string(id) from `user` where `name` = 'aa'", "ResultColumns": 2, "Table": "`user`" } @@ -4168,8 +4168,7 @@ "Sharded": true }, "FieldQuery": "select id, count(*) as b, req, weight_string(req), weight_string(id) from user_extra where 1 != 1 group by req, id, weight_string(req), weight_string(id)", - "OrderBy": "(2|3) ASC, (0|4) ASC", - "Query": "select id, count(*) as b, req, weight_string(req), weight_string(id) from user_extra group by req, id, weight_string(req), weight_string(id) order by req asc, id asc", + "Query": "select id, count(*) as b, req, weight_string(req), weight_string(id) from user_extra group by req, id, weight_string(req), weight_string(id)", "Table": "user_extra" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 708cff1617d..fe0eadf0496 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -45,44 +45,22 @@ "QueryType": "SELECT", "Original": "select id from user union select id from music", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|1)", + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], "ResultColumns": 1, "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|1) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "Query": "select id, weight_string(id) from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from music where 1 != 1", - "Query": "select id, weight_string(id) from music", - "Table": "music" - } - ] - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select id from music where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id) from (select id from `user` union select id from music) as dt", + "Table": "`user`, music" } ] }, @@ -141,63 +119,7 @@ { "comment": "almost dereks query - two queries with order by and limit being scattered to two different sets of tablets", "query": "(SELECT id FROM user ORDER BY id DESC LIMIT 1) UNION ALL (SELECT id FROM music ORDER BY id DESC LIMIT 1)", - "plan": { - "QueryType": "SELECT", - "Original": "(SELECT id FROM user ORDER BY id DESC LIMIT 1) UNION ALL (SELECT id FROM music ORDER BY id DESC LIMIT 1)", - "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Limit", - "Count": "INT64(1)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", - "Table": "`user`" - } - ] - }, - { - "OperatorType": "Limit", - "Count": "INT64(1)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from music where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", - "Table": "music" - } - ] - } - ] - } - ] - }, - "TablesUsed": [ - "user.music", - "user.user" - ] - } + "plan": "VT13001: [BUG] only weight_string function is expected - got id" }, { "comment": "Union all", @@ -251,190 +173,50 @@ { "comment": "union all between two scatter selects, with order by", "query": "(select id from user order by id limit 5) union all (select id from music order by id desc limit 5)", - "plan": { - "QueryType": "SELECT", - "Original": "(select id from user order by id limit 5) union all (select id from music order by id desc limit 5)", - "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Limit", - "Count": "INT64(5)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) ASC", - "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", - "Table": "`user`" - } - ] - }, - { - "OperatorType": "Limit", - "Count": "INT64(5)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from music where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", - "Table": "music" - } - ] - } - ] - } - ] - }, - "TablesUsed": [ - "user.music", - "user.user" - ] - } + "plan": "VT13001: [BUG] only weight_string function is expected - got id" }, { "comment": "union all on scatter and single route", "query": "select id from user where id = 1 union select id from user where id = 1 union all select id from user", + "plan": "VT13001: [BUG] do not know how to turn *operators.Distinct into SQL" + }, + { + "comment": "union of information_schema with normal table", + "query": "select CHARACTER_SET_NAME from information_schema.CHARACTER_SETS union select user_name from unsharded", "plan": { "QueryType": "SELECT", - "Original": "select id from user where id = 1 union select id from user where id = 1 union all select id from user", + "Original": "select CHARACTER_SET_NAME from information_schema.CHARACTER_SETS union select user_name from unsharded", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" ], + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|1)", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|1) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "Query": "select id, weight_string(id) from `user` where id = 1", - "Table": "`user`", - "Values": [ - "INT64(1)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "Query": "select id, weight_string(id) from `user` where id = 1", - "Table": "`user`", - "Values": [ - "INT64(1)" - ], - "Vindex": "user_index" - } - ] - } - ] - } - ] + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select CHARACTER_SET_NAME, weight_string(CHARACTER_SET_NAME) from information_schema.CHARACTER_SETS where 1 != 1", + "Query": "select CHARACTER_SET_NAME, weight_string(CHARACTER_SET_NAME) from information_schema.CHARACTER_SETS", + "Table": "information_schema.CHARACTER_SETS" }, { "OperatorType": "Route", - "Variant": "Scatter", + "Variant": "Unsharded", "Keyspace": { - "Name": "user", - "Sharded": true + "Name": "main", + "Sharded": false }, - "FieldQuery": "select id from `user` where 1 != 1", - "Query": "select id from `user`", - "Table": "`user`" - } - ] - } - ] - }, - "TablesUsed": [ - "user.user" - ] - } - }, - { - "comment": "union of information_schema with normal table", - "query": "select CHARACTER_SET_NAME from information_schema.CHARACTER_SETS union select user_name from unsharded", - "plan": { - "QueryType": "SELECT", - "Original": "select CHARACTER_SET_NAME from information_schema.CHARACTER_SETS union select user_name from unsharded", - "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "0 COLLATE utf8mb4_0900_ai_ci", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "0 ASC COLLATE utf8mb4_0900_ai_ci", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select CHARACTER_SET_NAME from information_schema.CHARACTER_SETS where 1 != 1", - "Query": "select CHARACTER_SET_NAME from information_schema.CHARACTER_SETS", - "Table": "information_schema.CHARACTER_SETS" - }, - { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select user_name from unsharded where 1 != 1", - "Query": "select user_name from unsharded", - "Table": "unsharded" - } - ] + "FieldQuery": "select user_name, weight_string(user_name) from unsharded where 1 != 1", + "Query": "select user_name, weight_string(user_name) from unsharded", + "Table": "unsharded" } ] } @@ -457,18 +239,17 @@ "QueryType": "SELECT", "Original": "(select id from user union select id from music) union select 1 from dual", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|1)", + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], "ResultColumns": 1, "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|1) ASC", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Distinct", "Inputs": [ { "OperatorType": "Route", @@ -477,33 +258,22 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "Query": "select id, weight_string(id) from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from music where 1 != 1", - "Query": "select id, weight_string(id) from music", - "Table": "music" - }, - { - "OperatorType": "Route", - "Variant": "Reference", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1, weight_string(1) from dual where 1 != 1", - "Query": "select 1, weight_string(1) from dual", - "Table": "dual" + "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select id from music where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id) from (select id from `user` union select id from music) as dt", + "Table": "`user`, music" } ] + }, + { + "OperatorType": "Route", + "Variant": "Reference", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1, weight_string(1) from dual where 1 != 1", + "Query": "select 1, weight_string(1) from dual", + "Table": "dual" } ] } @@ -529,87 +299,150 @@ { "comment": "union with the same target shard because of vindex", "query": "select * from music where id = 1 union select * from user where id = 1", - "plan": "VT09015: schema tracking required" + "plan": "VT13001: [BUG] do not know how to turn *operators.Distinct into SQL" }, { "comment": "union with different target shards", "query": "select 1 from music where id = 1 union select 1 from music where id = 2", + "plan": "VT13001: [BUG] do not know how to turn *operators.Distinct into SQL" + }, + { + "comment": "multiple select statement have inner order by with union - TODO (systay) no need to send down ORDER BY if we are going to loose it with UNION DISTINCT", + "query": "(select id from user order by 1 desc) union (select id from user order by 1 asc)", + "plan": { + "QueryType": "SELECT", + "Original": "(select id from user order by 1 desc) union (select id from user order by 1 asc)", + "Instructions": { + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], + "ResultColumns": 1, + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from ((select id from `user` where 1 != 1) union (select id from `user` where 1 != 1)) as dt where 1 != 1", + "Query": "select id, weight_string(id) from ((select id from `user` order by id desc) union (select id from `user` order by id asc)) as dt", + "Table": "`user`" + } + ] + }, + "TablesUsed": [ + "user.user" + ] + } + }, + { + "comment": "multiple unions", + "query": "select 1 union select null union select 1.0 union select '1' union select 2 union select 2.0 from user", + "plan": "VT13001: [BUG] do not know how to turn *operators.Distinct into SQL" + }, + { + "comment": "union distinct between a scatter query and a join (other side)", + "query": "(select user.id, user.name from user join user_extra where user_extra.extra = 'asdf') union select 'b','c' from user", "plan": { "QueryType": "SELECT", - "Original": "select 1 from music where id = 1 union select 1 from music where id = 2", + "Original": "(select user.id, user.name from user join user_extra where user_extra.extra = 'asdf') union select 'b','c' from user", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "0", + "OperatorType": "Distinct", + "Collations": [ + "(0:2)", + "(1:3)" + ], + "ResultColumns": 2, "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "0 ASC", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,L:1,L:2,L:3", + "TableName": "`user`_user_extra", "Inputs": [ { "OperatorType": "Route", - "Variant": "EqualUnique", + "Variant": "Scatter", "Keyspace": { "Name": "user", "Sharded": true }, - "FieldQuery": "select 1 from music where 1 != 1", - "Query": "select 1 from music where id = 1", - "Table": "music", - "Values": [ - "INT64(1)" - ], - "Vindex": "music_user_map" + "FieldQuery": "select `user`.id, `user`.`name`, weight_string(`user`.id), weight_string(`user`.`name`) from `user` where 1 != 1", + "Query": "select `user`.id, `user`.`name`, weight_string(`user`.id), weight_string(`user`.`name`) from `user`", + "Table": "`user`" }, { "OperatorType": "Route", - "Variant": "EqualUnique", + "Variant": "Scatter", "Keyspace": { "Name": "user", "Sharded": true }, - "FieldQuery": "select 1 from music where 1 != 1", - "Query": "select 1 from music where id = 2", - "Table": "music", - "Values": [ - "INT64(2)" - ], - "Vindex": "music_user_map" + "FieldQuery": "select 1 from user_extra where 1 != 1", + "Query": "select 1 from user_extra where user_extra.extra = 'asdf'", + "Table": "user_extra" } ] + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 'b', 'c', weight_string('b'), weight_string('c') from `user` where 1 != 1", + "Query": "select 'b', 'c', weight_string('b'), weight_string('c') from `user`", + "Table": "`user`" } ] } ] }, "TablesUsed": [ - "user.music" + "user.user", + "user.user_extra" ] } }, { - "comment": "multiple select statement have inner order by with union - TODO (systay) no need to send down ORDER BY if we are going to loose it with UNION DISTINCT", - "query": "(select id from user order by 1 desc) union (select id from user order by 1 asc)", + "comment": "union distinct between a scatter query and a join (other side)", + "query": "select 'b','c' from user union (select user.id, user.name from user join user_extra where user_extra.extra = 'asdf')", "plan": { "QueryType": "SELECT", - "Original": "(select id from user order by 1 desc) union (select id from user order by 1 asc)", + "Original": "select 'b','c' from user union (select user.id, user.name from user join user_extra where user_extra.extra = 'asdf')", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|1)", - "ResultColumns": 1, + "OperatorType": "Distinct", + "Collations": [ + "(0:2)", + "(1:3)" + ], + "ResultColumns": 2, "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|1) ASC", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 'b', 'c', weight_string('b'), weight_string('c') from `user` where 1 != 1", + "Query": "select 'b', 'c', weight_string('b'), weight_string('c') from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,L:1,L:2,L:3", + "TableName": "`user`_user_extra", "Inputs": [ { "OperatorType": "Route", @@ -618,9 +451,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from `user` order by id desc", + "FieldQuery": "select `user`.id, `user`.`name`, weight_string(`user`.id), weight_string(`user`.`name`) from `user` where 1 != 1", + "Query": "select `user`.id, `user`.`name`, weight_string(`user`.id), weight_string(`user`.`name`) from `user`", "Table": "`user`" }, { @@ -630,106 +462,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) ASC", - "Query": "select id, weight_string(id) from `user` order by id asc", - "Table": "`user`" - } - ] - } - ] - } - ] - }, - "TablesUsed": [ - "user.user" - ] - } - }, - { - "comment": "multiple unions", - "query": "select 1 union select null union select 1.0 union select '1' union select 2 union select 2.0 from user", - "plan": { - "QueryType": "SELECT", - "Original": "select 1 union select null union select 1.0 union select '1' union select 2 union select 2.0 from user", - "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "0", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "0 ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Reference", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 from dual where 1 != 1", - "Query": "select 1 from dual", - "Table": "dual" - }, - { - "OperatorType": "Route", - "Variant": "Reference", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select null from dual where 1 != 1", - "Query": "select null from dual", - "Table": "dual" - }, - { - "OperatorType": "Route", - "Variant": "Reference", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1.0 from dual where 1 != 1", - "Query": "select 1.0 from dual", - "Table": "dual" - }, - { - "OperatorType": "Route", - "Variant": "Reference", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select '1' from dual where 1 != 1", - "Query": "select '1' from dual", - "Table": "dual" - }, - { - "OperatorType": "Route", - "Variant": "Reference", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 2 from dual where 1 != 1", - "Query": "select 2 from dual", - "Table": "dual" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select 2.0 from `user` where 1 != 1", - "Query": "select 2.0 from `user`", - "Table": "`user`" + "FieldQuery": "select 1 from user_extra where 1 != 1", + "Query": "select 1 from user_extra where user_extra.extra = 'asdf'", + "Table": "user_extra" } ] } @@ -738,61 +473,32 @@ ] }, "TablesUsed": [ - "main.dual", - "user.user" + "user.user", + "user.user_extra" ] } }, { - "comment": "union distinct between a scatter query and a join (other side)", - "query": "(select user.id, user.name from user join user_extra where user_extra.extra = 'asdf') union select 'b','c' from user", + "comment": "unmergable because we are using aggregation", + "query": "select count(*) as s from user union select count(*) as s from music", "plan": { "QueryType": "SELECT", - "Original": "(select user.id, user.name from user join user_extra where user_extra.extra = 'asdf') union select 'b','c' from user", + "Original": "select count(*) as s from user union select count(*) as s from music", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|2), (1|3)", - "ResultColumns": 2, + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], + "ResultColumns": 1, "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC, (1|3) ASC", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "sum_count_star(0) AS s, any_value(1)", "Inputs": [ - { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "L:0,L:1,L:2,L:3", - "TableName": "`user`_user_extra", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select `user`.id, `user`.`name`, weight_string(`user`.id), weight_string(`user`.`name`) from `user` where 1 != 1", - "Query": "select `user`.id, `user`.`name`, weight_string(`user`.id), weight_string(`user`.`name`) from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select 1 from user_extra where 1 != 1", - "Query": "select 1 from user_extra where user_extra.extra = 'asdf'", - "Table": "user_extra" - } - ] - }, { "OperatorType": "Route", "Variant": "Scatter", @@ -800,40 +506,16 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select 'b', 'c', weight_string('b'), weight_string('c') from `user` where 1 != 1", - "Query": "select 'b', 'c', weight_string('b'), weight_string('c') from `user`", + "FieldQuery": "select count(*) as s, weight_string(count(*)) from `user` where 1 != 1", + "Query": "select count(*) as s, weight_string(count(*)) from `user`", "Table": "`user`" } ] - } - ] - } - ] - }, - "TablesUsed": [ - "user.user", - "user.user_extra" - ] - } - }, - { - "comment": "union distinct between a scatter query and a join (other side)", - "query": "select 'b','c' from user union (select user.id, user.name from user join user_extra where user_extra.extra = 'asdf')", - "plan": { - "QueryType": "SELECT", - "Original": "select 'b','c' from user union (select user.id, user.name from user join user_extra where user_extra.extra = 'asdf')", - "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "0 COLLATE utf8mb4_0900_ai_ci, 1 COLLATE utf8mb4_0900_ai_ci", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "0 ASC COLLATE utf8mb4_0900_ai_ci, 1 ASC COLLATE utf8mb4_0900_ai_ci", - "Inputs": [ + }, { - "OperatorType": "Concatenate", + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "sum_count_star(0) AS s, any_value(1)", "Inputs": [ { "OperatorType": "Route", @@ -842,106 +524,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select 'b', 'c' from `user` where 1 != 1", - "Query": "select 'b', 'c' from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "L:0,L:1", - "TableName": "`user`_user_extra", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select `user`.id, `user`.`name` from `user` where 1 != 1", - "Query": "select `user`.id, `user`.`name` from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select 1 from user_extra where 1 != 1", - "Query": "select 1 from user_extra where user_extra.extra = 'asdf'", - "Table": "user_extra" - } - ] - } - ] - } - ] - } - ] - }, - "TablesUsed": [ - "user.user", - "user.user_extra" - ] - } - }, - { - "comment": "unmergable because we are using aggregation", - "query": "select count(*) as s from user union select count(*) as s from music", - "plan": { - "QueryType": "SELECT", - "Original": "select count(*) as s from user union select count(*) as s from music", - "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "0", - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "0 ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Aggregate", - "Variant": "Scalar", - "Aggregates": "sum_count_star(0) AS s", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select count(*) as s from `user` where 1 != 1", - "Query": "select count(*) as s from `user`", - "Table": "`user`" - } - ] - }, - { - "OperatorType": "Aggregate", - "Variant": "Scalar", - "Aggregates": "sum_count_star(0) AS s", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select count(*) as s from music where 1 != 1", - "Query": "select count(*) as s from music", - "Table": "music" - } - ] + "FieldQuery": "select count(*) as s, weight_string(count(*)) from music where 1 != 1", + "Query": "select count(*) as s, weight_string(count(*)) from music", + "Table": "music" } ] } @@ -958,7 +543,7 @@ { "comment": "Union in derived table with first SELECT being an UNION", "query": "select * from ((select id from user union select id+1 from user) union select user_id from user_extra) as t", - "plan": "VT13001: [BUG] did not expect to add group by here" + "plan": "VT13001: [BUG] only weight_string function is expected - got t.id" }, { "comment": "gen4 optimises away ORDER BY when it's safe to do", @@ -967,72 +552,52 @@ "QueryType": "SELECT", "Original": "(select id from user union select id from music order by id) union select 1 from unsharded", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|1)", + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], "ResultColumns": 1, "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|1) ASC", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|1) ASC", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|1)", + "OperatorType": "Distinct", + "Collations": [ + "(0:1)", + "(1:2)" + ], "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|1) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "Query": "select id, weight_string(id) from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from music where 1 != 1", - "Query": "select id, weight_string(id) from music", - "Table": "music" - } - ] - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id), weight_string(weight_string(id)) from (select id from `user` where 1 != 1 union select id from music where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id), weight_string(weight_string(id)) from (select id from `user` union select id from music) as dt", + "Table": "`user`, music" } ] - }, - { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1, weight_string(1) from unsharded where 1 != 1", - "Query": "select 1, weight_string(1) from unsharded", - "Table": "unsharded" } ] + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1, weight_string(1) from unsharded where 1 != 1", + "Query": "select 1, weight_string(1) from unsharded", + "Table": "unsharded" } ] } @@ -1056,44 +621,22 @@ "Count": "INT64(10)", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|1)", + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], "ResultColumns": 1, "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|1) ASC", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "Query": "select id, weight_string(id) from `user` limit :__upper_limit", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Reference", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 3, weight_string(3) from dual where 1 != 1", - "Query": "select 3, weight_string(3) from dual limit :__upper_limit", - "Table": "dual" - } - ] - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id) from (select id from `user` union select 3 from dual) as dt", + "Table": "`user`, dual" } ] } @@ -1134,64 +677,58 @@ "QueryType": "SELECT", "Original": "select col from unsharded union select id from user union select col2 from unsharded union select col from user_extra", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|1)", + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], "ResultColumns": 1, "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|1) ASC", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select col, weight_string(col) from unsharded where 1 != 1", - "Query": "select col, weight_string(col) from unsharded", - "Table": "unsharded" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "Query": "select id, weight_string(id) from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select col2, weight_string(col2) from unsharded where 1 != 1", - "Query": "select col2, weight_string(col2) from unsharded", - "Table": "unsharded" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select col, weight_string(col) from user_extra where 1 != 1", - "Query": "select col, weight_string(col) from user_extra", - "Table": "user_extra" - } - ] + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select col, weight_string(col) from unsharded where 1 != 1", + "Query": "select col, weight_string(col) from unsharded", + "Table": "unsharded" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "Query": "select id, weight_string(id) from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select col2, weight_string(col2) from unsharded where 1 != 1", + "Query": "select col2, weight_string(col2) from unsharded", + "Table": "unsharded" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select col, weight_string(col) from user_extra where 1 != 1", + "Query": "select col, weight_string(col) from user_extra", + "Table": "user_extra" } ] } @@ -1236,42 +773,24 @@ "QueryType": "SELECT", "Original": "select id from user union select 3 order by id", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|1)", + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|1) ASC", "ResultColumns": 1, "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|1) ASC", + "OperatorType": "Distinct", "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "Query": "select id, weight_string(id) from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Reference", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 3, weight_string(3) from dual where 1 != 1", - "Query": "select 3, weight_string(3) from dual", - "Table": "dual" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id) from (select id from `user` union select 3 from dual) as dt", + "Table": "`user`, dual" } ] } @@ -1296,41 +815,35 @@ ], "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|1)", + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|1) ASC", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id + 42 as foo, weight_string(id + 42) from `user` where 1 != 1", - "Query": "select id + 42 as foo, weight_string(id + 42) from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 + id as foo, weight_string(1 + id) from unsharded where 1 != 1", - "Query": "select 1 + id as foo, weight_string(1 + id) from unsharded", - "Table": "unsharded" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id + 42 as foo, weight_string(id + 42) from `user` where 1 != 1", + "Query": "select id + 42 as foo, weight_string(id + 42) from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 + id as foo, weight_string(1 + id) from unsharded where 1 != 1", + "Query": "select 1 + id as foo, weight_string(1 + id) from unsharded", + "Table": "unsharded" } ] } @@ -1347,17 +860,17 @@ { "comment": "systable union query in derived table with constraint on outside (without star projection)", "query": "select * from (select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `COLUMN_NAME` = 'primary'", - "plan": "VT13001: [BUG] did not expect to add group by here" + "plan": "VT13001: [BUG] only weight_string function is expected - got kcu.COLUMN_NAME" }, { "comment": "pushes predicate on both sides of UNION", "query": "select * from (select name, id as foo from user union select 'extra', user_id from user_extra) X where X.foo = 3", - "plan": "VT13001: [BUG] did not expect to add group by here" + "plan": "VT13001: [BUG] do not know how to turn *operators.Distinct into SQL" }, { "comment": "systable union query in derived table with constraint on outside (star projection)", "query": "select * from (select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `constraint_name` = 'primary'", - "plan": "VT13001: [BUG] did not expect to add group by here" + "plan": "VT13001: [BUG] only weight_string function is expected - got kcu.CONSTRAINT_CATALOG" }, { "comment": "unknown columns are OK as long as the whole query is unsharded", @@ -1388,59 +901,55 @@ "QueryType": "SELECT", "Original": "select id, foo, bar from unsharded union select user.intcol, user.textcol2, authoritative.col2 from user join authoritative", "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "GroupBy": "(0|3), (1|4), (2|5)", + "OperatorType": "Distinct", + "Collations": [ + "(0:3)", + "(1:4)", + "(2:5)" + ], "ResultColumns": 3, "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|3) ASC, (1|4) ASC, (2|5) ASC", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select id, foo, bar, weight_string(id), weight_string(foo), weight_string(bar) from unsharded where 1 != 1", + "Query": "select id, foo, bar, weight_string(id), weight_string(foo), weight_string(bar) from unsharded", + "Table": "unsharded" + }, + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,L:1,R:0,L:2,L:3,R:1", + "TableName": "`user`_authoritative", "Inputs": [ { "OperatorType": "Route", - "Variant": "Unsharded", + "Variant": "Scatter", "Keyspace": { - "Name": "main", - "Sharded": false + "Name": "user", + "Sharded": true }, - "FieldQuery": "select id, foo, bar, weight_string(id), weight_string(foo), weight_string(bar) from unsharded where 1 != 1", - "Query": "select id, foo, bar, weight_string(id), weight_string(foo), weight_string(bar) from unsharded", - "Table": "unsharded" + "FieldQuery": "select `user`.intcol, `user`.textcol2, weight_string(`user`.intcol), weight_string(`user`.textcol2) from `user` where 1 != 1", + "Query": "select `user`.intcol, `user`.textcol2, weight_string(`user`.intcol), weight_string(`user`.textcol2) from `user`", + "Table": "`user`" }, { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "L:0,L:1,R:0,L:2,L:3,R:1", - "TableName": "`user`_authoritative", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select `user`.intcol, `user`.textcol2, weight_string(`user`.intcol), weight_string(`user`.textcol2) from `user` where 1 != 1", - "Query": "select `user`.intcol, `user`.textcol2, weight_string(`user`.intcol), weight_string(`user`.textcol2) from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select authoritative.col2, weight_string(authoritative.col2) from authoritative where 1 != 1", - "Query": "select authoritative.col2, weight_string(authoritative.col2) from authoritative", - "Table": "authoritative" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select authoritative.col2, weight_string(authoritative.col2) from authoritative where 1 != 1", + "Query": "select authoritative.col2, weight_string(authoritative.col2) from authoritative", + "Table": "authoritative" } ] } @@ -1458,22 +967,7 @@ { "comment": "UNION ALL with repeating column on the LHS", "query": "select foo, foo, foo from user union all select bar, baz, toto from music", - "v3-plan": { - "QueryType": "SELECT", - "Original": "select foo, foo, foo from user union all select bar, baz, toto from music", - "Instructions": { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select foo, foo, foo from `user` where 1 != 1 union all select bar, baz, toto from music where 1 != 1", - "Query": "select foo, foo, foo from `user` union all select bar, baz, toto from music", - "Table": "`user`" - } - }, - "gen4-plan": { + "plan": { "QueryType": "SELECT", "Original": "select foo, foo, foo from user union all select bar, baz, toto from music", "Instructions": { @@ -1512,22 +1006,7 @@ { "comment": "UNION ALL with repeating column on the RHS", "query": "select bar, baz, toto from music union all select foo, foo, foo from user", - "v3-plan": { - "QueryType": "SELECT", - "Original": "select bar, baz, toto from music union all select foo, foo, foo from user", - "Instructions": { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select bar, baz, toto from music where 1 != 1 union all select foo, foo, foo from `user` where 1 != 1", - "Query": "select bar, baz, toto from music union all select foo, foo, foo from `user`", - "Table": "music" - } - }, - "gen4-plan": { + "plan": { "QueryType": "SELECT", "Original": "select bar, baz, toto from music union all select foo, foo, foo from user", "Instructions": { @@ -1566,83 +1045,69 @@ { "comment": "UNION with repeating column on the LHS", "query": "select foo, foo, foo from user union select bar, baz, toto from music", - "v3-plan": { + "plan": { "QueryType": "SELECT", "Original": "select foo, foo, foo from user union select bar, baz, toto from music", "Instructions": { "OperatorType": "Distinct", + "Collations": [ + "(0:3)", + "(0:0)", + "(0:0)" + ], + "ResultColumns": 3, "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select foo, foo, foo from `user` where 1 != 1", - "Query": "select foo, foo, foo from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select bar, baz, toto from music where 1 != 1", - "Query": "select bar, baz, toto from music", - "Table": "music" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select weight_string(foo) from (select foo, foo, foo from `user` where 1 != 1 union select bar, baz, toto from music where 1 != 1) as dt where 1 != 1", + "Query": "select weight_string(foo) from (select foo, foo, foo from `user` union select bar, baz, toto from music) as dt", + "Table": "`user`, music" } ] - } - }, - "gen4-plan": "VT13001: [BUG] grouping column on wrong index: want: 1, got: 0" + }, + "TablesUsed": [ + "user.music", + "user.user" + ] + } }, { "comment": "UNION with repeating column on the RHS", "query": "select bar, baz, toto from music union select foo, foo, foo from user", - "v3-plan": { + "plan": { "QueryType": "SELECT", "Original": "select bar, baz, toto from music union select foo, foo, foo from user", "Instructions": { "OperatorType": "Distinct", + "Collations": [ + "(0:3)", + "(1:0)", + "(2:1)" + ], + "ResultColumns": 3, "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select bar, baz, toto from music where 1 != 1", - "Query": "select bar, baz, toto from music", - "Table": "music" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select foo, foo, foo from `user` where 1 != 1", - "Query": "select foo, foo, foo from `user`", - "Table": "`user`" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select weight_string(baz), weight_string(toto) from (select bar, baz, toto from music where 1 != 1 union select foo, foo, foo from `user` where 1 != 1) as dt where 1 != 1", + "Query": "select weight_string(baz), weight_string(toto) from (select bar, baz, toto from music union select foo, foo, foo from `user`) as dt", + "Table": "`user`, music" } ] - } - }, - "gen4-plan": "VT12001: unsupported: offsets did not line up for UNION" + }, + "TablesUsed": [ + "user.music", + "user.user" + ] + } } ] From 6a3eeb668ac23b0c4ba10ee39514c9f334766dfb Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Wed, 12 Jul 2023 15:11:16 +0200 Subject: [PATCH 09/44] wip - logic around turning UNION operators to SQL Signed-off-by: Andres Taylor --- .../planbuilder/operators/SQL_builder.go | 66 ++++++++- go/vt/vtgate/planbuilder/operators/ops/op.go | 1 + .../planbuilder/testdata/aggr_cases.json | 31 ++-- .../ddl_cases_no_default_keyspace.json | 16 +- .../testdata/large_union_cases.json | 23 ++- .../planbuilder/testdata/select_cases.json | 48 +++++- .../planbuilder/testdata/union_cases.json | 139 +++++++++++++++++- go/vt/vtgate/semantics/semantic_state.go | 4 +- 8 files changed, 290 insertions(+), 38 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/SQL_builder.go b/go/vt/vtgate/planbuilder/operators/SQL_builder.go index 4226695bd1f..79950cb8cec 100644 --- a/go/vt/vtgate/planbuilder/operators/SQL_builder.go +++ b/go/vt/vtgate/planbuilder/operators/SQL_builder.go @@ -21,6 +21,8 @@ import ( "sort" "strings" + "golang.org/x/exp/slices" + "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" @@ -104,9 +106,35 @@ func (qb *queryBuilder) addGroupBy(original sqlparser.Expr) { sel.GroupBy = append(sel.GroupBy, original) } -func (qb *queryBuilder) addProjection(projection *sqlparser.AliasedExpr) { - sel := qb.sel.(*sqlparser.Select) - sel.SelectExprs = append(sel.SelectExprs, projection) +func (qb *queryBuilder) addProjection(projection *sqlparser.AliasedExpr) error { + switch stmt := qb.sel.(type) { + case *sqlparser.Select: + stmt.SelectExprs = append(stmt.SelectExprs, projection) + return nil + case *sqlparser.Union: + // for UNION we can only check if it's valid, and only if we are dealing with a ColName + column, ok := projection.Expr.(*sqlparser.ColName) + if !ok { + return vterrors.VT12001(fmt.Sprintf("did not find column [%s] on UNION", sqlparser.String(projection))) + } + colName := column.Name.String() + exprs := sqlparser.GetFirstSelect(qb.sel).SelectExprs + offset := slices.IndexFunc(exprs, func(expr sqlparser.SelectExpr) bool { + switch ae := expr.(type) { + case *sqlparser.StarExpr: + return true + case *sqlparser.AliasedExpr: + // When accessing columns on top of a UNION, we fall back to this simple strategy of string comparisons + return ae.ColumnName() == colName + } + return false + }) + if offset == -1 { + return vterrors.VT12001(fmt.Sprintf("did not find column [%s] on UNION", sqlparser.String(projection))) + } + return nil + } + return vterrors.VT13001("switch should be exhaustive") } func (qb *queryBuilder) clearProjections() { @@ -342,6 +370,13 @@ func buildQuery(op ops.Operator, qb *queryBuilder) error { return buildAggregation(op, qb) case *Union: return buildUnion(op, qb) + case *Distinct: + err := buildQuery(op.Source, qb) + if err != nil { + return err + } + qb.sel.MakeDistinct() + return nil default: return vterrors.VT13001(fmt.Sprintf("do not know how to turn %T into SQL", op)) } @@ -361,7 +396,10 @@ func buildAggregation(op *Aggregator, qb *queryBuilder) error { return err } for _, column := range cols { - qb.addProjection(column) + err := qb.addProjection(column) + if err != nil { + return err + } } for _, by := range op.Grouping { @@ -407,7 +445,10 @@ func buildTable(op *Table, qb *queryBuilder) { qb.addPredicate(pred) } for _, name := range op.Columns { - qb.addProjection(&sqlparser.AliasedExpr{Expr: name}) + err := qb.addProjection(&sqlparser.AliasedExpr{Expr: name}) + if err != nil { + return + } } } @@ -422,7 +463,10 @@ func buildProjection(op *Projection, qb *queryBuilder) error { qb.clearProjections() for _, column := range op.Columns { - qb.addProjection(column) + err := qb.addProjection(column) + if err != nil { + return err + } } } @@ -438,7 +482,10 @@ func buildProjection(op *Projection, qb *queryBuilder) error { if !isSel { for _, column := range op.Columns { - qb.addProjection(column) + err := qb.addProjection(column) + if err != nil { + return err + } } } @@ -522,7 +569,10 @@ func buildDerived(op *Horizon, qb *queryBuilder) error { Select: sel, }, nil, op.ColumnAliases) for _, col := range op.Columns { - qb.addProjection(&sqlparser.AliasedExpr{Expr: col}) + err := qb.addProjection(&sqlparser.AliasedExpr{Expr: col}) + if err != nil { + return err + } } return nil } diff --git a/go/vt/vtgate/planbuilder/operators/ops/op.go b/go/vt/vtgate/planbuilder/operators/ops/op.go index baf95f93cd0..8ae713f4c4c 100644 --- a/go/vt/vtgate/planbuilder/operators/ops/op.go +++ b/go/vt/vtgate/planbuilder/operators/ops/op.go @@ -41,6 +41,7 @@ type ( // AddPredicate is used to push predicates. It pushed it as far down as is possible in the tree. // If we encounter a join and the predicate depends on both sides of the join, the predicate will be split into two parts, // where data is fetched from the LHS of the join to be used in the evaluation on the RHS + // TODO: we should remove this and replace it with rewriters AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (Operator, error) // AddColumn tells an operator to also output an additional column specified. diff --git a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json index f24949de3a2..c10fdf96478 100644 --- a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json @@ -3669,27 +3669,20 @@ "ResultColumns": 2, "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC", + "OperatorType": "Limit", + "Count": "INT64(2)", "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(2)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select val1, 1, weight_string(val1), weight_string(val1) from (select id, val1 from `user` where 1 != 1) as x where 1 != 1", - "OrderBy": "(0|3) ASC", - "Query": "select val1, 1, weight_string(val1), weight_string(val1) from (select id, val1 from `user` where val2 < 4) as x order by val1 asc limit :__upper_limit", - "Table": "`user`" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select val1, 1, weight_string(val1) from (select id, val1 from `user` where 1 != 1) as x where 1 != 1", + "OrderBy": "(0|2) ASC", + "Query": "select val1, 1, weight_string(val1) from (select id, val1 from `user` where val2 < 4) as x order by val1 asc limit :__upper_limit", + "Table": "`user`" } ] } diff --git a/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json b/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json index 8fe0b4e838b..9df66921fd5 100644 --- a/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json +++ b/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json @@ -501,7 +501,21 @@ { "comment": "create view with union with the same target shard", "query": "create view user.view_a as select * from music where user_id = 1 union select * from user where id = 1", - "plan": "VT13001: [BUG] do not know how to turn *operators.Distinct into SQL" + "plan": { + "QueryType": "DDL", + "Original": "create view user.view_a as select * from music where user_id = 1 union select * from user where id = 1", + "Instructions": { + "OperatorType": "DDL", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "Query": "create view view_a as select * from music where user_id = 1 union select * from `user` where id = 1" + }, + "TablesUsed": [ + "user.view_a" + ] + } }, { "comment": "create view with testing SingleRow Projection", diff --git a/go/vt/vtgate/planbuilder/testdata/large_union_cases.json b/go/vt/vtgate/planbuilder/testdata/large_union_cases.json index fde34dfe5fa..cc648220d27 100644 --- a/go/vt/vtgate/planbuilder/testdata/large_union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/large_union_cases.json @@ -2,6 +2,27 @@ { "comment": "this testcase breaks goland, so it lives on its own file", "query": "(SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270698330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270699497 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270703806 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270707364 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270714657 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270721330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270812079 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271011532 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271034164 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271034177 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271066849 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271098740 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271355000 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271924504 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272086055 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272127855 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272191137 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272468271 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270644941 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270650576 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270652906 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270660650 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270670201 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270698330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270699497 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270707364 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271799956 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271799956 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270644941 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270649256 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270653671 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270670201 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270717223 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270720898 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271346411 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271352121 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271354908 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271367516 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271472522 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271821733 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272068709 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272127855 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272191137 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272244005 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272468271 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272244005 ORDER BY created_at ASC, id ASC LIMIT 11)", - "plan": "VT13001: [BUG] do not know how to turn *operators.Distinct into SQL" + "plan": { + "QueryType": "SELECT", + "Original": "(SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270698330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270699497 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270703806 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270707364 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270714657 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270721330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270812079 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271011532 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271034164 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271034177 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271066849 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271098740 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271355000 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271924504 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272086055 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272127855 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272191137 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272468271 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270644941 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270650576 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270652906 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270660650 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270670201 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270698330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270699497 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270707364 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271799956 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271799956 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270644941 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270649256 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270653671 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270670201 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270717223 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270720898 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271346411 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271352121 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271354908 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271367516 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271472522 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271821733 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272068709 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272127855 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272191137 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272244005 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272468271 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272244005 ORDER BY created_at ASC, id ASC LIMIT 11)", + "Instructions": { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "(select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1)", + "Query": "(select content, user_id from music where user_id = 1270698330 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270699497 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270703806 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270707364 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270714657 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270721330 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270812079 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271011532 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271034164 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271034177 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271066849 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271098740 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271355000 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271639345 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271914117 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271924504 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272086055 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272127855 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272191137 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272468271 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270637436 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270644941 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270650576 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270652906 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270660650 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270670201 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270698330 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270699497 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270707364 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271365691 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271799956 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271914117 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270637436 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271799956 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270637436 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271639345 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270644941 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270649256 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270653671 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270670201 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270717223 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270720898 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270982590 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271346411 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271352121 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271354908 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271365691 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271367516 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271472522 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271607757 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271639345 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271821733 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271914117 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272068709 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272127855 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272191137 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272244005 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272468271 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270982590 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271365691 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271607757 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270982590 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271365691 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271607757 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272244005 order by created_at asc, id asc limit 11)", + "Table": "music", + "Values": [ + "INT64(1272244005)" + ], + "Vindex": "user_index" + }, + "TablesUsed": [ + "user.music" + ] + } } ] diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.json b/go/vt/vtgate/planbuilder/testdata/select_cases.json index e7615789b92..6f849d54ba1 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.json @@ -1360,12 +1360,56 @@ { "comment": "union with the same target shard", "query": "select * from music where user_id = 1 union select * from user where id = 1", - "plan": "VT13001: [BUG] do not know how to turn *operators.Distinct into SQL" + "plan": { + "QueryType": "SELECT", + "Original": "select * from music where user_id = 1 union select * from user where id = 1", + "Instructions": { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select * from music where 1 != 1 union select * from `user` where 1 != 1", + "Query": "select * from music where user_id = 1 union select * from `user` where id = 1", + "Table": "`user`, music", + "Values": [ + "INT64(1)" + ], + "Vindex": "user_index" + }, + "TablesUsed": [ + "user.music", + "user.user" + ] + } }, { "comment": "union with the same target shard last_insert_id", "query": "select *, last_insert_id() from music where user_id = 1 union select * from user where id = 1", - "plan": "VT13001: [BUG] do not know how to turn *operators.Distinct into SQL" + "plan": { + "QueryType": "SELECT", + "Original": "select *, last_insert_id() from music where user_id = 1 union select * from user where id = 1", + "Instructions": { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select *, :__lastInsertId as `last_insert_id()` from music where 1 != 1 union select * from `user` where 1 != 1", + "Query": "select *, :__lastInsertId as `last_insert_id()` from music where user_id = 1 union select * from `user` where id = 1", + "Table": "`user`, music", + "Values": [ + "INT64(1)" + ], + "Vindex": "user_index" + }, + "TablesUsed": [ + "user.music", + "user.user" + ] + } }, { "comment": "unsharded union in derived table", diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index fe0eadf0496..38e3e13cd97 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -178,7 +178,44 @@ { "comment": "union all on scatter and single route", "query": "select id from user where id = 1 union select id from user where id = 1 union all select id from user", - "plan": "VT13001: [BUG] do not know how to turn *operators.Distinct into SQL" + "plan": { + "QueryType": "SELECT", + "Original": "select id from user where id = 1 union select id from user where id = 1 union all select id from user", + "Instructions": { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from `user` where 1 != 1 union select id from `user` where 1 != 1", + "Query": "select id from `user` where id = 1 union select id from `user` where id = 1", + "Table": "`user`", + "Values": [ + "INT64(1)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from `user` where 1 != 1", + "Query": "select id from `user`", + "Table": "`user`" + } + ] + }, + "TablesUsed": [ + "user.user" + ] + } }, { "comment": "union of information_schema with normal table", @@ -299,12 +336,55 @@ { "comment": "union with the same target shard because of vindex", "query": "select * from music where id = 1 union select * from user where id = 1", - "plan": "VT13001: [BUG] do not know how to turn *operators.Distinct into SQL" + "plan": { + "QueryType": "SELECT", + "Original": "select * from music where id = 1 union select * from user where id = 1", + "Instructions": { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select * from music where 1 != 1 union select * from `user` where 1 != 1", + "Query": "select * from music where id = 1 union select * from `user` where id = 1", + "Table": "`user`, music", + "Values": [ + "INT64(1)" + ], + "Vindex": "user_index" + }, + "TablesUsed": [ + "user.music", + "user.user" + ] + } }, { "comment": "union with different target shards", "query": "select 1 from music where id = 1 union select 1 from music where id = 2", - "plan": "VT13001: [BUG] do not know how to turn *operators.Distinct into SQL" + "plan": { + "QueryType": "SELECT", + "Original": "select 1 from music where id = 1 union select 1 from music where id = 2", + "Instructions": { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 1 from music where 1 != 1 union select 1 from music where 1 != 1", + "Query": "select 1 from music where id = 1 union select 1 from music where id = 2", + "Table": "music", + "Values": [ + "INT64(2)" + ], + "Vindex": "music_user_map" + }, + "TablesUsed": [ + "user.music" + ] + } }, { "comment": "multiple select statement have inner order by with union - TODO (systay) no need to send down ORDER BY if we are going to loose it with UNION DISTINCT", @@ -340,7 +420,34 @@ { "comment": "multiple unions", "query": "select 1 union select null union select 1.0 union select '1' union select 2 union select 2.0 from user", - "plan": "VT13001: [BUG] do not know how to turn *operators.Distinct into SQL" + "plan": { + "QueryType": "SELECT", + "Original": "select 1 union select null union select 1.0 union select '1' union select 2 union select 2.0 from user", + "Instructions": { + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], + "ResultColumns": 1, + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select `1`, weight_string(`1`) from (select 1 from dual where 1 != 1 union select null from dual where 1 != 1 union select 1.0 from dual where 1 != 1 union select '1' from dual where 1 != 1 union select 2 from dual where 1 != 1 union select 2.0 from `user` where 1 != 1) as dt where 1 != 1", + "Query": "select `1`, weight_string(`1`) from (select 1 from dual union select null from dual union select 1.0 from dual union select '1' from dual union select 2 from dual union select 2.0 from `user`) as dt", + "Table": "`user`, dual" + } + ] + }, + "TablesUsed": [ + "main.dual", + "user.user" + ] + } }, { "comment": "union distinct between a scatter query and a join (other side)", @@ -865,7 +972,29 @@ { "comment": "pushes predicate on both sides of UNION", "query": "select * from (select name, id as foo from user union select 'extra', user_id from user_extra) X where X.foo = 3", - "plan": "VT13001: [BUG] do not know how to turn *operators.Distinct into SQL" + "plan": { + "QueryType": "SELECT", + "Original": "select * from (select name, id as foo from user union select 'extra', user_id from user_extra) X where X.foo = 3", + "Instructions": { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select `name`, id as foo from `user` where 1 != 1 union select 'extra', user_id from user_extra where 1 != 1", + "Query": "select `name`, id as foo from `user` where id = 3 union select 'extra', user_id from user_extra where user_id = 3", + "Table": "`user`, user_extra", + "Values": [ + "INT64(3)" + ], + "Vindex": "user_index" + }, + "TablesUsed": [ + "user.user", + "user.user_extra" + ] + } }, { "comment": "systable union query in derived table with constraint on outside (star projection)", diff --git a/go/vt/vtgate/semantics/semantic_state.go b/go/vt/vtgate/semantics/semantic_state.go index 3058f0608cc..7adcd4598a4 100644 --- a/go/vt/vtgate/semantics/semantic_state.go +++ b/go/vt/vtgate/semantics/semantic_state.go @@ -447,8 +447,8 @@ func (st *SemTable) EqualsExprWithDeps(a, b sqlparser.Expr) bool { if !eq { return false } - adeps := st.DirectDeps(a) - bdeps := st.DirectDeps(b) + adeps := st.RecursiveDeps(a) + bdeps := st.RecursiveDeps(b) if adeps.IsEmpty() || bdeps.IsEmpty() || adeps == bdeps { return true } From 616bfbe8bf770b82afd9724de1a0f269cfd9bf7b Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Wed, 12 Jul 2023 17:13:31 +0200 Subject: [PATCH 10/44] logic around DISTINCT pushing Signed-off-by: Andres Taylor --- .../planbuilder/operators/SQL_builder.go | 62 +++++--- .../vtgate/planbuilder/operators/distinct.go | 23 ++- .../operators/horizon_expanding.go | 5 +- .../planbuilder/operators/horizon_planning.go | 66 +++++--- .../planbuilder/operators/offset_planning.go | 6 +- go/vt/vtgate/planbuilder/operators/route.go | 42 ----- .../planbuilder/testdata/aggr_cases.json | 8 +- .../testdata/info_schema57_cases.json | 8 +- .../testdata/info_schema80_cases.json | 8 +- .../planbuilder/testdata/oltp_cases.json | 2 +- .../testdata/postprocess_cases.json | 8 +- .../planbuilder/testdata/union_cases.json | 143 ++++++++++-------- 12 files changed, 215 insertions(+), 166 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/SQL_builder.go b/go/vt/vtgate/planbuilder/operators/SQL_builder.go index 79950cb8cec..9b63082d4a2 100644 --- a/go/vt/vtgate/planbuilder/operators/SQL_builder.go +++ b/go/vt/vtgate/planbuilder/operators/SQL_builder.go @@ -112,31 +112,53 @@ func (qb *queryBuilder) addProjection(projection *sqlparser.AliasedExpr) error { stmt.SelectExprs = append(stmt.SelectExprs, projection) return nil case *sqlparser.Union: - // for UNION we can only check if it's valid, and only if we are dealing with a ColName - column, ok := projection.Expr.(*sqlparser.ColName) - if !ok { - return vterrors.VT12001(fmt.Sprintf("did not find column [%s] on UNION", sqlparser.String(projection))) - } - colName := column.Name.String() - exprs := sqlparser.GetFirstSelect(qb.sel).SelectExprs - offset := slices.IndexFunc(exprs, func(expr sqlparser.SelectExpr) bool { - switch ae := expr.(type) { - case *sqlparser.StarExpr: - return true - case *sqlparser.AliasedExpr: - // When accessing columns on top of a UNION, we fall back to this simple strategy of string comparisons - return ae.ColumnName() == colName - } - return false - }) - if offset == -1 { - return vterrors.VT12001(fmt.Sprintf("did not find column [%s] on UNION", sqlparser.String(projection))) + switch expr := projection.Expr.(type) { + case *sqlparser.ColName: + return checkUnionColumnByName(expr, qb.sel) + default: + // if there is more than just column names, we'll just push the UNION + // inside a derived table and then recurse into this method again + qb.pushUnionInsideDerived() + return qb.addProjection(projection) } - return nil + } return vterrors.VT13001("switch should be exhaustive") } +func (qb *queryBuilder) pushUnionInsideDerived() { + dt := &sqlparser.DerivedTable{ + Lateral: false, + Select: qb.sel, + } + qb.sel = &sqlparser.Select{ + From: []sqlparser.TableExpr{&sqlparser.AliasedTableExpr{ + Expr: dt, + As: sqlparser.NewIdentifierCS("dt"), + }}, + SelectExprs: sqlparser.CloneSelectExprs(sqlparser.GetFirstSelect(qb.sel).SelectExprs), + } +} + +func checkUnionColumnByName(column *sqlparser.ColName, sel sqlparser.SelectStatement) error { + colName := column.Name.String() + exprs := sqlparser.GetFirstSelect(sel).SelectExprs + offset := slices.IndexFunc(exprs, func(expr sqlparser.SelectExpr) bool { + switch ae := expr.(type) { + case *sqlparser.StarExpr: + return true + case *sqlparser.AliasedExpr: + // When accessing columns on top of a UNION, we fall back to this simple strategy of string comparisons + return ae.ColumnName() == colName + } + return false + }) + if offset == -1 { + return vterrors.VT12001(fmt.Sprintf("did not find column [%s] on UNION", sqlparser.String(column))) + } + return nil +} + func (qb *queryBuilder) clearProjections() { sel, isSel := qb.sel.(*sqlparser.Select) if !isSel { diff --git a/go/vt/vtgate/planbuilder/operators/distinct.go b/go/vt/vtgate/planbuilder/operators/distinct.go index b3a20afb0ea..23185fcf8ac 100644 --- a/go/vt/vtgate/planbuilder/operators/distinct.go +++ b/go/vt/vtgate/planbuilder/operators/distinct.go @@ -22,14 +22,18 @@ import ( "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/engine" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" + "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/rewrite" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" ) type ( Distinct struct { - Source ops.Operator - QP *QueryProjection - Pushed bool + // When splitting a distinct up, we only need one total DISTINCT at the route, any other + // intermediate DISTINCTs while we are pushing down can simply be removed + Original bool + Source ops.Operator + QP *QueryProjection + Pushed bool // When offset planning, we'll fill in this field Columns []engine.CheckCol @@ -76,6 +80,7 @@ func (d *Distinct) planOffsets(ctx *plancontext.PlanningContext) error { func (d *Distinct) Clone(inputs []ops.Operator) ops.Operator { return &Distinct{ + Original: d.Original, Source: inputs[0], Columns: slices.Clone(d.Columns), QP: d.QP, @@ -119,6 +124,9 @@ func (d *Distinct) GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.S } func (d *Distinct) ShortDescription() string { + if d.Original { + return "ORG" + } return "" } @@ -129,3 +137,12 @@ func (d *Distinct) GetOrdering() ([]ops.OrderBy, error) { func (d *Distinct) setTruncateColumnCount(offset int) { d.Truncate = offset } + +func (d *Distinct) Compact(*plancontext.PlanningContext) (ops.Operator, *rewrite.ApplyResult, error) { + other, ok := d.Source.(*Distinct) + if !ok { + return d, rewrite.SameTree, nil + } + d.Source = other.Source + return d, rewrite.NewTree("removed double distinct", other), nil +} diff --git a/go/vt/vtgate/planbuilder/operators/horizon_expanding.go b/go/vt/vtgate/planbuilder/operators/horizon_expanding.go index ce615e580ed..265dc337803 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_expanding.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_expanding.go @@ -76,8 +76,9 @@ func expandSelectHorizon(ctx *plancontext.PlanningContext, horizon *Horizon, sel if qp.NeedsDistinct() { op = &Distinct{ - Source: op, - QP: qp, + Original: true, + Source: op, + QP: qp, } } diff --git a/go/vt/vtgate/planbuilder/operators/horizon_planning.go b/go/vt/vtgate/planbuilder/operators/horizon_planning.go index 8083e055a4c..d78c39ec89d 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_planning.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_planning.go @@ -104,6 +104,9 @@ func planHorizons(ctx *plancontext.PlanningContext, root ops.Operator) (op ops.O if err != nil { return nil, err } + if op == nil { + panic("got nil op back") + } } if rewrite.DebugOperatorTree { fmt.Printf("PHASE: %s\n", phase.Name) @@ -112,11 +115,17 @@ func planHorizons(ctx *plancontext.PlanningContext, root ops.Operator) (op ops.O if err != nil { return nil, err } + if op == nil { + panic("got nil op back") + } op, err = compact(ctx, op) if err != nil { return nil, err } + if op == nil { + panic("got nil op back") + } } return addGroupByOnRHSOfJoin(op) @@ -592,38 +601,50 @@ func tryPushingDownDistinct(ctx *plancontext.PlanningContext, in *Distinct) (ops if in.Pushed { return in, rewrite.SameTree, nil } + in.Pushed = true switch src := in.Source.(type) { case *Route: - if src.IsSingleShard() { + if src.IsSingleShard() || !in.Original { return rewrite.Swap(in, src, "push distinct under route") } + if isDistinct(src.Source) { + return in, rewrite.SameTree, nil + } + src.Source = &Distinct{Source: src.Source} + + return in, rewrite.NewTree("added distinct under route - kept original", src), nil case *Distinct: return src, rewrite.NewTree("removed double distinct", src), nil case *Aggregator: return in, rewrite.SameTree, nil - } + case *Union: + for i := range src.Sources { + src.Sources[i] = &Distinct{Source: src.Sources[i]} + } + return in, rewrite.NewTree("pushed down DISTINCT under UNION", src), nil + case *ApplyJoin: + src.LHS = &Distinct{Source: src.LHS} + src.RHS = &Distinct{Source: src.RHS} - // TODO: tell the inputs from here we only need distinct inputs - in.Pushed = true + if in.Original { + return in, rewrite.NewTree("pushed distinct under join - kept original", in.Source), nil + } + + return in.Source, rewrite.NewTree("pushed distinct under join", in.Source), nil + } return in, rewrite.SameTree, nil +} - //cols, err := in.Source.GetColumns(ctx) - //if err != nil { - // return nil, nil, err - //} - // - //aggr := &Aggregator{ - // Source: in.Source, - // QP: in.QP, - // Original: true, - //} - // - //for _, col := range cols { - // aggr.addColumnWithoutPushing(col, true) - //} - // - //return aggr, rewrite.NewTree("replace distinct with aggregator", in), nil +func isDistinct(op ops.Operator) bool { + switch op := op.(type) { + case *Distinct: + return true + case *Union: + return op.distinct + default: + return false + } } func tryPushDownUnion(ctx *plancontext.PlanningContext, op *Union) (ops.Operator, *rewrite.ApplyResult, error) { @@ -635,7 +656,10 @@ func tryPushDownUnion(ctx *plancontext.PlanningContext, op *Union) (ops.Operator if len(sources) == 1 { result := sources[0] if op.distinct { - result = &Distinct{Source: result} + result = &Distinct{ + Source: result, + Original: true, + } } return result, rewrite.NewTree("pushed union under route", op), nil diff --git a/go/vt/vtgate/planbuilder/operators/offset_planning.go b/go/vt/vtgate/planbuilder/operators/offset_planning.go index e7477f94aac..bf7c352c6a9 100644 --- a/go/vt/vtgate/planbuilder/operators/offset_planning.go +++ b/go/vt/vtgate/planbuilder/operators/offset_planning.go @@ -172,7 +172,11 @@ func pullDistinctFromUNION(root ops.Operator) (ops.Operator, error) { union.distinct = false - return &Distinct{Source: union}, rewrite.NewTree("pulled out DISTINCT from union", union), nil + distinct := &Distinct{ + Original: true, + Source: union, + } + return distinct, rewrite.NewTree("pulled out DISTINCT from union", union), nil } return rewrite.TopDown(root, TableID, visitor, stopAtRoute) diff --git a/go/vt/vtgate/planbuilder/operators/route.go b/go/vt/vtgate/planbuilder/operators/route.go index 9383d8bdbd8..c5b31e9d0fb 100644 --- a/go/vt/vtgate/planbuilder/operators/route.go +++ b/go/vt/vtgate/planbuilder/operators/route.go @@ -616,48 +616,6 @@ func addColumnToInput(ctx *plancontext.PlanningContext, operator ops.Operator, e TableID: &tableID, Alias: "dt", }, true, len(op.columns) - //wsExpr, isWeightString := expr.Expr.(*sqlparser.WeightStringFuncExpr) - //if !isWeightString { - // return false, 0, vterrors.VT12001("Pushing columns in union that isn't a weight string") - //} - //columnOffset := -1 - //for idx, column := range op.columns { - // if ctx.SemTable.EqualsExpr(column.Expr, wsExpr.Expr) { - // columnOffset = idx - // break - // } - //} - //if columnOffset == -1 { - // return false, 0, vterrors.VT13001("Couldn't find the offset of the weight string argument in Union") - //} - // - //idx := -1 - //for i, source := range op.Sources { - // cols, err := source.GetColumns(ctx) - // if err != nil { - // return false, 0, err - // } - // ok, offset, err := addColumnToInput(ctx, source, aeWrap(weightStringFor(cols[columnOffset].Expr)), false) - // if err != nil { - // return ok, offset, err - // } - // if !ok { - // if i == 0 { - // return false, 0, nil - // } - // // if we succeeded on one input, and failed later, we are kind of screwed - // return false, 0, vterrors.VT12001("could not push down to all inputs") - // } - // if idx == -1 { - // idx = offset - // continue - // } - // if idx != offset { - // return false, 0, vterrors.VT12001("union columns did not line up") - // } - //} - //return true, idx, nil - default: return op, false, 0 } diff --git a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json index c10fdf96478..f69cca52c72 100644 --- a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json @@ -383,7 +383,7 @@ "Sharded": true }, "FieldQuery": "select col from `user` where 1 != 1", - "Query": "select col from `user`", + "Query": "select distinct col from `user`", "Table": "`user`" } ] @@ -1305,7 +1305,7 @@ "Sharded": true }, "FieldQuery": "select col1, col2, weight_string(col1), weight_string(col2) from `user` where 1 != 1", - "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user`", + "Query": "select distinct col1, col2, weight_string(col1), weight_string(col2) from `user`", "Table": "`user`" } ] @@ -4891,7 +4891,7 @@ "Sharded": true }, "FieldQuery": "select a, b as a, weight_string(b) from `user` where 1 != 1", - "Query": "select a, b as a, weight_string(b) from `user`", + "Query": "select distinct a, b as a, weight_string(b) from `user`", "Table": "`user`" } ] @@ -4922,7 +4922,7 @@ "Sharded": true }, "FieldQuery": "select a + 1, weight_string(a + 1) from `user` where 1 != 1", - "Query": "select a + 1, weight_string(a + 1) from `user`", + "Query": "select distinct a + 1, weight_string(a + 1) from `user`", "Table": "`user`" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json index 7c7c49b6ae8..d47c92400b9 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json @@ -118,7 +118,7 @@ "Sharded": false }, "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns` where 1 != 1", - "Query": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns`", + "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns`", "Table": "information_schema.`columns`" }, { @@ -129,7 +129,7 @@ "Sharded": false }, "FieldQuery": "select table_schema, weight_string(table_schema) from information_schema.`tables` where 1 != 1", - "Query": "select table_schema, weight_string(table_schema) from information_schema.`tables`", + "Query": "select distinct table_schema, weight_string(table_schema) from information_schema.`tables`", "Table": "information_schema.`tables`" } ] @@ -182,7 +182,7 @@ "Sharded": false }, "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where 1 != 1", - "Query": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "Query": "select distinct TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", "SysTableTableSchema": "[VARCHAR(\"user\")]", "Table": "information_schema.`tables`" }, @@ -194,7 +194,7 @@ "Sharded": false }, "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where 1 != 1", - "Query": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "Query": "select distinct TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", "SysTableTableSchema": "[VARCHAR(\"main\")]", "Table": "information_schema.`tables`" } diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json index d326e98830a..d2fb99b4634 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json @@ -118,7 +118,7 @@ "Sharded": false }, "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns` where 1 != 1", - "Query": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns`", + "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns`", "Table": "information_schema.`columns`" }, { @@ -129,7 +129,7 @@ "Sharded": false }, "FieldQuery": "select table_schema, weight_string(table_schema) from information_schema.`tables` where 1 != 1", - "Query": "select table_schema, weight_string(table_schema) from information_schema.`tables`", + "Query": "select distinct table_schema, weight_string(table_schema) from information_schema.`tables`", "Table": "information_schema.`tables`" } ] @@ -182,7 +182,7 @@ "Sharded": false }, "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where 1 != 1", - "Query": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "Query": "select distinct TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", "SysTableTableSchema": "[VARCHAR(\"user\")]", "Table": "information_schema.`tables`" }, @@ -194,7 +194,7 @@ "Sharded": false }, "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where 1 != 1", - "Query": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "Query": "select distinct TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", "SysTableTableSchema": "[VARCHAR(\"main\")]", "Table": "information_schema.`tables`" } diff --git a/go/vt/vtgate/planbuilder/testdata/oltp_cases.json b/go/vt/vtgate/planbuilder/testdata/oltp_cases.json index 5708628eca9..810f58b4ea9 100644 --- a/go/vt/vtgate/planbuilder/testdata/oltp_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/oltp_cases.json @@ -124,7 +124,7 @@ "Sharded": true }, "FieldQuery": "select c from sbtest30 where 1 != 1", - "Query": "select c from sbtest30 where id between 1 and 10", + "Query": "select distinct c from sbtest30 where id between 1 and 10", "Table": "sbtest30" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json index 40ac155f0ae..cb87e68b01e 100644 --- a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json @@ -1718,7 +1718,7 @@ "Sharded": true }, "FieldQuery": "select `user`.a, weight_string(`user`.a) from `user` where 1 != 1", - "Query": "select `user`.a, weight_string(`user`.a) from `user`", + "Query": "select distinct `user`.a, weight_string(`user`.a) from `user`", "Table": "`user`" }, { @@ -1729,7 +1729,7 @@ "Sharded": true }, "FieldQuery": "select 1 from user_extra where 1 != 1", - "Query": "select 1 from user_extra", + "Query": "select distinct 1 from user_extra", "Table": "user_extra" } ] @@ -1764,7 +1764,7 @@ "Sharded": true }, "FieldQuery": "select a as c, a, weight_string(a) from `user` where 1 != 1", - "Query": "select a as c, a, weight_string(a) from `user`", + "Query": "select distinct a as c, a, weight_string(a) from `user`", "Table": "`user`" } ] @@ -1796,7 +1796,7 @@ "Sharded": true }, "FieldQuery": "select a, a, weight_string(a) from `user` where 1 != 1", - "Query": "select a, a, weight_string(a) from `user`", + "Query": "select distinct a, a, weight_string(a) from `user`", "Table": "`user`" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 38e3e13cd97..62063f5a74d 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -241,7 +241,7 @@ "Sharded": false }, "FieldQuery": "select CHARACTER_SET_NAME, weight_string(CHARACTER_SET_NAME) from information_schema.CHARACTER_SETS where 1 != 1", - "Query": "select CHARACTER_SET_NAME, weight_string(CHARACTER_SET_NAME) from information_schema.CHARACTER_SETS", + "Query": "select distinct CHARACTER_SET_NAME, weight_string(CHARACTER_SET_NAME) from information_schema.CHARACTER_SETS", "Table": "information_schema.CHARACTER_SETS" }, { @@ -252,7 +252,7 @@ "Sharded": false }, "FieldQuery": "select user_name, weight_string(user_name) from unsharded where 1 != 1", - "Query": "select user_name, weight_string(user_name) from unsharded", + "Query": "select distinct user_name, weight_string(user_name) from unsharded", "Table": "unsharded" } ] @@ -309,7 +309,7 @@ "Sharded": false }, "FieldQuery": "select 1, weight_string(1) from dual where 1 != 1", - "Query": "select 1, weight_string(1) from dual", + "Query": "select distinct 1, weight_string(1) from dual", "Table": "dual" } ] @@ -480,7 +480,7 @@ "Sharded": true }, "FieldQuery": "select `user`.id, `user`.`name`, weight_string(`user`.id), weight_string(`user`.`name`) from `user` where 1 != 1", - "Query": "select `user`.id, `user`.`name`, weight_string(`user`.id), weight_string(`user`.`name`) from `user`", + "Query": "select distinct `user`.id, `user`.`name`, weight_string(`user`.id), weight_string(`user`.`name`) from `user`", "Table": "`user`" }, { @@ -491,7 +491,7 @@ "Sharded": true }, "FieldQuery": "select 1 from user_extra where 1 != 1", - "Query": "select 1 from user_extra where user_extra.extra = 'asdf'", + "Query": "select distinct 1 from user_extra where user_extra.extra = 'asdf'", "Table": "user_extra" } ] @@ -504,7 +504,7 @@ "Sharded": true }, "FieldQuery": "select 'b', 'c', weight_string('b'), weight_string('c') from `user` where 1 != 1", - "Query": "select 'b', 'c', weight_string('b'), weight_string('c') from `user`", + "Query": "select distinct 'b', 'c', weight_string('b'), weight_string('c') from `user`", "Table": "`user`" } ] @@ -542,7 +542,7 @@ "Sharded": true }, "FieldQuery": "select 'b', 'c', weight_string('b'), weight_string('c') from `user` where 1 != 1", - "Query": "select 'b', 'c', weight_string('b'), weight_string('c') from `user`", + "Query": "select distinct 'b', 'c', weight_string('b'), weight_string('c') from `user`", "Table": "`user`" }, { @@ -559,7 +559,7 @@ "Sharded": true }, "FieldQuery": "select `user`.id, `user`.`name`, weight_string(`user`.id), weight_string(`user`.`name`) from `user` where 1 != 1", - "Query": "select `user`.id, `user`.`name`, weight_string(`user`.id), weight_string(`user`.`name`) from `user`", + "Query": "select distinct `user`.id, `user`.`name`, weight_string(`user`.id), weight_string(`user`.`name`) from `user`", "Table": "`user`" }, { @@ -570,7 +570,7 @@ "Sharded": true }, "FieldQuery": "select 1 from user_extra where 1 != 1", - "Query": "select 1 from user_extra where user_extra.extra = 'asdf'", + "Query": "select distinct 1 from user_extra where user_extra.extra = 'asdf'", "Table": "user_extra" } ] @@ -602,38 +602,56 @@ "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Scalar", - "Aggregates": "sum_count_star(0) AS s, any_value(1)", + "OperatorType": "Distinct", + "Collations": [ + "0", + "(1:2)" + ], "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select count(*) as s, weight_string(count(*)) from `user` where 1 != 1", - "Query": "select count(*) as s, weight_string(count(*)) from `user`", - "Table": "`user`" + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "sum_count_star(0) AS s, any_value(1), any_value(2)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select count(*) as s, weight_string(count(*)), weight_string(weight_string(count(*))) from `user` where 1 != 1", + "Query": "select count(*) as s, weight_string(count(*)), weight_string(weight_string(count(*))) from `user`", + "Table": "`user`" + } + ] } ] }, { - "OperatorType": "Aggregate", - "Variant": "Scalar", - "Aggregates": "sum_count_star(0) AS s, any_value(1)", + "OperatorType": "Distinct", + "Collations": [ + "0", + "(1:2)" + ], "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select count(*) as s, weight_string(count(*)) from music where 1 != 1", - "Query": "select count(*) as s, weight_string(count(*)) from music", - "Table": "music" + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "sum_count_star(0) AS s, any_value(1), any_value(2)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select count(*) as s, weight_string(count(*)), weight_string(weight_string(count(*))) from music where 1 != 1", + "Query": "select count(*) as s, weight_string(count(*)), weight_string(weight_string(count(*))) from music", + "Table": "music" + } + ] } ] } @@ -669,27 +687,32 @@ "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|1) ASC", + "OperatorType": "Distinct", "Inputs": [ { - "OperatorType": "Distinct", - "Collations": [ - "(0:1)", - "(1:2)" - ], + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|1) ASC", "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id), weight_string(weight_string(id)) from (select id from `user` where 1 != 1 union select id from music where 1 != 1) as dt where 1 != 1", - "Query": "select id, weight_string(id), weight_string(weight_string(id)) from (select id from `user` union select id from music) as dt", - "Table": "`user`, music" + "OperatorType": "Distinct", + "Collations": [ + "(0:1)", + "(1:2)" + ], + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id), weight_string(weight_string(id)) from (select id from `user` where 1 != 1 union select id from music where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id), weight_string(weight_string(id)) from (select id from `user` union select id from music) as dt", + "Table": "`user`, music" + } + ] } ] } @@ -703,7 +726,7 @@ "Sharded": false }, "FieldQuery": "select 1, weight_string(1) from unsharded where 1 != 1", - "Query": "select 1, weight_string(1) from unsharded", + "Query": "select distinct 1, weight_string(1) from unsharded", "Table": "unsharded" } ] @@ -801,7 +824,7 @@ "Sharded": false }, "FieldQuery": "select col, weight_string(col) from unsharded where 1 != 1", - "Query": "select col, weight_string(col) from unsharded", + "Query": "select distinct col, weight_string(col) from unsharded", "Table": "unsharded" }, { @@ -812,7 +835,7 @@ "Sharded": true }, "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "Query": "select id, weight_string(id) from `user`", + "Query": "select distinct id, weight_string(id) from `user`", "Table": "`user`" }, { @@ -823,7 +846,7 @@ "Sharded": false }, "FieldQuery": "select col2, weight_string(col2) from unsharded where 1 != 1", - "Query": "select col2, weight_string(col2) from unsharded", + "Query": "select distinct col2, weight_string(col2) from unsharded", "Table": "unsharded" }, { @@ -834,7 +857,7 @@ "Sharded": true }, "FieldQuery": "select col, weight_string(col) from user_extra where 1 != 1", - "Query": "select col, weight_string(col) from user_extra", + "Query": "select distinct col, weight_string(col) from user_extra", "Table": "user_extra" } ] @@ -938,7 +961,7 @@ "Sharded": true }, "FieldQuery": "select id + 42 as foo, weight_string(id + 42) from `user` where 1 != 1", - "Query": "select id + 42 as foo, weight_string(id + 42) from `user`", + "Query": "select distinct id + 42 as foo, weight_string(id + 42) from `user`", "Table": "`user`" }, { @@ -949,7 +972,7 @@ "Sharded": false }, "FieldQuery": "select 1 + id as foo, weight_string(1 + id) from unsharded where 1 != 1", - "Query": "select 1 + id as foo, weight_string(1 + id) from unsharded", + "Query": "select distinct 1 + id as foo, weight_string(1 + id) from unsharded", "Table": "unsharded" } ] @@ -1049,7 +1072,7 @@ "Sharded": false }, "FieldQuery": "select id, foo, bar, weight_string(id), weight_string(foo), weight_string(bar) from unsharded where 1 != 1", - "Query": "select id, foo, bar, weight_string(id), weight_string(foo), weight_string(bar) from unsharded", + "Query": "select distinct id, foo, bar, weight_string(id), weight_string(foo), weight_string(bar) from unsharded", "Table": "unsharded" }, { @@ -1066,7 +1089,7 @@ "Sharded": true }, "FieldQuery": "select `user`.intcol, `user`.textcol2, weight_string(`user`.intcol), weight_string(`user`.textcol2) from `user` where 1 != 1", - "Query": "select `user`.intcol, `user`.textcol2, weight_string(`user`.intcol), weight_string(`user`.textcol2) from `user`", + "Query": "select distinct `user`.intcol, `user`.textcol2, weight_string(`user`.intcol), weight_string(`user`.textcol2) from `user`", "Table": "`user`" }, { @@ -1077,7 +1100,7 @@ "Sharded": true }, "FieldQuery": "select authoritative.col2, weight_string(authoritative.col2) from authoritative where 1 != 1", - "Query": "select authoritative.col2, weight_string(authoritative.col2) from authoritative", + "Query": "select distinct authoritative.col2, weight_string(authoritative.col2) from authoritative", "Table": "authoritative" } ] From 22d7f352d8b5bf37d415aeb26fafbbcb62df4a73 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Wed, 12 Jul 2023 17:57:57 +0200 Subject: [PATCH 11/44] improved logic in Union.AddColumn Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/operators/union.go | 50 ++- .../planbuilder/testdata/aggr_cases.json | 46 +++ .../testdata/info_schema57_cases.json | 41 +- .../testdata/info_schema80_cases.json | 41 +- .../planbuilder/testdata/select_cases.json | 36 +- .../planbuilder/testdata/union_cases.json | 375 +++++++++++++++++- .../testdata/unsupported_cases.json | 43 +- 7 files changed, 605 insertions(+), 27 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/union.go b/go/vt/vtgate/planbuilder/operators/union.go index 296c59d6a9f..d69c6afb664 100644 --- a/go/vt/vtgate/planbuilder/operators/union.go +++ b/go/vt/vtgate/planbuilder/operators/union.go @@ -191,38 +191,57 @@ func (u *Union) AddColumn(ctx *plancontext.PlanningContext, ae *sqlparser.Aliase if err != nil { return nil, 0, err } + + // First we check if we already have this column for idx, col := range cols { if ctx.SemTable.EqualsExprWithDeps(ae.Expr, col.Expr) { return u, idx, nil } } - ws, isWeightString := ae.Expr.(*sqlparser.WeightStringFuncExpr) - if !isWeightString { - return nil, 0, vterrors.VT13001(fmt.Sprintf("only weight_string function is expected - got %s", sqlparser.String(ae))) - } + switch e := ae.Expr.(type) { + case *sqlparser.ColName: + // here we deal with pure column access on top of the union + offset := slices.IndexFunc(cols, func(expr *sqlparser.AliasedExpr) bool { + return e.Name.EqualString(expr.ColumnName()) + }) + if offset == -1 { + return nil, 0, vterrors.VT13001(fmt.Sprintf("could not find the column '%s' on the UNION", sqlparser.String(e))) + } + return u, offset, nil + case *sqlparser.WeightStringFuncExpr: + wsArg := e.Expr + argIdx := slices.IndexFunc(cols, func(expr *sqlparser.AliasedExpr) bool { + return ctx.SemTable.EqualsExprWithDeps(wsArg, expr.Expr) + }) + + if argIdx == -1 { + return nil, 0, vterrors.VT13001(fmt.Sprintf("could not find the argument to the weight_string function: %s", sqlparser.String(wsArg))) + } - wsArg := ws.Expr - argIdx := slices.IndexFunc(cols, func(expr *sqlparser.AliasedExpr) bool { - return ctx.SemTable.EqualsExprWithDeps(wsArg, expr.Expr) - }) + outputOffset, err := u.addWeightStringToOffset(ctx, argIdx, addToGroupBy) + if err != nil { + return nil, 0, err + } - if argIdx == -1 { - return nil, 0, vterrors.VT13001(fmt.Sprintf("could not find the argument to the weight_string function: %s", sqlparser.String(wsArg))) + return u, outputOffset, nil + default: + return nil, 0, vterrors.VT13001(fmt.Sprintf("only weight_string function is expected - got %s", sqlparser.String(ae))) } - var outputOffset int +} +func (u *Union) addWeightStringToOffset(ctx *plancontext.PlanningContext, argIdx int, addToGroupBy bool) (outputOffset int, err error) { for i, src := range u.Sources { exprs := u.Selects[i] selectExpr := exprs[argIdx] ae, ok := selectExpr.(*sqlparser.AliasedExpr) if !ok { - return nil, 0, vterrors.VT09015() + return 0, vterrors.VT09015() } newSrc, thisOffset, err := src.AddColumn(ctx, aeWrap(weightStringFor(ae.Expr)), false, addToGroupBy) if err != nil { - return nil, 0, err + return 0, err } // all offsets for the newly added ws need to line up @@ -230,14 +249,13 @@ func (u *Union) AddColumn(ctx *plancontext.PlanningContext, ae *sqlparser.Aliase outputOffset = thisOffset } else { if thisOffset != outputOffset { - return nil, 0, vterrors.VT12001("weight_string offsets did not line up for UNION") + return 0, vterrors.VT12001("weight_string offsets did not line up for UNION") } } u.Sources[i] = newSrc } - - return u, outputOffset, nil + return } func (u *Union) GetColumns(ctx *plancontext.PlanningContext) (result []*sqlparser.AliasedExpr, err error) { diff --git a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json index f69cca52c72..ae65abc6a4a 100644 --- a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json @@ -5837,6 +5837,52 @@ ] } }, + { + "comment": "aggregation on union", + "query": "select sum(col) from (select col from user union all select col from unsharded) t", + "plan": { + "QueryType": "SELECT", + "Original": "select sum(col) from (select col from user union all select col from unsharded) t", + "Instructions": { + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "sum(0) AS sum(col)", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select col from `user` where 1 != 1", + "Query": "select col from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select col from unsharded where 1 != 1", + "Query": "select col from unsharded", + "Table": "unsharded" + } + ] + } + ] + }, + "TablesUsed": [ + "main.unsharded", + "user.user" + ] + } + }, { "comment": "aggregation on top of derived table with limit", "query": "select count(val2), sum(val2) from (select id, val2 from user where val2 is null limit 2) as x", diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json index d47c92400b9..244391daa91 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json @@ -994,7 +994,46 @@ { "comment": "merge even one side have schema name in derived table", "query": "select * from (select TABLE_NAME from information_schema.tables t where t.TABLE_SCHEMA = 'a' union select TABLE_NAME from information_schema.columns) dt", - "plan": "VT13001: [BUG] only weight_string function is expected - got dt.TABLE_NAME" + "plan": { + "QueryType": "SELECT", + "Original": "select * from (select TABLE_NAME from information_schema.tables t where t.TABLE_SCHEMA = 'a' union select TABLE_NAME from information_schema.columns) dt", + "Instructions": { + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`tables` as t where 1 != 1", + "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"a\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns` where 1 != 1", + "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns`", + "Table": "information_schema.`columns`" + } + ] + } + ] + } + } }, { "comment": "merge even one side have schema name in subquery", diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json index d2fb99b4634..d0f1cd63906 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json @@ -1059,7 +1059,46 @@ { "comment": "merge even one side have schema name in derived table", "query": "select * from (select TABLE_NAME from information_schema.tables t where t.TABLE_SCHEMA = 'a' union select TABLE_NAME from information_schema.columns) dt", - "plan": "VT13001: [BUG] only weight_string function is expected - got dt.TABLE_NAME" + "plan": { + "QueryType": "SELECT", + "Original": "select * from (select TABLE_NAME from information_schema.tables t where t.TABLE_SCHEMA = 'a' union select TABLE_NAME from information_schema.columns) dt", + "Instructions": { + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`tables` as t where 1 != 1", + "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"a\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns` where 1 != 1", + "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns`", + "Table": "information_schema.`columns`" + } + ] + } + ] + } + } }, { "comment": "merge even one side have schema name in subquery", diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.json b/go/vt/vtgate/planbuilder/testdata/select_cases.json index 6f849d54ba1..834bd750bcf 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.json @@ -2473,7 +2473,41 @@ { "comment": "union as a derived table", "query": "select found from (select id as found from user union all (select id from unsharded)) as t", - "plan": "VT13001: [BUG] only weight_string function is expected - got found" + "plan": { + "QueryType": "SELECT", + "Original": "select found from (select id as found from user union all (select id from unsharded)) as t", + "Instructions": { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id as found from `user` where 1 != 1", + "Query": "select id as found from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select id from unsharded where 1 != 1", + "Query": "select id from unsharded", + "Table": "unsharded" + } + ] + }, + "TablesUsed": [ + "main.unsharded", + "user.user" + ] + } }, { "comment": "use output column containing data from both sides of the join", diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 62063f5a74d..b92e1fd18c5 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -119,7 +119,63 @@ { "comment": "almost dereks query - two queries with order by and limit being scattered to two different sets of tablets", "query": "(SELECT id FROM user ORDER BY id DESC LIMIT 1) UNION ALL (SELECT id FROM music ORDER BY id DESC LIMIT 1)", - "plan": "VT13001: [BUG] only weight_string function is expected - got id" + "plan": { + "QueryType": "SELECT", + "Original": "(SELECT id FROM user ORDER BY id DESC LIMIT 1) UNION ALL (SELECT id FROM music ORDER BY id DESC LIMIT 1)", + "Instructions": { + "OperatorType": "SimpleProjection", + "Columns": [ + 0 + ], + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Limit", + "Count": "INT64(1)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from `user`", + "Table": "`user`" + } + ] + }, + { + "OperatorType": "Limit", + "Count": "INT64(1)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from music where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from music", + "Table": "music" + } + ] + } + ] + } + ] + }, + "TablesUsed": [ + "user.music", + "user.user" + ] + } }, { "comment": "Union all", @@ -168,12 +224,102 @@ { "comment": "union operations in derived table, without star expression (FROM)¡", "query": "select col1,col2 from (select col1, col2 from user union all select col1, col2 from user_extra) as t", - "plan": "VT13001: [BUG] only weight_string function is expected - got col1" + "plan": { + "QueryType": "SELECT", + "Original": "select col1,col2 from (select col1, col2 from user union all select col1, col2 from user_extra) as t", + "Instructions": { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select col1, col2 from `user` where 1 != 1", + "Query": "select col1, col2 from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select col1, col2 from user_extra where 1 != 1", + "Query": "select col1, col2 from user_extra", + "Table": "user_extra" + } + ] + }, + "TablesUsed": [ + "user.user", + "user.user_extra" + ] + } }, { "comment": "union all between two scatter selects, with order by", "query": "(select id from user order by id limit 5) union all (select id from music order by id desc limit 5)", - "plan": "VT13001: [BUG] only weight_string function is expected - got id" + "plan": { + "QueryType": "SELECT", + "Original": "(select id from user order by id limit 5) union all (select id from music order by id desc limit 5)", + "Instructions": { + "OperatorType": "SimpleProjection", + "Columns": [ + 0 + ], + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Limit", + "Count": "INT64(5)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) ASC", + "Query": "select id, weight_string(id) from `user`", + "Table": "`user`" + } + ] + }, + { + "OperatorType": "Limit", + "Count": "INT64(5)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from music where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from music", + "Table": "music" + } + ] + } + ] + } + ] + }, + "TablesUsed": [ + "user.music", + "user.user" + ] + } }, { "comment": "union all on scatter and single route", @@ -668,7 +814,54 @@ { "comment": "Union in derived table with first SELECT being an UNION", "query": "select * from ((select id from user union select id+1 from user) union select user_id from user_extra) as t", - "plan": "VT13001: [BUG] only weight_string function is expected - got t.id" + "plan": { + "QueryType": "SELECT", + "Original": "select * from ((select id from user union select id+1 from user) union select user_id from user_extra) as t", + "Instructions": { + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Distinct", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select id + 1 from `user` where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id) from (select id from `user` union select id + 1 from `user`) as dt", + "Table": "`user`" + } + ] + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select user_id, weight_string(user_id) from user_extra where 1 != 1", + "Query": "select distinct user_id, weight_string(user_id) from user_extra", + "Table": "user_extra" + } + ] + } + ] + }, + "TablesUsed": [ + "user.user", + "user.user_extra" + ] + } }, { "comment": "gen4 optimises away ORDER BY when it's safe to do", @@ -874,7 +1067,80 @@ { "comment": "derived table with union", "query": "select tbl2.id FROM ((select id from user order by id limit 5) union all (select id from user order by id desc limit 5)) as tbl1 INNER JOIN user as tbl2 ON tbl1.id = tbl2.id", - "plan": "VT13001: [BUG] only weight_string function is expected - got tbl1.id" + "plan": { + "QueryType": "SELECT", + "Original": "select tbl2.id FROM ((select id from user order by id limit 5) union all (select id from user order by id desc limit 5)) as tbl1 INNER JOIN user as tbl2 ON tbl1.id = tbl2.id", + "Instructions": { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "R:0", + "JoinVars": { + "tbl1_id": 0 + }, + "TableName": "`user`_`user`", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Limit", + "Count": "INT64(5)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) ASC", + "Query": "select id, weight_string(id) from `user`", + "Table": "`user`" + } + ] + }, + { + "OperatorType": "Limit", + "Count": "INT64(5)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from `user`", + "Table": "`user`" + } + ] + } + ] + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select tbl2.id from `user` as tbl2 where 1 != 1", + "Query": "select tbl2.id from `user` as tbl2 where tbl2.id = :tbl1_id", + "Table": "`user`", + "Values": [ + ":tbl1_id" + ], + "Vindex": "user_index" + } + ] + }, + "TablesUsed": [ + "user.user" + ] + } }, { "comment": "ambiguous LIMIT", @@ -990,7 +1256,49 @@ { "comment": "systable union query in derived table with constraint on outside (without star projection)", "query": "select * from (select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `COLUMN_NAME` = 'primary'", - "plan": "VT13001: [BUG] only weight_string function is expected - got kcu.COLUMN_NAME" + "plan": { + "QueryType": "SELECT", + "Original": "select * from (select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `COLUMN_NAME` = 'primary'", + "Instructions": { + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select kcu.COLUMN_NAME, weight_string(kcu.COLUMN_NAME) from information_schema.key_column_usage as kcu where 1 != 1", + "Query": "select distinct kcu.COLUMN_NAME, weight_string(kcu.COLUMN_NAME) from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name /* VARCHAR */ and COLUMN_NAME = 'primary'", + "SysTableTableName": "[kcu_table_name:VARCHAR(\"user_extra\")]", + "SysTableTableSchema": "[VARCHAR(\"user\")]", + "Table": "information_schema.key_column_usage" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select kcu.COLUMN_NAME, weight_string(kcu.COLUMN_NAME) from information_schema.key_column_usage as kcu where 1 != 1", + "Query": "select distinct kcu.COLUMN_NAME, weight_string(kcu.COLUMN_NAME) from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name1 /* VARCHAR */ and COLUMN_NAME = 'primary'", + "SysTableTableName": "[kcu_table_name1:VARCHAR(\"music\")]", + "SysTableTableSchema": "[VARCHAR(\"user\")]", + "Table": "information_schema.key_column_usage" + } + ] + } + ] + } + } }, { "comment": "pushes predicate on both sides of UNION", @@ -1022,7 +1330,60 @@ { "comment": "systable union query in derived table with constraint on outside (star projection)", "query": "select * from (select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `constraint_name` = 'primary'", - "plan": "VT13001: [BUG] only weight_string function is expected - got kcu.CONSTRAINT_CATALOG" + "plan": { + "QueryType": "SELECT", + "Original": "select * from (select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `constraint_name` = 'primary'", + "Instructions": { + "OperatorType": "Distinct", + "Collations": [ + "(0:12)", + "(1:13)", + "(2:14)", + "(3:15)", + "(4:16)", + "(5:17)", + "(6:18)", + "(7:19)", + "(8:20)", + "(9:21)", + "(10:22)", + "(11:23)" + ], + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME, weight_string(kcu.CONSTRAINT_CATALOG), weight_string(kcu.CONSTRAINT_SCHEMA), weight_string(kcu.CONSTRAINT_NAME), weight_string(kcu.TABLE_CATALOG), weight_string(kcu.TABLE_SCHEMA), weight_string(kcu.TABLE_NAME), weight_string(kcu.COLUMN_NAME), weight_string(kcu.ORDINAL_POSITION), weight_string(kcu.POSITION_IN_UNIQUE_CONSTRAINT), weight_string(kcu.REFERENCED_TABLE_SCHEMA), weight_string(kcu.REFERENCED_TABLE_NAME), weight_string(kcu.REFERENCED_COLUMN_NAME) from information_schema.key_column_usage as kcu where 1 != 1", + "Query": "select distinct kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME, weight_string(kcu.CONSTRAINT_CATALOG), weight_string(kcu.CONSTRAINT_SCHEMA), weight_string(kcu.CONSTRAINT_NAME), weight_string(kcu.TABLE_CATALOG), weight_string(kcu.TABLE_SCHEMA), weight_string(kcu.TABLE_NAME), weight_string(kcu.COLUMN_NAME), weight_string(kcu.ORDINAL_POSITION), weight_string(kcu.POSITION_IN_UNIQUE_CONSTRAINT), weight_string(kcu.REFERENCED_TABLE_SCHEMA), weight_string(kcu.REFERENCED_TABLE_NAME), weight_string(kcu.REFERENCED_COLUMN_NAME) from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name /* VARCHAR */ and CONSTRAINT_NAME = 'primary'", + "SysTableTableName": "[kcu_table_name:VARCHAR(\"user_extra\")]", + "SysTableTableSchema": "[VARCHAR(\"user\")]", + "Table": "information_schema.key_column_usage" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME, weight_string(kcu.CONSTRAINT_CATALOG), weight_string(kcu.CONSTRAINT_SCHEMA), weight_string(kcu.CONSTRAINT_NAME), weight_string(kcu.TABLE_CATALOG), weight_string(kcu.TABLE_SCHEMA), weight_string(kcu.TABLE_NAME), weight_string(kcu.COLUMN_NAME), weight_string(kcu.ORDINAL_POSITION), weight_string(kcu.POSITION_IN_UNIQUE_CONSTRAINT), weight_string(kcu.REFERENCED_TABLE_SCHEMA), weight_string(kcu.REFERENCED_TABLE_NAME), weight_string(kcu.REFERENCED_COLUMN_NAME) from information_schema.key_column_usage as kcu where 1 != 1", + "Query": "select distinct kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME, weight_string(kcu.CONSTRAINT_CATALOG), weight_string(kcu.CONSTRAINT_SCHEMA), weight_string(kcu.CONSTRAINT_NAME), weight_string(kcu.TABLE_CATALOG), weight_string(kcu.TABLE_SCHEMA), weight_string(kcu.TABLE_NAME), weight_string(kcu.COLUMN_NAME), weight_string(kcu.ORDINAL_POSITION), weight_string(kcu.POSITION_IN_UNIQUE_CONSTRAINT), weight_string(kcu.REFERENCED_TABLE_SCHEMA), weight_string(kcu.REFERENCED_TABLE_NAME), weight_string(kcu.REFERENCED_COLUMN_NAME) from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name1 /* VARCHAR */ and CONSTRAINT_NAME = 'primary'", + "SysTableTableName": "[kcu_table_name1:VARCHAR(\"music\")]", + "SysTableTableSchema": "[VARCHAR(\"user\")]", + "Table": "information_schema.key_column_usage" + } + ] + } + ] + } + } }, { "comment": "unknown columns are OK as long as the whole query is unsharded", diff --git a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json index 0f8ea9c7b5e..e3598695674 100644 --- a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json @@ -377,7 +377,48 @@ { "comment": "aggregation on union", "query": "select sum(col) from (select col from user union all select col from unsharded) t", - "plan": "VT13001: [BUG] only weight_string function is expected - got col" + "plan": { + "QueryType": "SELECT", + "Original": "select sum(col) from (select col from user union all select col from unsharded) t", + "Instructions": { + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "sum(0) AS sum(col)", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select col from `user` where 1 != 1", + "Query": "select col from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select col from unsharded where 1 != 1", + "Query": "select col from unsharded", + "Table": "unsharded" + } + ] + } + ] + }, + "TablesUsed": [ + "main.unsharded", + "user.user" + ] + } }, { "comment": "insert having subquery in row values", From 897089e769eba769a7a4122f3193e4841983d24a Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Wed, 12 Jul 2023 18:00:49 +0200 Subject: [PATCH 12/44] missing license header Signed-off-by: Andres Taylor --- .../planbuilder/operators/union_merging.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/go/vt/vtgate/planbuilder/operators/union_merging.go b/go/vt/vtgate/planbuilder/operators/union_merging.go index cb126043c4b..3d12c851daa 100644 --- a/go/vt/vtgate/planbuilder/operators/union_merging.go +++ b/go/vt/vtgate/planbuilder/operators/union_merging.go @@ -1,3 +1,19 @@ +/* +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 operators import ( From efde977eb1be92dad43a63756254360fb3b4a999 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Thu, 13 Jul 2023 08:35:25 +0200 Subject: [PATCH 13/44] don't remove operators by mistake Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/operators/route.go | 21 +++- .../planbuilder/testdata/aggr_cases.json | 112 ++++++++++++------ .../planbuilder/testdata/from_cases.json | 3 +- .../testdata/memory_sort_cases.json | 23 ++-- .../testdata/postprocess_cases.json | 46 +++---- .../planbuilder/testdata/select_cases.json | 7 +- .../planbuilder/testdata/union_cases.json | 14 +-- 7 files changed, 144 insertions(+), 82 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/route.go b/go/vt/vtgate/planbuilder/operators/route.go index c5b31e9d0fb..4baf090c505 100644 --- a/go/vt/vtgate/planbuilder/operators/route.go +++ b/go/vt/vtgate/planbuilder/operators/route.go @@ -593,11 +593,26 @@ type selectExpressions interface { func addColumnToInput(ctx *plancontext.PlanningContext, operator ops.Operator, expr *sqlparser.AliasedExpr, addToGroupBy bool) (ops.Operator, bool, int) { switch op := operator.(type) { case *CorrelatedSubQueryOp: - return addColumnToInput(ctx, op.Outer, expr, addToGroupBy) + src, added, offset := addColumnToInput(ctx, op.Outer, expr, addToGroupBy) + if added { + op.Outer = src + } + return op, added, offset + case *Limit: - return addColumnToInput(ctx, op.Source, expr, addToGroupBy) + src, added, offset := addColumnToInput(ctx, op.Source, expr, addToGroupBy) + if added { + op.Source = src + } + return op, added, offset + case *Ordering: - return addColumnToInput(ctx, op.Source, expr, addToGroupBy) + src, added, offset := addColumnToInput(ctx, op.Source, expr, addToGroupBy) + if added { + op.Source = src + } + return op, added, offset + case selectExpressions: if op.isDerived() { // if the only thing we can push to is a derived table, diff --git a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json index ae65abc6a4a..775ecf500be 100644 --- a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json @@ -497,7 +497,8 @@ "Sharded": true }, "FieldQuery": "select col1, col2, weight_string(col1), weight_string(col2) from `user` where 1 != 1 group by col1, col2, weight_string(col1), weight_string(col2)", - "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2)", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2) order by col1 asc, col2 asc", "Table": "`user`" } ] @@ -527,7 +528,8 @@ "Sharded": true }, "FieldQuery": "select col2, weight_string(col2) from `user` where 1 != 1 group by col2, weight_string(col2)", - "Query": "select col2, weight_string(col2) from `user` group by col2, weight_string(col2)", + "OrderBy": "(0|1) ASC", + "Query": "select col2, weight_string(col2) from `user` group by col2, weight_string(col2) order by col2 asc", "Table": "`user`" } ] @@ -558,7 +560,8 @@ "Sharded": true }, "FieldQuery": "select col1, col2, weight_string(col1), weight_string(col2) from `user` where 1 != 1 group by col1, col2, weight_string(col1), weight_string(col2)", - "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2)", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2) order by col1 asc, col2 asc", "Table": "`user`" } ] @@ -589,7 +592,8 @@ "Sharded": true }, "FieldQuery": "select col1, col2, weight_string(col1), weight_string(col2) from `user` where 1 != 1 group by col1, col2, weight_string(col1), weight_string(col2)", - "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2)", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2) order by col1 asc, col2 asc", "Table": "`user`" } ] @@ -620,7 +624,8 @@ "Sharded": true }, "FieldQuery": "select col1, min(col2) as `min(distinct col2)`, weight_string(col1), weight_string(col2) from `user` where 1 != 1 group by col1, weight_string(col1), weight_string(col2)", - "Query": "select col1, min(col2) as `min(distinct col2)`, weight_string(col1), weight_string(col2) from `user` group by col1, weight_string(col1), weight_string(col2)", + "OrderBy": "(0|2) ASC", + "Query": "select col1, min(col2) as `min(distinct col2)`, weight_string(col1), weight_string(col2) from `user` group by col1, weight_string(col1), weight_string(col2) order by col1 asc", "Table": "`user`" } ] @@ -656,7 +661,8 @@ "Sharded": true }, "FieldQuery": "select col1, col2, weight_string(col1), weight_string(col2) from `user` where 1 != 1 group by col1, col2, weight_string(col1), weight_string(col2)", - "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2)", + "OrderBy": "(0|2) ASC, (1|3) ASC", + "Query": "select col1, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2) order by col1 asc, col2 asc", "Table": "`user`" } ] @@ -694,7 +700,8 @@ "Sharded": true }, "FieldQuery": "select a, b, count(*), weight_string(a), weight_string(b) from `user` where 1 != 1 group by a, b, weight_string(a), weight_string(b)", - "Query": "select a, b, count(*), weight_string(a), weight_string(b) from `user` group by a, b, weight_string(a), weight_string(b)", + "OrderBy": "(0|3) ASC, (1|4) ASC", + "Query": "select a, b, count(*), weight_string(a), weight_string(b) from `user` group by a, b, weight_string(a), weight_string(b) order by a asc, b asc", "Table": "`user`" } ] @@ -725,7 +732,8 @@ "Sharded": true }, "FieldQuery": "select a, b, count(*), weight_string(b), weight_string(a) from `user` where 1 != 1 group by b, a, weight_string(b), weight_string(a)", - "Query": "select a, b, count(*), weight_string(b), weight_string(a) from `user` group by b, a, weight_string(b), weight_string(a)", + "OrderBy": "(1|3) ASC, (0|4) ASC", + "Query": "select a, b, count(*), weight_string(b), weight_string(a) from `user` group by b, a, weight_string(b), weight_string(a) order by b asc, a asc", "Table": "`user`" } ] @@ -756,7 +764,8 @@ "Sharded": true }, "FieldQuery": "select a, b, count(*), weight_string(b), weight_string(a) from `user` where 1 != 1 group by b, a, weight_string(b), weight_string(a)", - "Query": "select a, b, count(*), weight_string(b), weight_string(a) from `user` group by b, a, weight_string(b), weight_string(a)", + "OrderBy": "(1|3) ASC, (0|4) ASC", + "Query": "select a, b, count(*), weight_string(b), weight_string(a) from `user` group by b, a, weight_string(b), weight_string(a) order by b asc, a asc", "Table": "`user`" } ] @@ -1152,7 +1161,8 @@ "Sharded": true }, "FieldQuery": "select a, count(*), weight_string(a) from `user` where 1 != 1 group by a, weight_string(a)", - "Query": "select a, count(*), weight_string(a) from `user` group by a, weight_string(a)", + "OrderBy": "(0|2) ASC", + "Query": "select a, count(*), weight_string(a) from `user` group by a, weight_string(a) order by a asc", "Table": "`user`" } ] @@ -1183,7 +1193,8 @@ "Sharded": true }, "FieldQuery": "select id, 1.1 from `user` where 1 != 1 group by 1.1", - "Query": "select id, 1.1 from `user` group by 1.1", + "OrderBy": "1 ASC", + "Query": "select id, 1.1 from `user` group by 1.1 order by 1.1 asc", "Table": "`user`" } ] @@ -1370,7 +1381,8 @@ "Sharded": true }, "FieldQuery": "select `user`.a, weight_string(`user`.a) from `user` where 1 != 1 group by `user`.a, weight_string(`user`.a)", - "Query": "select `user`.a, weight_string(`user`.a) from `user` group by `user`.a, weight_string(`user`.a)", + "OrderBy": "(0|1) ASC", + "Query": "select `user`.a, weight_string(`user`.a) from `user` group by `user`.a, weight_string(`user`.a) order by `user`.a asc", "Table": "`user`" }, { @@ -1420,7 +1432,8 @@ "Sharded": true }, "FieldQuery": "select col1, col2, col2, weight_string(col1), weight_string(col2) from `user` where 1 != 1 group by col1, col2, weight_string(col1), weight_string(col2)", - "Query": "select col1, col2, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2)", + "OrderBy": "(0|3) ASC, (1|4) ASC", + "Query": "select col1, col2, col2, weight_string(col1), weight_string(col2) from `user` group by col1, col2, weight_string(col1), weight_string(col2) order by col1 asc, col2 asc", "Table": "`user`" } ] @@ -1595,7 +1608,8 @@ "Sharded": true }, "FieldQuery": "select lower(textcol1) as v, count(*), weight_string(lower(textcol1)) from `user` where 1 != 1 group by v, weight_string(lower(textcol1))", - "Query": "select lower(textcol1) as v, count(*), weight_string(lower(textcol1)) from `user` group by v, weight_string(lower(textcol1))", + "OrderBy": "(0|2) ASC", + "Query": "select lower(textcol1) as v, count(*), weight_string(lower(textcol1)) from `user` group by v, weight_string(lower(textcol1)) order by v asc", "Table": "`user`" } ] @@ -1656,7 +1670,7 @@ }, "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select id, weight_string(id) from `user`", + "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", "ResultColumns": 1, "Table": "`user`" } @@ -2064,7 +2078,8 @@ "Sharded": true }, "FieldQuery": "select count(*) as a, val1, weight_string(val1) from `user` where 1 != 1 group by val1, weight_string(val1)", - "Query": "select count(*) as a, val1, weight_string(val1) from `user` group by val1, weight_string(val1)", + "OrderBy": "(1|2) ASC", + "Query": "select count(*) as a, val1, weight_string(val1) from `user` group by val1, weight_string(val1) order by val1 asc", "Table": "`user`" } ] @@ -2316,7 +2331,8 @@ "Sharded": true }, "FieldQuery": "select count(*), `user`.a, weight_string(`user`.a) from `user` where 1 != 1 group by `user`.a, weight_string(`user`.a)", - "Query": "select count(*), `user`.a, weight_string(`user`.a) from `user` group by `user`.a, weight_string(`user`.a)", + "OrderBy": "(1|2) ASC", + "Query": "select count(*), `user`.a, weight_string(`user`.a) from `user` group by `user`.a, weight_string(`user`.a) order by `user`.a asc", "Table": "`user`" }, { @@ -2377,7 +2393,8 @@ "Sharded": true }, "FieldQuery": "select count(*), `user`.a, weight_string(`user`.a) from `user` where 1 != 1 group by `user`.a, weight_string(`user`.a)", - "Query": "select count(*), `user`.a, weight_string(`user`.a) from `user` group by `user`.a, weight_string(`user`.a)", + "OrderBy": "(1|2) ASC", + "Query": "select count(*), `user`.a, weight_string(`user`.a) from `user` group by `user`.a, weight_string(`user`.a) order by `user`.a asc", "Table": "`user`" }, { @@ -2530,7 +2547,8 @@ "Sharded": true }, "FieldQuery": "select col1, min(id) as `min(distinct id)`, col3, weight_string(col1), weight_string(id), weight_string(col3) from `user` where 1 != 1 group by col1, col3, weight_string(col1), weight_string(id), weight_string(col3)", - "Query": "select col1, min(id) as `min(distinct id)`, col3, weight_string(col1), weight_string(id), weight_string(col3) from `user` group by col1, col3, weight_string(col1), weight_string(id), weight_string(col3)", + "OrderBy": "(0|3) ASC, (2|5) ASC", + "Query": "select col1, min(id) as `min(distinct id)`, col3, weight_string(col1), weight_string(id), weight_string(col3) from `user` group by col1, col3, weight_string(col1), weight_string(id), weight_string(col3) order by col1 asc, col3 asc", "Table": "`user`" } ] @@ -2619,7 +2637,8 @@ "Sharded": true }, "FieldQuery": "select val2, val1, count(*), weight_string(val2), weight_string(val1) from `user` where 1 != 1 group by val2, val1, weight_string(val2), weight_string(val1)", - "Query": "select val2, val1, count(*), weight_string(val2), weight_string(val1) from `user` group by val2, val1, weight_string(val2), weight_string(val1)", + "OrderBy": "(0|3) ASC, (1|4) ASC", + "Query": "select val2, val1, count(*), weight_string(val2), weight_string(val1) from `user` group by val2, val1, weight_string(val2), weight_string(val1) order by val2 asc, val1 asc", "Table": "`user`" } ] @@ -2650,7 +2669,8 @@ "Sharded": true }, "FieldQuery": "select ascii(val1) as a, count(*), weight_string(ascii(val1)) from `user` where 1 != 1 group by a, weight_string(ascii(val1))", - "Query": "select ascii(val1) as a, count(*), weight_string(ascii(val1)) from `user` group by a, weight_string(ascii(val1))", + "OrderBy": "(0|2) ASC", + "Query": "select ascii(val1) as a, count(*), weight_string(ascii(val1)) from `user` group by a, weight_string(ascii(val1)) order by a asc", "Table": "`user`" } ] @@ -2681,7 +2701,8 @@ "Sharded": true }, "FieldQuery": "select tcol1, tcol2, tcol2, weight_string(tcol1), weight_string(tcol2) from `user` where 1 != 1 group by tcol1, tcol2, weight_string(tcol1), weight_string(tcol2)", - "Query": "select tcol1, tcol2, tcol2, weight_string(tcol1), weight_string(tcol2) from `user` group by tcol1, tcol2, weight_string(tcol1), weight_string(tcol2)", + "OrderBy": "(0|3) ASC, (1|4) ASC", + "Query": "select tcol1, tcol2, tcol2, weight_string(tcol1), weight_string(tcol2) from `user` group by tcol1, tcol2, weight_string(tcol1), weight_string(tcol2) order by tcol1 asc, tcol2 asc", "Table": "`user`" } ] @@ -2712,7 +2733,8 @@ "Sharded": true }, "FieldQuery": "select tcol2, tcol1, count(*), tcol2, weight_string(tcol1), weight_string(tcol2) from `user` where 1 != 1 group by tcol1, tcol2, weight_string(tcol1), weight_string(tcol2)", - "Query": "select tcol2, tcol1, count(*), tcol2, weight_string(tcol1), weight_string(tcol2) from `user` group by tcol1, tcol2, weight_string(tcol1), weight_string(tcol2)", + "OrderBy": "(1|4) ASC, (0|5) ASC", + "Query": "select tcol2, tcol1, count(*), tcol2, weight_string(tcol1), weight_string(tcol2) from `user` group by tcol1, tcol2, weight_string(tcol1), weight_string(tcol2) order by tcol1 asc, tcol2 asc", "Table": "`user`" } ] @@ -2944,7 +2966,8 @@ "Sharded": true }, "FieldQuery": "select foo, count(*), weight_string(foo) from `user` where 1 != 1 group by foo, weight_string(foo)", - "Query": "select foo, count(*), weight_string(foo) from `user` group by foo, weight_string(foo)", + "OrderBy": "(0|2) ASC", + "Query": "select foo, count(*), weight_string(foo) from `user` group by foo, weight_string(foo) order by foo asc", "Table": "`user`" } ] @@ -2990,7 +3013,8 @@ "Sharded": true }, "FieldQuery": "select foo, sum(foo), sum(bar), weight_string(foo) from `user` where 1 != 1 group by foo, weight_string(foo)", - "Query": "select foo, sum(foo), sum(bar), weight_string(foo) from `user` group by foo, weight_string(foo)", + "OrderBy": "(0|3) ASC", + "Query": "select foo, sum(foo), sum(bar), weight_string(foo) from `user` group by foo, weight_string(foo) order by foo asc", "Table": "`user`" } ] @@ -3036,7 +3060,8 @@ "Sharded": true }, "FieldQuery": "select foo, sum(foo) as fooSum, sum(bar) as barSum, weight_string(foo) from `user` where 1 != 1 group by foo, weight_string(foo)", - "Query": "select foo, sum(foo) as fooSum, sum(bar) as barSum, weight_string(foo) from `user` group by foo, weight_string(foo)", + "OrderBy": "(0|3) ASC", + "Query": "select foo, sum(foo) as fooSum, sum(bar) as barSum, weight_string(foo) from `user` group by foo, weight_string(foo) order by foo asc", "Table": "`user`" } ] @@ -3080,7 +3105,8 @@ "Sharded": true }, "FieldQuery": "select foo, count(*), weight_string(foo) from `user` where 1 != 1 group by foo, weight_string(foo)", - "Query": "select foo, count(*), weight_string(foo) from `user` group by foo, weight_string(foo)", + "OrderBy": "(0|2) ASC", + "Query": "select foo, count(*), weight_string(foo) from `user` group by foo, weight_string(foo) order by foo asc", "Table": "`user`" } ] @@ -3387,7 +3413,8 @@ "Sharded": true }, "FieldQuery": "select `user`.col, `user`.id, weight_string(`user`.id) from `user` where 1 != 1 group by `user`.id, `user`.col, weight_string(`user`.id)", - "Query": "select `user`.col, `user`.id, weight_string(`user`.id) from `user` group by `user`.id, `user`.col, weight_string(`user`.id)", + "OrderBy": "(1|2) ASC", + "Query": "select `user`.col, `user`.id, weight_string(`user`.id) from `user` group by `user`.id, `user`.col, weight_string(`user`.id) order by `user`.id asc", "Table": "`user`" }, { @@ -3503,7 +3530,8 @@ "Sharded": true }, "FieldQuery": "select `user`.id, weight_string(id) from `user` where 1 != 1 group by id, weight_string(id)", - "Query": "select `user`.id, weight_string(id) from `user` group by id, weight_string(id)", + "OrderBy": "(0|1) ASC", + "Query": "select `user`.id, weight_string(id) from `user` group by id, weight_string(id) order by id asc", "Table": "`user`" }, { @@ -4062,7 +4090,8 @@ "Sharded": true }, "FieldQuery": "select foo, max(baz) as bazo, weight_string(foo), weight_string(baz) from (select foo, baz from `user` where 1 != 1) as f where 1 != 1 group by foo, weight_string(foo), weight_string(baz)", - "Query": "select foo, max(baz) as bazo, weight_string(foo), weight_string(baz) from (select foo, baz from `user`) as f group by foo, weight_string(foo), weight_string(baz)", + "OrderBy": "(0|2) ASC", + "Query": "select foo, max(baz) as bazo, weight_string(foo), weight_string(baz) from (select foo, baz from `user`) as f group by foo, weight_string(foo), weight_string(baz) order by foo asc", "Table": "`user`" } ] @@ -4106,7 +4135,8 @@ "Sharded": true }, "FieldQuery": "select foo, count(baz) as bazo, weight_string(foo) from (select foo, baz from `user` where 1 != 1) as f where 1 != 1 group by foo, weight_string(foo)", - "Query": "select foo, count(baz) as bazo, weight_string(foo) from (select foo, baz from `user`) as f group by foo, weight_string(foo)", + "OrderBy": "(0|2) ASC", + "Query": "select foo, count(baz) as bazo, weight_string(foo) from (select foo, baz from `user`) as f group by foo, weight_string(foo) order by foo asc", "Table": "`user`" } ] @@ -4146,7 +4176,8 @@ "Sharded": true }, "FieldQuery": "select col, count(*), col + 1, weight_string(col + 1) from `user` where 1 != 1 group by col", - "Query": "select col, count(*), col + 1, weight_string(col + 1) from `user` group by col", + "OrderBy": "0 ASC", + "Query": "select col, count(*), col + 1, weight_string(col + 1) from `user` group by col order by col asc", "Table": "`user`" } ] @@ -4173,7 +4204,7 @@ }, "FieldQuery": "select id, id + 1, weight_string(id + 1) from `user` where 1 != 1 group by id", "OrderBy": "(1|2) ASC", - "Query": "select id, id + 1, weight_string(id + 1) from `user` group by id", + "Query": "select id, id + 1, weight_string(id + 1) from `user` group by id order by id + 1 asc", "ResultColumns": 1, "Table": "`user`" }, @@ -4203,7 +4234,8 @@ "Sharded": true }, "FieldQuery": "select a, a + 1, weight_string(a + 1) from `user` where 1 != 1 group by a + 1, weight_string(a + 1)", - "Query": "select a, a + 1, weight_string(a + 1) from `user` group by a + 1, weight_string(a + 1)", + "OrderBy": "(1|2) ASC", + "Query": "select a, a + 1, weight_string(a + 1) from `user` group by a + 1, weight_string(a + 1) order by a + 1 asc", "Table": "`user`" } ] @@ -4959,7 +4991,8 @@ "Sharded": true }, "FieldQuery": "select count(*), col from `user` where 1 != 1 group by col", - "Query": "select count(*), col from `user` group by col", + "OrderBy": "1 ASC", + "Query": "select count(*), col from `user` group by col order by col asc", "Table": "`user`" } ] @@ -5180,7 +5213,8 @@ "Sharded": true }, "FieldQuery": "select `user`.col, `user`.bar, weight_string(`user`.bar) from `user` where 1 != 1 group by `user`.col, `user`.bar, weight_string(`user`.bar)", - "Query": "select `user`.col, `user`.bar, weight_string(`user`.bar) from `user` group by `user`.col, `user`.bar, weight_string(`user`.bar)", + "OrderBy": "0 ASC, (1|2) ASC", + "Query": "select `user`.col, `user`.bar, weight_string(`user`.bar) from `user` group by `user`.col, `user`.bar, weight_string(`user`.bar) order by `user`.col asc, `user`.bar asc", "Table": "`user`" }, { @@ -5782,7 +5816,8 @@ "Sharded": true }, "FieldQuery": "select u.col1, weight_string(u.col1) from `user` as u where 1 != 1 group by u.col1, weight_string(u.col1)", - "Query": "select u.col1, weight_string(u.col1) from `user` as u group by u.col1, weight_string(u.col1)", + "OrderBy": "(0|1) ASC", + "Query": "select u.col1, weight_string(u.col1) from `user` as u group by u.col1, weight_string(u.col1) order by u.col1 asc", "Table": "`user`" }, { @@ -5827,7 +5862,8 @@ "Sharded": true }, "FieldQuery": "select foo, min(bar) as `min(distinct bar)`, baz, baz, max(toto) as `max(distinct toto)`, weight_string(foo), weight_string(bar), weight_string(baz), weight_string(toto) from `user` where 1 != 1 group by foo, baz, weight_string(foo), weight_string(bar), weight_string(baz), weight_string(toto)", - "Query": "select foo, min(bar) as `min(distinct bar)`, baz, baz, max(toto) as `max(distinct toto)`, weight_string(foo), weight_string(bar), weight_string(baz), weight_string(toto) from `user` group by foo, baz, weight_string(foo), weight_string(bar), weight_string(baz), weight_string(toto)", + "OrderBy": "(0|5) ASC, (2|7) ASC", + "Query": "select foo, min(bar) as `min(distinct bar)`, baz, baz, max(toto) as `max(distinct toto)`, weight_string(foo), weight_string(bar), weight_string(baz), weight_string(toto) from `user` group by foo, baz, weight_string(foo), weight_string(bar), weight_string(baz), weight_string(toto) order by foo asc, baz asc", "Table": "`user`" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/from_cases.json b/go/vt/vtgate/planbuilder/testdata/from_cases.json index ca352638d22..533521881be 100644 --- a/go/vt/vtgate/planbuilder/testdata/from_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/from_cases.json @@ -3751,7 +3751,8 @@ "Sharded": true }, "FieldQuery": "select col1, count(*), weight_string(col1) from (select colC + colD as col1 from `user` where 1 != 1) as tbl where 1 != 1 group by col1, weight_string(col1)", - "Query": "select col1, count(*), weight_string(col1) from (select colC + colD as col1 from `user`) as tbl group by col1, weight_string(col1)", + "OrderBy": "(0|2) ASC", + "Query": "select col1, count(*), weight_string(col1) from (select colC + colD as col1 from `user`) as tbl group by col1, weight_string(col1) order by col1 asc", "Table": "`user`" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json b/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json index fdaa73f5e25..58e6744f1a6 100644 --- a/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/memory_sort_cases.json @@ -25,7 +25,8 @@ "Sharded": true }, "FieldQuery": "select a, b, count(*), weight_string(a), weight_string(b) from `user` where 1 != 1 group by a, weight_string(a)", - "Query": "select a, b, count(*), weight_string(a), weight_string(b) from `user` group by a, weight_string(a)", + "OrderBy": "(0|3) ASC", + "Query": "select a, b, count(*), weight_string(a), weight_string(b) from `user` group by a, weight_string(a) order by a asc", "Table": "`user`" } ] @@ -63,7 +64,8 @@ "Sharded": true }, "FieldQuery": "select a, b, count(*) as k, weight_string(a) from `user` where 1 != 1 group by a, weight_string(a)", - "Query": "select a, b, count(*) as k, weight_string(a) from `user` group by a, weight_string(a)", + "OrderBy": "(0|3) ASC", + "Query": "select a, b, count(*) as k, weight_string(a) from `user` group by a, weight_string(a) order by a asc", "Table": "`user`" } ] @@ -101,7 +103,8 @@ "Sharded": true }, "FieldQuery": "select a, b, count(*) as k, weight_string(a), weight_string(b) from `user` where 1 != 1 group by a, weight_string(a)", - "Query": "select a, b, count(*) as k, weight_string(a), weight_string(b) from `user` group by a, weight_string(a)", + "OrderBy": "(0|3) ASC", + "Query": "select a, b, count(*) as k, weight_string(a), weight_string(b) from `user` group by a, weight_string(a) order by a asc", "Table": "`user`" } ] @@ -143,7 +146,8 @@ "Sharded": true }, "FieldQuery": "select a, b, count(*) as k, weight_string(a) from `user` where 1 != 1 group by a, weight_string(a)", - "Query": "select a, b, count(*) as k, weight_string(a) from `user` group by a, weight_string(a) limit :__upper_limit", + "OrderBy": "(0|3) ASC", + "Query": "select a, b, count(*) as k, weight_string(a) from `user` group by a, weight_string(a) order by a asc limit :__upper_limit", "Table": "`user`" } ] @@ -183,7 +187,8 @@ "Sharded": true }, "FieldQuery": "select a, b, count(*) as k, weight_string(a) from `user` where 1 != 1 group by a, weight_string(a)", - "Query": "select a, b, count(*) as k, weight_string(a) from `user` group by a, weight_string(a)", + "OrderBy": "(0|3) ASC", + "Query": "select a, b, count(*) as k, weight_string(a) from `user` group by a, weight_string(a) order by a asc", "Table": "`user`" } ] @@ -254,7 +259,7 @@ }, "FieldQuery": "select id, weight_string(id) from (select `user`.id, `user`.col from `user` where 1 != 1) as t where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select id, weight_string(id) from (select `user`.id, `user`.col from `user`) as t", + "Query": "select id, weight_string(id) from (select `user`.id, `user`.col from `user`) as t order by id asc", "Table": "`user`" }, { @@ -549,7 +554,7 @@ }, "FieldQuery": "select a, convert(a, binary), weight_string(convert(a, binary)) from `user` where 1 != 1", "OrderBy": "(1|2) DESC", - "Query": "select a, convert(a, binary), weight_string(convert(a, binary)) from `user`", + "Query": "select a, convert(a, binary), weight_string(convert(a, binary)) from `user` order by convert(a, binary) desc", "ResultColumns": 1, "Table": "`user`" }, @@ -582,7 +587,7 @@ }, "FieldQuery": "select u.a, convert(a, binary), weight_string(convert(a, binary)) from `user` as u where 1 != 1", "OrderBy": "(1|2) DESC", - "Query": "select u.a, convert(a, binary), weight_string(convert(a, binary)) from `user` as u", + "Query": "select u.a, convert(a, binary), weight_string(convert(a, binary)) from `user` as u order by convert(a, binary) desc", "Table": "`user`" }, { @@ -642,7 +647,7 @@ }, "FieldQuery": "select col, id, weight_string(id) from `user` where 1 != 1", "OrderBy": "(1|2) ASC", - "Query": "select col, id, weight_string(id) from `user`", + "Query": "select col, id, weight_string(id) from `user` order by id asc", "ResultColumns": 1, "Table": "`user`" }, diff --git a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json index cb87e68b01e..8e9270d1f6a 100644 --- a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json @@ -267,7 +267,7 @@ }, "FieldQuery": "select user_id, col1, col2, weight_string(user_id) from authoritative where 1 != 1", "OrderBy": "(0|3) ASC", - "Query": "select user_id, col1, col2, weight_string(user_id) from authoritative", + "Query": "select user_id, col1, col2, weight_string(user_id) from authoritative order by user_id asc", "ResultColumns": 3, "Table": "authoritative" }, @@ -314,7 +314,7 @@ }, "FieldQuery": "select a, textcol1, b, weight_string(a), weight_string(b) from `user` where 1 != 1", "OrderBy": "(0|3) ASC, 1 ASC COLLATE latin1_swedish_ci, (2|4) ASC", - "Query": "select a, textcol1, b, weight_string(a), weight_string(b) from `user`", + "Query": "select a, textcol1, b, weight_string(a), weight_string(b) from `user` order by a asc, textcol1 asc, b asc", "ResultColumns": 3, "Table": "`user`" }, @@ -338,7 +338,7 @@ }, "FieldQuery": "select a, `user`.textcol1, b, weight_string(a), weight_string(b) from `user` where 1 != 1", "OrderBy": "(0|3) ASC, 1 ASC COLLATE latin1_swedish_ci, (2|4) ASC", - "Query": "select a, `user`.textcol1, b, weight_string(a), weight_string(b) from `user`", + "Query": "select a, `user`.textcol1, b, weight_string(a), weight_string(b) from `user` order by a asc, textcol1 asc, b asc", "ResultColumns": 3, "Table": "`user`" }, @@ -362,7 +362,7 @@ }, "FieldQuery": "select a, textcol1, b, textcol2, weight_string(a), weight_string(b) from `user` where 1 != 1", "OrderBy": "(0|4) ASC, 1 ASC COLLATE latin1_swedish_ci, (2|5) ASC, 3 ASC COLLATE latin1_swedish_ci", - "Query": "select a, textcol1, b, textcol2, weight_string(a), weight_string(b) from `user`", + "Query": "select a, textcol1, b, textcol2, weight_string(a), weight_string(b) from `user` order by a asc, textcol1 asc, b asc, textcol2 asc", "ResultColumns": 4, "Table": "`user`" }, @@ -391,7 +391,7 @@ }, "FieldQuery": "select id as foo, weight_string(id) from music where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select id as foo, weight_string(id) from music", + "Query": "select id as foo, weight_string(id) from music order by foo asc", "ResultColumns": 1, "Table": "music" }, @@ -542,7 +542,7 @@ "Sharded": true }, "FieldQuery": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where 1 != 1", - "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1", + "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1 order by a asc", "Table": "`user`", "Values": [ "INT64(1)" @@ -595,7 +595,7 @@ "Sharded": true }, "FieldQuery": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where 1 != 1", - "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1", + "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1 order by a asc", "Table": "`user`", "Values": [ "INT64(1)" @@ -713,7 +713,7 @@ "Sharded": true }, "FieldQuery": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where 1 != 1", - "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1", + "Query": "select `user`.col1 as a, `user`.col2, `user`.id from `user` where `user`.id = 1 order by RAND()", "Table": "`user`", "Values": [ "INT64(1)" @@ -1375,7 +1375,7 @@ }, "FieldQuery": "select id as foo, weight_string(id) from music where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select id as foo, weight_string(id) from music", + "Query": "select id as foo, weight_string(id) from music order by foo asc", "ResultColumns": 1, "Table": "music" }, @@ -1399,7 +1399,7 @@ }, "FieldQuery": "select id as foo, id2 as id, weight_string(id2) from music where 1 != 1", "OrderBy": "(1|2) ASC", - "Query": "select id as foo, id2 as id, weight_string(id2) from music", + "Query": "select id as foo, id2 as id, weight_string(id2) from music order by id asc", "ResultColumns": 2, "Table": "music" }, @@ -1429,7 +1429,7 @@ }, "FieldQuery": "select `name`, weight_string(`name`) from `user` where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select `name`, weight_string(`name`) from `user`", + "Query": "select `name`, weight_string(`name`) from `user` order by `name` asc", "Table": "`user`" }, { @@ -1538,7 +1538,8 @@ "Sharded": true }, "FieldQuery": "select count(id), num, weight_string(num) from `user` where 1 != 1 group by num, weight_string(num)", - "Query": "select count(id), num, weight_string(num) from `user` group by num, weight_string(num)", + "OrderBy": "(1|2) ASC", + "Query": "select count(id), num, weight_string(num) from `user` group by num, weight_string(num) order by num asc", "Table": "`user`" } ] @@ -1574,7 +1575,8 @@ "Sharded": true }, "FieldQuery": "select count(id), num, weight_string(num) from `user` where 1 != 1 group by num, weight_string(num)", - "Query": "select count(id), num, weight_string(num) from `user` group by num, weight_string(num)", + "OrderBy": "(1|2) ASC", + "Query": "select count(id), num, weight_string(num) from `user` group by num, weight_string(num) order by num asc", "Table": "`user`" } ] @@ -1607,7 +1609,7 @@ }, "FieldQuery": "select `name`, weight_string(`name`) from `user` where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select `name`, weight_string(`name`) from `user`", + "Query": "select `name`, weight_string(`name`) from `user` order by `name` asc", "Table": "`user`" }, { @@ -1644,7 +1646,7 @@ }, "FieldQuery": "select id, id, weight_string(id) from `user` where 1 != 1", "OrderBy": "(0|2) ASC", - "Query": "select id, id, weight_string(id) from `user`", + "Query": "select id, id, weight_string(id) from `user` order by id asc", "ResultColumns": 2, "Table": "`user`" }, @@ -1679,7 +1681,8 @@ "Sharded": true }, "FieldQuery": "select col, count(*), c1, weight_string(c1) from `user` where 1 != 1 group by col", - "Query": "select col, count(*), c1, weight_string(c1) from `user` group by col", + "OrderBy": "0 ASC", + "Query": "select col, count(*), c1, weight_string(c1) from `user` group by col order by col asc", "Table": "`user`" } ] @@ -1878,7 +1881,7 @@ }, "FieldQuery": "select id, id + 1, weight_string(id + 1) from `user` where 1 != 1", "OrderBy": "(1|2) ASC", - "Query": "select id, id + 1, weight_string(id + 1) from `user`", + "Query": "select id, id + 1, weight_string(id + 1) from `user` order by id + 1 asc", "ResultColumns": 1, "Table": "`user`" }, @@ -1902,7 +1905,7 @@ }, "FieldQuery": "select `user`.col1 as a, a collate utf8_general_ci, weight_string(a collate utf8_general_ci) from `user` where 1 != 1", "OrderBy": "(1|2) ASC", - "Query": "select `user`.col1 as a, a collate utf8_general_ci, weight_string(a collate utf8_general_ci) from `user`", + "Query": "select `user`.col1 as a, a collate utf8_general_ci, weight_string(a collate utf8_general_ci) from `user` order by a collate utf8_general_ci asc", "ResultColumns": 1, "Table": "`user`" }, @@ -1926,7 +1929,7 @@ }, "FieldQuery": "select id, id + 1, weight_string(id + 1) from `user` where 1 != 1", "OrderBy": "(1|2) ASC", - "Query": "select id, id + 1, weight_string(id + 1) from `user`", + "Query": "select id, id + 1, weight_string(id + 1) from `user` order by id + 1 asc", "ResultColumns": 1, "Table": "`user`" }, @@ -1950,7 +1953,7 @@ }, "FieldQuery": "select `user`.col1 as a, a collate utf8_general_ci, weight_string(a collate utf8_general_ci) from `user` where 1 != 1", "OrderBy": "(1|2) ASC", - "Query": "select `user`.col1 as a, a collate utf8_general_ci, weight_string(a collate utf8_general_ci) from `user`", + "Query": "select `user`.col1 as a, a collate utf8_general_ci, weight_string(a collate utf8_general_ci) from `user` order by a collate utf8_general_ci asc", "ResultColumns": 1, "Table": "`user`" }, @@ -2051,7 +2054,8 @@ "Sharded": true }, "FieldQuery": "select min(a.id), a.tcol1, weight_string(a.tcol1), weight_string(a.id) from `user` as a where 1 != 1 group by a.tcol1, weight_string(a.tcol1), weight_string(a.id)", - "Query": "select min(a.id), a.tcol1, weight_string(a.tcol1), weight_string(a.id) from `user` as a group by a.tcol1, weight_string(a.tcol1), weight_string(a.id)", + "OrderBy": "(1|2) ASC", + "Query": "select min(a.id), a.tcol1, weight_string(a.tcol1), weight_string(a.id) from `user` as a group by a.tcol1, weight_string(a.tcol1), weight_string(a.id) order by a.tcol1 asc", "Table": "`user`" }, { diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.json b/go/vt/vtgate/planbuilder/testdata/select_cases.json index 834bd750bcf..12f3ee7f112 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.json @@ -1000,7 +1000,7 @@ }, "FieldQuery": "select user_id, weight_string(user_id) from music where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select user_id, weight_string(user_id) from music", + "Query": "select user_id, weight_string(user_id) from music order by user_id asc limit :__upper_limit", "ResultColumns": 1, "Table": "music" } @@ -3212,7 +3212,7 @@ }, "FieldQuery": "select id, `name`, weight_string(id) from `user` where 1 != 1", "OrderBy": "(0|2) ASC", - "Query": "select id, `name`, weight_string(id) from `user` where `name` = 'aa'", + "Query": "select id, `name`, weight_string(id) from `user` where `name` = 'aa' order by id asc limit :__upper_limit", "ResultColumns": 2, "Table": "`user`" } @@ -4246,7 +4246,8 @@ "Sharded": true }, "FieldQuery": "select id, count(*) as b, req, weight_string(req), weight_string(id) from user_extra where 1 != 1 group by req, id, weight_string(req), weight_string(id)", - "Query": "select id, count(*) as b, req, weight_string(req), weight_string(id) from user_extra group by req, id, weight_string(req), weight_string(id)", + "OrderBy": "(2|3) ASC, (0|4) ASC", + "Query": "select id, count(*) as b, req, weight_string(req), weight_string(id) from user_extra group by req, id, weight_string(req), weight_string(id) order by req asc, id asc", "Table": "user_extra" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index b92e1fd18c5..358bb75e582 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -144,7 +144,7 @@ }, "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from `user`", + "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", "Table": "`user`" } ] @@ -162,7 +162,7 @@ }, "FieldQuery": "select id, weight_string(id) from music where 1 != 1", "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from music", + "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", "Table": "music" } ] @@ -288,7 +288,7 @@ }, "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select id, weight_string(id) from `user`", + "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", "Table": "`user`" } ] @@ -306,7 +306,7 @@ }, "FieldQuery": "select id, weight_string(id) from music where 1 != 1", "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from music", + "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", "Table": "music" } ] @@ -958,7 +958,7 @@ "Sharded": true }, "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt where 1 != 1", - "Query": "select id, weight_string(id) from (select id from `user` union select 3 from dual) as dt", + "Query": "select id, weight_string(id) from (select id from `user` union select 3 from dual) as dt limit :__upper_limit", "Table": "`user`, dual" } ] @@ -1095,7 +1095,7 @@ }, "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", "OrderBy": "(0|1) ASC", - "Query": "select id, weight_string(id) from `user`", + "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", "Table": "`user`" } ] @@ -1113,7 +1113,7 @@ }, "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from `user`", + "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", "Table": "`user`" } ] From bce1ff8419107bca77906b49345ef82437985e28 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Thu, 13 Jul 2023 09:26:20 +0200 Subject: [PATCH 14/44] merge UNION ALL as well Signed-off-by: Andres Taylor --- .../planbuilder/operators/SQL_builder.go | 40 ++- .../planbuilder/operators/horizon_planning.go | 56 ++-- .../planbuilder/operators/union_merging.go | 31 +- .../planbuilder/testdata/union_cases.json | 274 ++++++------------ 4 files changed, 184 insertions(+), 217 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/SQL_builder.go b/go/vt/vtgate/planbuilder/operators/SQL_builder.go index 9b63082d4a2..9af753c8804 100644 --- a/go/vt/vtgate/planbuilder/operators/SQL_builder.go +++ b/go/vt/vtgate/planbuilder/operators/SQL_builder.go @@ -578,10 +578,43 @@ func buildDerived(op *Horizon, qb *queryBuilder) error { if err != nil { return err } - sel := qb.sel.(*sqlparser.Select) // we can only handle SELECT in derived tables at the moment - qb.sel = nil sqlparser.RemoveKeyspace(op.Query) - opQuery := op.Query.(*sqlparser.Select) + + stmt := qb.sel + qb.sel = nil + switch sel := stmt.(type) { + case *sqlparser.Select: + return buildDerivedSelect(op, qb, sel) + case *sqlparser.Union: + return buildDerivedUnion(op, qb, sel) + + default: + panic(fmt.Sprintf("what is this? %v", stmt)) + } +} + +func buildDerivedUnion(op *Horizon, qb *queryBuilder, union *sqlparser.Union) error { + opQuery, ok := op.Query.(*sqlparser.Union) + if !ok { + return vterrors.VT12001("Horizon contained SELECT but statement was UNION") + } + + union.Limit = opQuery.Limit + union.OrderBy = opQuery.OrderBy + union.Distinct = opQuery.Distinct + + qb.addTableExpr(op.Alias, op.Alias, TableID(op), &sqlparser.DerivedTable{ + Select: union, + }, nil, op.ColumnAliases) + + return nil +} + +func buildDerivedSelect(op *Horizon, qb *queryBuilder, sel *sqlparser.Select) error { + opQuery, ok := op.Query.(*sqlparser.Select) + if !ok { + return vterrors.VT12001("Horizon contained UNION but statement was SELECT") + } sel.Limit = opQuery.Limit sel.OrderBy = opQuery.OrderBy sel.GroupBy = opQuery.GroupBy @@ -597,6 +630,7 @@ func buildDerived(op *Horizon, qb *queryBuilder) error { } } return nil + } func buildHorizon(op *Horizon, qb *queryBuilder) error { diff --git a/go/vt/vtgate/planbuilder/operators/horizon_planning.go b/go/vt/vtgate/planbuilder/operators/horizon_planning.go index d78c39ec89d..0689aa208f9 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_planning.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_planning.go @@ -147,7 +147,7 @@ func optimizeHorizonPlanning(ctx *plancontext.PlanningContext, root ops.Operator case *Filter: return tryPushingDownFilter(ctx, in) case *Distinct: - return tryPushingDownDistinct(ctx, in) + return tryPushingDownDistinct(in) case *Union: return tryPushDownUnion(ctx, in) default: @@ -597,7 +597,7 @@ func pushFilterUnderProjection(ctx *plancontext.PlanningContext, filter *Filter, } -func tryPushingDownDistinct(ctx *plancontext.PlanningContext, in *Distinct) (ops.Operator, *rewrite.ApplyResult, error) { +func tryPushingDownDistinct(in *Distinct) (ops.Operator, *rewrite.ApplyResult, error) { if in.Pushed { return in, rewrite.SameTree, nil } @@ -648,34 +648,40 @@ func isDistinct(op ops.Operator) bool { } func tryPushDownUnion(ctx *plancontext.PlanningContext, op *Union) (ops.Operator, *rewrite.ApplyResult, error) { + var sources []ops.Operator + var selects []sqlparser.SelectExprs + var err error + if op.distinct { - sources, selects, err := mergeUnionInputInAnyOrder(ctx, op) - if err != nil { - return nil, nil, err - } - if len(sources) == 1 { - result := sources[0] - if op.distinct { - result = &Distinct{ - Source: result, - Original: true, - } - } + sources, selects, err = mergeUnionInputInAnyOrder(ctx, op) + } else { + sources, selects, err = mergeUnionInputsInOrder(ctx, op) + } + if err != nil { + return nil, nil, err + } - return result, rewrite.NewTree("pushed union under route", op), nil - } - var result *rewrite.ApplyResult - if len(sources) != len(op.Sources) { - result = rewrite.NewTree("merged union inputs", op) + if len(sources) == 1 { + result := sources[0] + if op.distinct { + result = &Distinct{ + Source: result, + Original: true, + } } - return &Union{ - Sources: sources, - Selects: selects, - distinct: true, - }, result, nil + + return result, rewrite.NewTree("pushed union under route", op), nil + } + + if len(sources) == len(op.Sources) { + return op, rewrite.SameTree, nil } - return op, rewrite.SameTree, nil + return &Union{ + Sources: sources, + Selects: selects, + distinct: op.distinct, + }, rewrite.NewTree("merged union inputs", op), nil } // makeSureOutputIsCorrect uses the original Horizon to make sure that the output columns line up with what the user asked for diff --git a/go/vt/vtgate/planbuilder/operators/union_merging.go b/go/vt/vtgate/planbuilder/operators/union_merging.go index 3d12c851daa..55e66c5c3f6 100644 --- a/go/vt/vtgate/planbuilder/operators/union_merging.go +++ b/go/vt/vtgate/planbuilder/operators/union_merging.go @@ -39,7 +39,9 @@ func mergeUnionInputInAnyOrder(ctx *plancontext.PlanningContext, op *Union) ([]o if j <= idx { continue } - newPlan, err := mergeUnionInputs(ctx, srcA, srcB, nil, nil, op.distinct) + selA := selects[idx] + selB := selects[j] + newPlan, err := mergeUnionInputs(ctx, srcA, srcB, selA, selB, op.distinct) if err != nil { return nil, nil, err } @@ -71,6 +73,33 @@ func mergeUnionInputInAnyOrder(ctx *plancontext.PlanningContext, op *Union) ([]o return sources, selects, nil } +func mergeUnionInputsInOrder(ctx *plancontext.PlanningContext, op *Union) ([]ops.Operator, []sqlparser.SelectExprs, error) { + sources := op.Sources + selects := op.Selects + for { + merged := false + for i := 0; i < len(sources)-1; i++ { + j := i + 1 + srcA, selA := sources[i], selects[i] + srcB, selB := sources[j], selects[j] + newPlan, err := mergeUnionInputs(ctx, srcA, srcB, selA, selB, op.distinct) + if err != nil { + return nil, nil, err + } + if newPlan != nil { + sources[i] = newPlan + merged = true + sources = append(sources[:i+1], sources[j+1:]...) + } + } + if !merged { + break + } + } + + return sources, selects, nil +} + // mergeUnionInputs checks whether two operators can be merged into a single one. // If they can be merged, a new operator with the merged routing is returned // If they cannot be merged, nil is returned. diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 358bb75e582..05a07be7aef 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -6,31 +6,15 @@ "QueryType": "SELECT", "Original": "select id from user union all select id from music", "Instructions": { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id from `user` where 1 != 1", - "Query": "select id from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id from music where 1 != 1", - "Query": "select id from music", - "Table": "music" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from `user` where 1 != 1 union all select id from music where 1 != 1", + "Query": "select id from `user` union all select id from music", + "Table": "`user`, music" }, "TablesUsed": [ "user.music", @@ -77,39 +61,19 @@ "QueryType": "SELECT", "Original": "select id from user where id = 1 union all select id from user where id = 5", "Instructions": { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id from `user` where 1 != 1", - "Query": "select id from `user` where id = 1", - "Table": "`user`", - "Values": [ - "INT64(1)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id from `user` where 1 != 1", - "Query": "select id from `user` where id = 5", - "Table": "`user`", - "Values": [ - "INT64(5)" - ], - "Vindex": "user_index" - } - ] + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from `user` where 1 != 1 union all select id from `user` where 1 != 1", + "Query": "select id from `user` where id = 1 union all select id from `user` where id = 5", + "Table": "`user`", + "Values": [ + "INT64(5)" + ], + "Vindex": "user_index" }, "TablesUsed": [ "user.user" @@ -184,31 +148,15 @@ "QueryType": "SELECT", "Original": "select col1, col2 from user union all select col1, col2 from user_extra", "Instructions": { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select col1, col2 from `user` where 1 != 1", - "Query": "select col1, col2 from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select col1, col2 from user_extra where 1 != 1", - "Query": "select col1, col2 from user_extra", - "Table": "user_extra" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select col1, col2 from `user` where 1 != 1 union all select col1, col2 from user_extra where 1 != 1", + "Query": "select col1, col2 from `user` union all select col1, col2 from user_extra", + "Table": "`user`, user_extra" }, "TablesUsed": [ "user.user", @@ -219,7 +167,25 @@ { "comment": "union operations in subqueries (FROM)", "query": "select * from (select * from user union all select * from user_extra) as t", - "plan": "VT12001: unsupported: '*' expression in cross-shard query" + "plan": { + "QueryType": "SELECT", + "Original": "select * from (select * from user union all select * from user_extra) as t", + "Instructions": { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select * from (select * from `user` where 1 != 1 union all select * from user_extra where 1 != 1) as t where 1 != 1", + "Query": "select * from (select * from `user` union all select * from user_extra) as t", + "Table": "`user`, user_extra" + }, + "TablesUsed": [ + "user.user", + "user.user_extra" + ] + } }, { "comment": "union operations in derived table, without star expression (FROM)¡", @@ -228,31 +194,15 @@ "QueryType": "SELECT", "Original": "select col1,col2 from (select col1, col2 from user union all select col1, col2 from user_extra) as t", "Instructions": { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select col1, col2 from `user` where 1 != 1", - "Query": "select col1, col2 from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select col1, col2 from user_extra where 1 != 1", - "Query": "select col1, col2 from user_extra", - "Table": "user_extra" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select col1, col2 from (select col1, col2 from `user` where 1 != 1 union all select col1, col2 from user_extra where 1 != 1) as t where 1 != 1", + "Query": "select col1, col2 from (select col1, col2 from `user` union all select col1, col2 from user_extra) as t", + "Table": "`user`, user_extra" }, "TablesUsed": [ "user.user", @@ -328,35 +278,15 @@ "QueryType": "SELECT", "Original": "select id from user where id = 1 union select id from user where id = 1 union all select id from user", "Instructions": { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id from `user` where 1 != 1 union select id from `user` where 1 != 1", - "Query": "select id from `user` where id = 1 union select id from `user` where id = 1", - "Table": "`user`", - "Values": [ - "INT64(1)" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id from `user` where 1 != 1", - "Query": "select id from `user`", - "Table": "`user`" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from `user` where 1 != 1 union select id from `user` where 1 != 1 union all select id from `user` where 1 != 1", + "Query": "select id from `user` where id = 1 union select id from `user` where id = 1 union all select id from `user`", + "Table": "`user`" }, "TablesUsed": [ "user.user" @@ -1484,31 +1414,15 @@ "QueryType": "SELECT", "Original": "select foo, foo, foo from user union all select bar, baz, toto from music", "Instructions": { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select foo, foo, foo from `user` where 1 != 1", - "Query": "select foo, foo, foo from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select bar, baz, toto from music where 1 != 1", - "Query": "select bar, baz, toto from music", - "Table": "music" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select foo, foo, foo from `user` where 1 != 1 union all select bar, baz, toto from music where 1 != 1", + "Query": "select foo, foo, foo from `user` union all select bar, baz, toto from music", + "Table": "`user`, music" }, "TablesUsed": [ "user.music", @@ -1523,31 +1437,15 @@ "QueryType": "SELECT", "Original": "select bar, baz, toto from music union all select foo, foo, foo from user", "Instructions": { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select bar, baz, toto from music where 1 != 1", - "Query": "select bar, baz, toto from music", - "Table": "music" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select foo, foo, foo from `user` where 1 != 1", - "Query": "select foo, foo, foo from `user`", - "Table": "`user`" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select bar, baz, toto from music where 1 != 1 union all select foo, foo, foo from `user` where 1 != 1", + "Query": "select bar, baz, toto from music union all select foo, foo, foo from `user`", + "Table": "`user`, music" }, "TablesUsed": [ "user.music", From e478eaf59f5b0ee4988cfc6a2d6bc77ff8091591 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Thu, 13 Jul 2023 17:44:14 +0200 Subject: [PATCH 15/44] add FindCol to the Operator interface Signed-off-by: Andres Taylor --- .../planbuilder/operators/aggregator.go | 4 +-- .../planbuilder/operators/apply_join.go | 12 +++++++ .../vtgate/planbuilder/operators/distinct.go | 4 +++ go/vt/vtgate/planbuilder/operators/filter.go | 4 +++ go/vt/vtgate/planbuilder/operators/horizon.go | 14 +++++++++ go/vt/vtgate/planbuilder/operators/limit.go | 3 ++ .../planbuilder/operators/offset_planning.go | 31 +++---------------- .../vtgate/planbuilder/operators/operator.go | 3 ++ go/vt/vtgate/planbuilder/operators/ops/op.go | 2 ++ .../vtgate/planbuilder/operators/ordering.go | 4 +++ .../planbuilder/operators/projection.go | 9 +++--- go/vt/vtgate/planbuilder/operators/route.go | 5 ++- go/vt/vtgate/planbuilder/operators/table.go | 15 +++++++++ go/vt/vtgate/planbuilder/operators/union.go | 15 +++++++++ go/vt/vtgate/planbuilder/operators/vindex.go | 10 ++++++ 15 files changed, 102 insertions(+), 33 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/aggregator.go b/go/vt/vtgate/planbuilder/operators/aggregator.go index bc60daf3df5..6e6f349ae01 100644 --- a/go/vt/vtgate/planbuilder/operators/aggregator.go +++ b/go/vt/vtgate/planbuilder/operators/aggregator.go @@ -118,7 +118,7 @@ func (a *Aggregator) isDerived() bool { return a.TableID != nil } -func (a *Aggregator) findCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { +func (a *Aggregator) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { if a.isDerived() { derivedTBL, err := ctx.SemTable.TableInfoFor(*a.TableID) if err != nil { @@ -133,7 +133,7 @@ func (a *Aggregator) findCol(ctx *plancontext.PlanningContext, expr sqlparser.Ex } func (a *Aggregator) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, _, addToGroupBy bool) (ops.Operator, int, error) { - offset, err := a.findCol(ctx, expr.Expr) + offset, err := a.FindCol(ctx, expr.Expr) if err != nil { return nil, 0, err } diff --git a/go/vt/vtgate/planbuilder/operators/apply_join.go b/go/vt/vtgate/planbuilder/operators/apply_join.go index 2e4106524d3..31bcc32abe7 100644 --- a/go/vt/vtgate/planbuilder/operators/apply_join.go +++ b/go/vt/vtgate/planbuilder/operators/apply_join.go @@ -228,7 +228,19 @@ func (a *ApplyJoin) getJoinColumnFor(ctx *plancontext.PlanningContext, e *sqlpar return } +func (a *ApplyJoin) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { + offset, found := canReuseColumn(ctx, a.ColumnsAST, expr, joinColumnToExpr) + if !found { + return -1, nil + } + return offset, nil +} + func (a *ApplyJoin) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, _, addToGroupBy bool) (ops.Operator, int, error) { + if offset, err := a.FindCol(ctx, expr.Expr); err != nil || offset != -1 { + return a, offset, err + } + if offset, found := canReuseColumn(ctx, a.ColumnsAST, expr.Expr, joinColumnToExpr); found { return a, offset, nil } diff --git a/go/vt/vtgate/planbuilder/operators/distinct.go b/go/vt/vtgate/planbuilder/operators/distinct.go index 23185fcf8ac..b03047d8d7b 100644 --- a/go/vt/vtgate/planbuilder/operators/distinct.go +++ b/go/vt/vtgate/planbuilder/operators/distinct.go @@ -115,6 +115,10 @@ func (d *Distinct) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.A return d, offset, nil } +func (d *Distinct) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { + return d.Source.FindCol(ctx, expr) +} + func (d *Distinct) GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { return d.Source.GetColumns(ctx) } diff --git a/go/vt/vtgate/planbuilder/operators/filter.go b/go/vt/vtgate/planbuilder/operators/filter.go index 11678dd171b..203e2ca2d79 100644 --- a/go/vt/vtgate/planbuilder/operators/filter.go +++ b/go/vt/vtgate/planbuilder/operators/filter.go @@ -96,6 +96,10 @@ func (f *Filter) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.Ali return f, offset, nil } +func (f *Filter) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { + return f.Source.FindCol(ctx, expr) +} + func (f *Filter) GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { return f.Source.GetColumns(ctx) } diff --git a/go/vt/vtgate/planbuilder/operators/horizon.go b/go/vt/vtgate/planbuilder/operators/horizon.go index 28a99d7c847..9536a3ca4f0 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon.go +++ b/go/vt/vtgate/planbuilder/operators/horizon.go @@ -196,6 +196,20 @@ func canReuseColumn[T any]( return } +func (h *Horizon) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { + for idx, se := range sqlparser.GetFirstSelect(h.Query).SelectExprs { + ae, ok := se.(*sqlparser.AliasedExpr) + if !ok { + return 0, vterrors.VT09015() + } + if ctx.SemTable.EqualsExprWithDeps(ae.Expr, expr) { + return idx, nil + } + } + + return -1, nil +} + func (h *Horizon) GetColumns(*plancontext.PlanningContext) (exprs []*sqlparser.AliasedExpr, err error) { for _, expr := range sqlparser.GetFirstSelect(h.Query).SelectExprs { ae, ok := expr.(*sqlparser.AliasedExpr) diff --git a/go/vt/vtgate/planbuilder/operators/limit.go b/go/vt/vtgate/planbuilder/operators/limit.go index 27ff0f933cc..5b219c2a4e3 100644 --- a/go/vt/vtgate/planbuilder/operators/limit.go +++ b/go/vt/vtgate/planbuilder/operators/limit.go @@ -64,6 +64,9 @@ func (l *Limit) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.Alia l.Source = newSrc return l, offset, nil } +func (l *Limit) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { + return l.Source.FindCol(ctx, expr) +} func (l *Limit) GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { return l.Source.GetColumns(ctx) diff --git a/go/vt/vtgate/planbuilder/operators/offset_planning.go b/go/vt/vtgate/planbuilder/operators/offset_planning.go index bf7c352c6a9..4e6fdba5eac 100644 --- a/go/vt/vtgate/planbuilder/operators/offset_planning.go +++ b/go/vt/vtgate/planbuilder/operators/offset_planning.go @@ -19,8 +19,6 @@ package operators import ( "fmt" - "golang.org/x/exp/slices" - "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" @@ -74,39 +72,23 @@ func planOffsetsOnJoins(ctx *plancontext.PlanningContext, op ops.Operator) error // useOffsets rewrites an expression to use values from the input func useOffsets(ctx *plancontext.PlanningContext, expr sqlparser.Expr, op ops.Operator) (sqlparser.Expr, error) { - in := op.Inputs()[0] - columns, err := in.GetColumns(ctx) - if err != nil { - return nil, err - } - var exprOffset *sqlparser.Offset + in := op.Inputs()[0] found := func(e sqlparser.Expr, offset int) { exprOffset = sqlparser.NewOffset(offset, e) } notFound := func(e sqlparser.Expr) error { _, addToGroupBy := e.(*sqlparser.ColName) - var offset int - in, offset, err = in.AddColumn(ctx, aeWrap(e), true, addToGroupBy) - if err != nil { - return err - } - op.SetInputs([]ops.Operator{in}) - columns, err = in.GetColumns(ctx) + newSrc, offset, err := in.AddColumn(ctx, aeWrap(e), true, addToGroupBy) if err != nil { return err } + op.SetInputs([]ops.Operator{newSrc}) exprOffset = sqlparser.NewOffset(offset, e) return nil } - getColumns := func() []*sqlparser.AliasedExpr { return columns } - findCol := func(ctx *plancontext.PlanningContext, e sqlparser.Expr) (int, error) { - return slices.IndexFunc(getColumns(), func(expr *sqlparser.AliasedExpr) bool { - return ctx.SemTable.EqualsExprWithDeps(expr.Expr, e) - }), nil - } - visitor := getVisitor(ctx, findCol, found, notFound) + visitor := getVisitor(ctx, in.FindCol, found, notFound) // The cursor replace is not available while walking `down`, so `up` is used to do the replacement. up := func(cursor *sqlparser.CopyOnWriteCursor) { @@ -117,9 +99,6 @@ func useOffsets(ctx *plancontext.PlanningContext, expr sqlparser.Expr, op ops.Op } rewritten := sqlparser.CopyOnRewrite(expr, visitor, up, ctx.SemTable.CopyDependenciesOnSQLNodes) - if err != nil { - return nil, err - } return rewritten.(sqlparser.Expr), nil } @@ -146,7 +125,7 @@ func addColumnsToInput(ctx *plancontext.PlanningContext, root ops.Operator) (ops addedColumns = true return nil } - visitor := getVisitor(ctx, proj.findCol, found, notFound) + visitor := getVisitor(ctx, proj.FindCol, found, notFound) for _, expr := range filter.Predicates { _ = sqlparser.CopyOnRewrite(expr, visitor, nil, ctx.SemTable.CopyDependenciesOnSQLNodes) diff --git a/go/vt/vtgate/planbuilder/operators/operator.go b/go/vt/vtgate/planbuilder/operators/operator.go index 9ae3f232ad3..9d2033d483a 100644 --- a/go/vt/vtgate/planbuilder/operators/operator.go +++ b/go/vt/vtgate/planbuilder/operators/operator.go @@ -112,6 +112,9 @@ func (noColumns) AddColumn(*plancontext.PlanningContext, *sqlparser.AliasedExpr, func (noColumns) GetColumns(*plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { return nil, vterrors.VT13001("noColumns operators have no column") } +func (noColumns) FindCol(*plancontext.PlanningContext, sqlparser.Expr) (int, error) { + return 0, vterrors.VT13001("noColumns operators have no column") +} func (noColumns) GetSelectExprs(*plancontext.PlanningContext) (sqlparser.SelectExprs, error) { return nil, vterrors.VT13001("noColumns operators have no column") diff --git a/go/vt/vtgate/planbuilder/operators/ops/op.go b/go/vt/vtgate/planbuilder/operators/ops/op.go index 8ae713f4c4c..b031403133c 100644 --- a/go/vt/vtgate/planbuilder/operators/ops/op.go +++ b/go/vt/vtgate/planbuilder/operators/ops/op.go @@ -48,6 +48,8 @@ type ( // The offset to the column is returned. AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, reuseExisting, addToGroupBy bool) (Operator, int, error) + FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) + GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.SelectExprs, error) diff --git a/go/vt/vtgate/planbuilder/operators/ordering.go b/go/vt/vtgate/planbuilder/operators/ordering.go index d47cbcafeca..ca895f4bb2c 100644 --- a/go/vt/vtgate/planbuilder/operators/ordering.go +++ b/go/vt/vtgate/planbuilder/operators/ordering.go @@ -73,6 +73,10 @@ func (o *Ordering) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.A return o, offset, nil } +func (o *Ordering) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { + return o.Source.FindCol(ctx, expr) +} + func (o *Ordering) GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { return o.Source.GetColumns(ctx) } diff --git a/go/vt/vtgate/planbuilder/operators/projection.go b/go/vt/vtgate/planbuilder/operators/projection.go index d4a84f0bce3..9e61a1ae197 100644 --- a/go/vt/vtgate/planbuilder/operators/projection.go +++ b/go/vt/vtgate/planbuilder/operators/projection.go @@ -116,7 +116,7 @@ func (p *Projection) isDerived() bool { return p.TableID != nil } -func (p *Projection) findCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { +func (p *Projection) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { if p.isDerived() { derivedTBL, err := ctx.SemTable.TableInfoFor(*p.TableID) if err != nil { @@ -131,7 +131,7 @@ func (p *Projection) findCol(ctx *plancontext.PlanningContext, expr sqlparser.Ex } func (p *Projection) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, _, addToGroupBy bool) (ops.Operator, int, error) { - offset, err := p.findCol(ctx, expr.Expr) + offset, err := p.FindCol(ctx, expr.Expr) if err != nil { return nil, 0, err } @@ -310,7 +310,8 @@ func (p *Projection) planOffsets(ctx *plancontext.PlanningContext) error { } // first step is to replace the expressions we expect to get from our input with the offsets for these - rewritten, err := useOffsets(ctx, col.GetExpr(), p) + expr := col.GetExpr() + rewritten, err := useOffsets(ctx, expr, p) if err != nil { return err } @@ -319,7 +320,7 @@ func (p *Projection) planOffsets(ctx *plancontext.PlanningContext) error { if ok { // we got a pure offset back. No need to do anything else p.Projections[i] = Offset{ - Expr: col.GetExpr(), + Expr: expr, Offset: offset.V, } continue diff --git a/go/vt/vtgate/planbuilder/operators/route.go b/go/vt/vtgate/planbuilder/operators/route.go index 4baf090c505..1ed7d3f7439 100644 --- a/go/vt/vtgate/planbuilder/operators/route.go +++ b/go/vt/vtgate/planbuilder/operators/route.go @@ -585,7 +585,6 @@ type selectExpressions interface { ops.Operator addColumnWithoutPushing(expr *sqlparser.AliasedExpr, addToGroupBy bool) int isDerived() bool - findCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) } // addColumnToInput adds a column to an operator without pushing it down. @@ -636,6 +635,10 @@ func addColumnToInput(ctx *plancontext.PlanningContext, operator ops.Operator, e } } +func (r *Route) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { + return r.Source.FindCol(ctx, expr) +} + func (r *Route) GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { return r.Source.GetColumns(ctx) } diff --git a/go/vt/vtgate/planbuilder/operators/table.go b/go/vt/vtgate/planbuilder/operators/table.go index 820b0250c51..09f5927a574 100644 --- a/go/vt/vtgate/planbuilder/operators/table.go +++ b/go/vt/vtgate/planbuilder/operators/table.go @@ -77,6 +77,21 @@ func (to *Table) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.Ali return to, offset, nil } +func (to *Table) FindCol(_ *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { + colToFind, ok := expr.(*sqlparser.ColName) + if !ok { + return -1, nil + } + + for idx, colName := range to.Columns { + if colName.Name.Equal(colToFind.Name) { + return idx, nil + } + } + + return -1, nil +} + func (to *Table) GetColumns(*plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { return slice.Map(to.Columns, colNameToExpr), nil } diff --git a/go/vt/vtgate/planbuilder/operators/union.go b/go/vt/vtgate/planbuilder/operators/union.go index d69c6afb664..c555c74b90e 100644 --- a/go/vt/vtgate/planbuilder/operators/union.go +++ b/go/vt/vtgate/planbuilder/operators/union.go @@ -258,6 +258,21 @@ func (u *Union) addWeightStringToOffset(ctx *plancontext.PlanningContext, argIdx return } +func (u *Union) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { + columns, err := u.GetColumns(ctx) + if err != nil { + return 0, err + } + + for idx, col := range columns { + if ctx.SemTable.EqualsExprWithDeps(expr, col.Expr) { + return idx, nil + } + } + + return -1, nil +} + func (u *Union) GetColumns(ctx *plancontext.PlanningContext) (result []*sqlparser.AliasedExpr, err error) { if u.columns != nil { return u.columns, nil diff --git a/go/vt/vtgate/planbuilder/operators/vindex.go b/go/vt/vtgate/planbuilder/operators/vindex.go index 36b6002d1d6..2864110dc0b 100644 --- a/go/vt/vtgate/planbuilder/operators/vindex.go +++ b/go/vt/vtgate/planbuilder/operators/vindex.go @@ -82,6 +82,16 @@ func colNameToExpr(c *sqlparser.ColName) *sqlparser.AliasedExpr { } } +func (v *Vindex) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { + for idx, col := range v.Columns { + if ctx.SemTable.EqualsExprWithDeps(expr, col) { + return idx, nil + } + } + + return -1, nil +} + func (v *Vindex) GetColumns(*plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { return slice.Map(v.Columns, colNameToExpr), nil } From 5111b7f1ea7a6cba1e6c2589c34f6e57fdd2a20d Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Fri, 14 Jul 2023 13:51:16 +0530 Subject: [PATCH 16/44] create derived projection on top of union on horizon expansion Signed-off-by: Harshit Gangal --- go/vt/sqlparser/ast_funcs.go | 13 + go/vt/vtgate/evalengine/translate.go | 2 +- .../planbuilder/operators/SQL_builder.go | 5 +- go/vt/vtgate/planbuilder/operators/ast2op.go | 21 +- go/vt/vtgate/planbuilder/operators/horizon.go | 35 +- .../operators/horizon_expanding.go | 12 + .../planbuilder/operators/horizon_planning.go | 35 +- .../planbuilder/operators/projection.go | 8 + go/vt/vtgate/planbuilder/operators/union.go | 43 ++- .../planbuilder/operators/union_merging.go | 37 +- .../planbuilder/testdata/dml_cases.json | 2 +- .../testdata/info_schema57_cases.json | 112 +++--- .../testdata/info_schema80_cases.json | 112 +++--- .../planbuilder/testdata/select_cases.json | 50 +-- .../planbuilder/testdata/union_cases.json | 350 ++++++------------ go/vt/vtgate/semantics/derived_table.go | 26 +- go/vt/vtgate/semantics/table_collector.go | 5 +- 17 files changed, 447 insertions(+), 421 deletions(-) diff --git a/go/vt/sqlparser/ast_funcs.go b/go/vt/sqlparser/ast_funcs.go index 63b0a9c4811..c096af3848b 100644 --- a/go/vt/sqlparser/ast_funcs.go +++ b/go/vt/sqlparser/ast_funcs.go @@ -2504,3 +2504,16 @@ func (ty KillType) ToString() string { return ConnectionStr } } + +func GetColumnNames(exprs SelectExprs) (expanded bool, selectExprs SelectExprs) { + for _, col := range exprs { + switch col := col.(type) { + case *AliasedExpr: + expr := NewColName(col.ColumnName()) + selectExprs = append(selectExprs, &AliasedExpr{Expr: expr}) + default: + return false, exprs + } + } + return true, selectExprs +} diff --git a/go/vt/vtgate/evalengine/translate.go b/go/vt/vtgate/evalengine/translate.go index 7a63899b318..e07b138f848 100644 --- a/go/vt/vtgate/evalengine/translate.go +++ b/go/vt/vtgate/evalengine/translate.go @@ -211,7 +211,7 @@ func (ast *astCompiler) translateColOffset(col *sqlparser.Offset) (Expr, error) func (ast *astCompiler) translateColName(colname *sqlparser.ColName) (Expr, error) { if ast.cfg.ResolveColumn == nil { - return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "cannot lookup column (column access not supported here)") + return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "cannot lookup column '%s' (column access not supported here)", sqlparser.String(colname)) } idx, err := ast.cfg.ResolveColumn(colname) if err != nil { diff --git a/go/vt/vtgate/planbuilder/operators/SQL_builder.go b/go/vt/vtgate/planbuilder/operators/SQL_builder.go index 9af753c8804..2893abeb3f4 100644 --- a/go/vt/vtgate/planbuilder/operators/SQL_builder.go +++ b/go/vt/vtgate/planbuilder/operators/SQL_builder.go @@ -131,13 +131,14 @@ func (qb *queryBuilder) pushUnionInsideDerived() { Lateral: false, Select: qb.sel, } - qb.sel = &sqlparser.Select{ + sel := &sqlparser.Select{ From: []sqlparser.TableExpr{&sqlparser.AliasedTableExpr{ Expr: dt, As: sqlparser.NewIdentifierCS("dt"), }}, - SelectExprs: sqlparser.CloneSelectExprs(sqlparser.GetFirstSelect(qb.sel).SelectExprs), } + sel.SelectExprs = unionSelects(sqlparser.GetFirstSelect(qb.sel).SelectExprs) + qb.sel = sel } func checkUnionColumnByName(column *sqlparser.ColName, sel sqlparser.SelectStatement) error { diff --git a/go/vt/vtgate/planbuilder/operators/ast2op.go b/go/vt/vtgate/planbuilder/operators/ast2op.go index 2194625520c..6259f532599 100644 --- a/go/vt/vtgate/planbuilder/operators/ast2op.go +++ b/go/vt/vtgate/planbuilder/operators/ast2op.go @@ -100,16 +100,23 @@ func createOperatorFromUnion(ctx *plancontext.PlanningContext, node *sqlparser.U return nil, err } - lexprs := sqlparser.GetFirstSelect(node.Left).SelectExprs - rexprs := sqlparser.GetFirstSelect(node.Right).SelectExprs - union := &Union{ - distinct: node.Distinct, - Sources: []ops.Operator{opLHS, opRHS}, - Selects: []sqlparser.SelectExprs{lexprs, rexprs}, - } + lexprs := getExpressions(node.Left) + rexprs := getExpressions(node.Right) + + union := newUnion([]ops.Operator{opLHS, opRHS}, []sqlparser.SelectExprs{lexprs, rexprs}, node.Distinct) return &Horizon{Source: union, Query: node}, nil } +func getExpressions(stmt sqlparser.SelectStatement) sqlparser.SelectExprs { + switch stmt := stmt.(type) { + case *sqlparser.Select: + return stmt.SelectExprs + case *sqlparser.Union: + return unionSelects(sqlparser.GetFirstSelect(stmt).SelectExprs) + } + return nil +} + func createOperatorFromUpdate(ctx *plancontext.PlanningContext, updStmt *sqlparser.Update) (ops.Operator, error) { tableInfo, qt, err := createQueryTableForDML(ctx, updStmt.TableExprs[0], updStmt.Where) if err != nil { diff --git a/go/vt/vtgate/planbuilder/operators/horizon.go b/go/vt/vtgate/planbuilder/operators/horizon.go index 9536a3ca4f0..d859d1d1fe9 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon.go +++ b/go/vt/vtgate/planbuilder/operators/horizon.go @@ -211,12 +211,37 @@ func (h *Horizon) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) } func (h *Horizon) GetColumns(*plancontext.PlanningContext) (exprs []*sqlparser.AliasedExpr, err error) { - for _, expr := range sqlparser.GetFirstSelect(h.Query).SelectExprs { - ae, ok := expr.(*sqlparser.AliasedExpr) - if !ok { - return nil, vterrors.VT09015() + switch sel := h.Query.(type) { + case *sqlparser.Select: + for _, expr := range sel.SelectExprs { + ae, ok := expr.(*sqlparser.AliasedExpr) + if !ok { + return nil, vterrors.VT09015() + } + exprs = append(exprs, ae) + } + case *sqlparser.Union: + selectExprs := unionSelects(sqlparser.GetFirstSelect(h.Query).SelectExprs) + for _, expr := range selectExprs { + ae, ok := expr.(*sqlparser.AliasedExpr) + if !ok { + return nil, vterrors.VT09015() + } + exprs = append(exprs, ae) + } + } + return exprs, nil +} + +func unionSelects(exprs sqlparser.SelectExprs) (selectExprs sqlparser.SelectExprs) { + for _, col := range exprs { + switch col := col.(type) { + case *sqlparser.AliasedExpr: + expr := sqlparser.NewColName(col.ColumnName()) + selectExprs = append(selectExprs, aeWrap(expr)) + default: + selectExprs = append(selectExprs, col) } - exprs = append(exprs, ae) } return } diff --git a/go/vt/vtgate/planbuilder/operators/horizon_expanding.go b/go/vt/vtgate/planbuilder/operators/horizon_expanding.go index 265dc337803..e6bef2aa5fe 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_expanding.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_expanding.go @@ -60,6 +60,18 @@ func expandUnionHorizon(ctx *plancontext.PlanningContext, horizon *Horizon, unio } } + if horizon.TableId != nil { + op = &Projection{ + Source: op, + TableID: horizon.TableId, + Alias: horizon.Alias, + } + } + + if op == horizon.Source { + return op, rewrite.NewTree("removed UNION horizon not used", op), nil + } + return op, rewrite.NewTree("expand UNION horizon into smaller components", op), nil } diff --git a/go/vt/vtgate/planbuilder/operators/horizon_planning.go b/go/vt/vtgate/planbuilder/operators/horizon_planning.go index 0689aa208f9..c2f37b557c7 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_planning.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_planning.go @@ -77,6 +77,11 @@ func tryHorizonPlanning(ctx *plancontext.PlanningContext, root ops.Operator) (ou return nil, err } + if rewrite.DebugOperatorTree { + fmt.Println("After offset planning:") + fmt.Println(ops.ToTree(output)) + } + output, err = makeSureOutputIsCorrect(ctx, root, output) if err != nil { return nil, err @@ -604,12 +609,13 @@ func tryPushingDownDistinct(in *Distinct) (ops.Operator, *rewrite.ApplyResult, e in.Pushed = true switch src := in.Source.(type) { case *Route: + if isDistinct(src.Source) && src.IsSingleShard() { + return src, rewrite.NewTree("distinct not needed", in), nil + } if src.IsSingleShard() || !in.Original { return rewrite.Swap(in, src, "push distinct under route") } - if isDistinct(src.Source) { - return in, rewrite.SameTree, nil - } + src.Source = &Distinct{Source: src.Source} return in, rewrite.NewTree("added distinct under route - kept original", src), nil @@ -642,6 +648,8 @@ func isDistinct(op ops.Operator) bool { return true case *Union: return op.distinct + case *Horizon: + return op.Query.IsDistinct() default: return false } @@ -662,26 +670,21 @@ func tryPushDownUnion(ctx *plancontext.PlanningContext, op *Union) (ops.Operator } if len(sources) == 1 { - result := sources[0] - if op.distinct { - result = &Distinct{ - Source: result, - Original: true, - } + result := sources[0].(*Route) + if result.IsSingleShard() || !op.distinct { + return result, rewrite.NewTree("pushed union under route", op), nil } - return result, rewrite.NewTree("pushed union under route", op), nil + return &Distinct{ + Source: result, + Original: true, + }, rewrite.NewTree("pushed union under route", op), nil } if len(sources) == len(op.Sources) { return op, rewrite.SameTree, nil } - - return &Union{ - Sources: sources, - Selects: selects, - distinct: op.distinct, - }, rewrite.NewTree("merged union inputs", op), nil + return newUnion(sources, selects, op.distinct), rewrite.NewTree("merged union inputs", op), nil } // makeSureOutputIsCorrect uses the original Horizon to make sure that the output columns line up with what the user asked for diff --git a/go/vt/vtgate/planbuilder/operators/projection.go b/go/vt/vtgate/planbuilder/operators/projection.go index 9e61a1ae197..44c1b3b5722 100644 --- a/go/vt/vtgate/planbuilder/operators/projection.go +++ b/go/vt/vtgate/planbuilder/operators/projection.go @@ -139,6 +139,14 @@ func (p *Projection) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser return p, offset, nil } + if p.TableID != nil { + vt, err := ctx.SemTable.TableInfoFor(*p.TableID) + if err != nil { + return nil, 0, err + } + expr.Expr = semantics.RewriteDerivedTableExpression(expr.Expr, vt) + } + sourceOp, offset, err := p.Source.AddColumn(ctx, expr, true, addToGroupBy) if err != nil { return nil, 0, err diff --git a/go/vt/vtgate/planbuilder/operators/union.go b/go/vt/vtgate/planbuilder/operators/union.go index c555c74b90e..595f34b9bc1 100644 --- a/go/vt/vtgate/planbuilder/operators/union.go +++ b/go/vt/vtgate/planbuilder/operators/union.go @@ -38,6 +38,14 @@ type Union struct { offsetPlanned bool } +func newUnion(srcs []ops.Operator, stmts []sqlparser.SelectExprs, distinct bool) *Union { + return &Union{ + Sources: srcs, + Selects: stmts, + distinct: distinct, + } +} + // Clone implements the Operator interface func (u *Union) Clone(inputs []ops.Operator) ops.Operator { newOp := *u @@ -92,14 +100,7 @@ func (u *Union) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Ex if !ok { return nil, vterrors.VT12001("pushing predicates on UNION where the first SELECT contains * or NEXT") } - if !ae.As.IsEmpty() { - offsets[ae.As.String()] = i - continue - } - col, ok := ae.Expr.(*sqlparser.ColName) - if ok { - offsets[col.Name.Lowered()] = i - } + offsets[ae.ColumnName()] = i } for i := range u.Sources { @@ -126,7 +127,7 @@ func (u *Union) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Ex ae, ok := sel.SelectExprs[idx].(*sqlparser.AliasedExpr) if !ok { - err = vterrors.VT12001("pushing non-aliased expression predicates on concatenate") + err = vterrors.VT09015() cursor.StopTreeWalk() return } @@ -159,6 +160,17 @@ func (u *Union) GetSelectFor(source int) (*sqlparser.Select, error) { } func (u *Union) Compact(*plancontext.PlanningContext) (ops.Operator, *rewrite.ApplyResult, error) { + if u.distinct { + // first we remove unnecessary DISTINCTs + for idx, source := range u.Sources { + d, ok := source.(*Distinct) + if !ok || !d.Original { + continue + } + u.Sources[idx] = d.Source + } + } + var newSources []ops.Operator var newSelects []sqlparser.SelectExprs merged := false @@ -187,16 +199,17 @@ func (u *Union) Compact(*plancontext.PlanningContext) (ops.Operator, *rewrite.Ap } func (u *Union) AddColumn(ctx *plancontext.PlanningContext, ae *sqlparser.AliasedExpr, _, addToGroupBy bool) (ops.Operator, int, error) { - cols, err := u.GetColumns(ctx) + col, err := u.FindCol(ctx, ae.Expr) if err != nil { return nil, 0, err } + if col >= 0 { + return u, col, nil + } - // First we check if we already have this column - for idx, col := range cols { - if ctx.SemTable.EqualsExprWithDeps(ae.Expr, col.Expr) { - return u, idx, nil - } + cols, err := u.GetColumns(ctx) + if err != nil { + return nil, 0, err } switch e := ae.Expr.(type) { diff --git a/go/vt/vtgate/planbuilder/operators/union_merging.go b/go/vt/vtgate/planbuilder/operators/union_merging.go index 55e66c5c3f6..aa016d5b534 100644 --- a/go/vt/vtgate/planbuilder/operators/union_merging.go +++ b/go/vt/vtgate/planbuilder/operators/union_merging.go @@ -41,12 +41,13 @@ func mergeUnionInputInAnyOrder(ctx *plancontext.PlanningContext, op *Union) ([]o } selA := selects[idx] selB := selects[j] - newPlan, err := mergeUnionInputs(ctx, srcA, srcB, selA, selB, op.distinct) + newPlan, sel, err := mergeUnionInputs(ctx, srcA, srcB, selA, selB, op.distinct) if err != nil { return nil, nil, err } if newPlan != nil { sources[idx] = newPlan + selects[idx] = sel srcA = newPlan merged = true } else { @@ -82,14 +83,16 @@ func mergeUnionInputsInOrder(ctx *plancontext.PlanningContext, op *Union) ([]ops j := i + 1 srcA, selA := sources[i], selects[i] srcB, selB := sources[j], selects[j] - newPlan, err := mergeUnionInputs(ctx, srcA, srcB, selA, selB, op.distinct) + newPlan, sel, err := mergeUnionInputs(ctx, srcA, srcB, selA, selB, op.distinct) if err != nil { return nil, nil, err } if newPlan != nil { sources[i] = newPlan + selects[i] = sel merged = true sources = append(sources[:i+1], sources[j+1:]...) + selects = append(selects[:i+1], selects[j+1:]...) } } if !merged { @@ -104,22 +107,28 @@ func mergeUnionInputsInOrder(ctx *plancontext.PlanningContext, op *Union) ([]ops // If they can be merged, a new operator with the merged routing is returned // If they cannot be merged, nil is returned. // this function is very similar to mergeJoinInputs -func mergeUnionInputs(ctx *plancontext.PlanningContext, lhs, rhs ops.Operator, lhsExprs, rhsExprs sqlparser.SelectExprs, distinct bool) (ops.Operator, error) { +func mergeUnionInputs(ctx *plancontext.PlanningContext, lhs, rhs ops.Operator, lhsExprs, rhsExprs sqlparser.SelectExprs, distinct bool) (ops.Operator, sqlparser.SelectExprs, error) { lhsRoute, rhsRoute, routingA, routingB, a, b, sameKeyspace := prepareInputRoutes(lhs, rhs) if lhsRoute == nil { - return nil, nil + return nil, nil, nil } switch { // if either side is a dual query, we can always merge them together case b == dual: - return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingA), nil + return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingA) case a == dual: - return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB), nil + return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB) + + case a == anyShard && sameKeyspace: + return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB) + case b == anyShard && sameKeyspace: + return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingA) + case a == sharded && b == sharded && sameKeyspace: - return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB), nil + return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB) default: - return nil, nil + return nil, nil, nil } } @@ -127,14 +136,12 @@ func createMergedUnion( lhsRoute, rhsRoute *Route, lhsExprs, rhsExprs sqlparser.SelectExprs, distinct bool, - routing Routing) *Route { + routing Routing) (ops.Operator, sqlparser.SelectExprs, error) { + union := newUnion([]ops.Operator{lhsRoute.Source, rhsRoute.Source}, []sqlparser.SelectExprs{lhsExprs, rhsExprs}, distinct) + selectExprs := unionSelects(lhsExprs) return &Route{ - Source: &Union{ - Sources: []ops.Operator{lhsRoute.Source, rhsRoute.Source}, - Selects: []sqlparser.SelectExprs{lhsExprs, rhsExprs}, - distinct: distinct, - }, + Source: union, MergedWith: []*Route{rhsRoute}, Routing: routing, - } + }, selectExprs, nil } diff --git a/go/vt/vtgate/planbuilder/testdata/dml_cases.json b/go/vt/vtgate/planbuilder/testdata/dml_cases.json index c52807fed79..52ddd7d0228 100644 --- a/go/vt/vtgate/planbuilder/testdata/dml_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/dml_cases.json @@ -1617,7 +1617,7 @@ { "comment": "insert invalid index value", "query": "insert into music_extra(music_id, user_id) values(1, id)", - "plan": "cannot lookup column (column access not supported here)" + "plan": "cannot lookup column 'id' (column access not supported here)" }, { "comment": "insert invalid table", diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json index 244391daa91..c92e661374b 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json @@ -829,31 +829,39 @@ "QueryType": "SELECT", "Original": "select found from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", "Instructions": { - "OperatorType": "Concatenate", + "OperatorType": "SimpleProjection", + "Columns": [ + 0 + ], "Inputs": [ { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", - "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", - "SysTableTableSchema": "[VARCHAR(\"music\")]", - "Table": "information_schema.`tables`" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 as found from information_schema.views where 1 != 1", - "Query": "select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1", - "SysTableTableSchema": "[VARCHAR(\"music\")]", - "Table": "information_schema.views" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", + "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"music\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.views where 1 != 1", + "Query": "select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1", + "SysTableTableSchema": "[VARCHAR(\"music\")]", + "Table": "information_schema.views" + } + ] } ] } @@ -998,36 +1006,44 @@ "QueryType": "SELECT", "Original": "select * from (select TABLE_NAME from information_schema.tables t where t.TABLE_SCHEMA = 'a' union select TABLE_NAME from information_schema.columns) dt", "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "(0:1)" + "OperatorType": "SimpleProjection", + "Columns": [ + 0 ], "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], "Inputs": [ { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`tables` as t where 1 != 1", - "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */", - "SysTableTableSchema": "[VARCHAR(\"a\")]", - "Table": "information_schema.`tables`" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns` where 1 != 1", - "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns`", - "Table": "information_schema.`columns`" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`tables` as t where 1 != 1", + "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"a\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns` where 1 != 1", + "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns`", + "Table": "information_schema.`columns`" + } + ] } ] } diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json index d0f1cd63906..d724bfcbc09 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json @@ -894,31 +894,39 @@ "QueryType": "SELECT", "Original": "select found from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", "Instructions": { - "OperatorType": "Concatenate", + "OperatorType": "SimpleProjection", + "Columns": [ + 0 + ], "Inputs": [ { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", - "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", - "SysTableTableSchema": "[VARCHAR(\"music\")]", - "Table": "information_schema.`tables`" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 as found from information_schema.views where 1 != 1", - "Query": "select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1", - "SysTableTableSchema": "[VARCHAR(\"music\")]", - "Table": "information_schema.views" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", + "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"music\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.views where 1 != 1", + "Query": "select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1", + "SysTableTableSchema": "[VARCHAR(\"music\")]", + "Table": "information_schema.views" + } + ] } ] } @@ -1063,36 +1071,44 @@ "QueryType": "SELECT", "Original": "select * from (select TABLE_NAME from information_schema.tables t where t.TABLE_SCHEMA = 'a' union select TABLE_NAME from information_schema.columns) dt", "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "(0:1)" + "OperatorType": "SimpleProjection", + "Columns": [ + 0 ], "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], "Inputs": [ { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`tables` as t where 1 != 1", - "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */", - "SysTableTableSchema": "[VARCHAR(\"a\")]", - "Table": "information_schema.`tables`" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns` where 1 != 1", - "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns`", - "Table": "information_schema.`columns`" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`tables` as t where 1 != 1", + "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"a\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns` where 1 != 1", + "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns`", + "Table": "information_schema.`columns`" + } + ] } ] } diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.json b/go/vt/vtgate/planbuilder/testdata/select_cases.json index 12f3ee7f112..8542400102f 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.json @@ -2477,29 +2477,37 @@ "QueryType": "SELECT", "Original": "select found from (select id as found from user union all (select id from unsharded)) as t", "Instructions": { - "OperatorType": "Concatenate", + "OperatorType": "SimpleProjection", + "Columns": [ + 0 + ], "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id as found from `user` where 1 != 1", - "Query": "select id as found from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select id from unsharded where 1 != 1", - "Query": "select id from unsharded", - "Table": "unsharded" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id as found from `user` where 1 != 1", + "Query": "select id as found from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select id from unsharded where 1 != 1", + "Query": "select id from unsharded", + "Table": "unsharded" + } + ] } ] }, diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 05a07be7aef..5863dfe3b94 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -359,36 +359,15 @@ "ResultColumns": 1, "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Distinct", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select id from music where 1 != 1) as dt where 1 != 1", - "Query": "select id, weight_string(id) from (select id from `user` union select id from music) as dt", - "Table": "`user`, music" - } - ] - }, - { - "OperatorType": "Route", - "Variant": "Reference", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1, weight_string(1) from dual where 1 != 1", - "Query": "select distinct 1, weight_string(1) from dual", - "Table": "dual" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select id from music where 1 != 1 union select 1 from dual where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id) from (select id from `user` union select id from music union select 1 from dual) as dt", + "Table": "`user`, dual, music" } ] }, @@ -748,30 +727,17 @@ "QueryType": "SELECT", "Original": "select * from ((select id from user union select id+1 from user) union select user_id from user_extra) as t", "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "(0:1)" + "OperatorType": "SimpleProjection", + "Columns": [ + 0 ], "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], "Inputs": [ - { - "OperatorType": "Distinct", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select id + 1 from `user` where 1 != 1) as dt where 1 != 1", - "Query": "select id, weight_string(id) from (select id from `user` union select id + 1 from `user`) as dt", - "Table": "`user`" - } - ] - }, { "OperatorType": "Route", "Variant": "Scatter", @@ -779,9 +745,9 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select user_id, weight_string(user_id) from user_extra where 1 != 1", - "Query": "select distinct user_id, weight_string(user_id) from user_extra", - "Table": "user_extra" + "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select id + 1 from `user` where 1 != 1 union select user_id from user_extra where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id) from (select id from `user` union select id + 1 from `user` union select user_id from user_extra) as dt", + "Table": "`user`, user_extra" } ] } @@ -811,17 +777,23 @@ "Inputs": [ { "OperatorType": "Distinct", + "Collations": [ + "(0:1)", + "(1:2)" + ], "Inputs": [ { "OperatorType": "Sort", "Variant": "Memory", - "OrderBy": "(0|1) ASC", + "OrderBy": "(3|1) ASC", "Inputs": [ { "OperatorType": "Distinct", "Collations": [ "(0:1)", - "(1:2)" + "(1:2)", + "(2:4)", + "(3:1)" ], "Inputs": [ { @@ -831,8 +803,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id, weight_string(id), weight_string(weight_string(id)) from (select id from `user` where 1 != 1 union select id from music where 1 != 1) as dt where 1 != 1", - "Query": "select id, weight_string(id), weight_string(weight_string(id)) from (select id from `user` union select id from music) as dt", + "FieldQuery": "select id, weight_string(id), weight_string(weight_string(id)), id, weight_string(weight_string(weight_string(id))) from (select id from `user` where 1 != 1 union select id from music where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id), weight_string(weight_string(id)), id, weight_string(weight_string(weight_string(id))) from (select id from `user` union select id from music) as dt", "Table": "`user`, music" } ] @@ -888,7 +860,7 @@ "Sharded": true }, "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt where 1 != 1", - "Query": "select id, weight_string(id) from (select id from `user` union select 3 from dual) as dt limit :__upper_limit", + "Query": "select id, weight_string(id) from (select id from `user` union select 3 from dual limit :__upper_limit) as dt", "Table": "`user`, dual" } ] @@ -1004,47 +976,50 @@ "OperatorType": "Join", "Variant": "Join", "JoinColumnIndexes": "R:0", - "JoinVars": { - "tbl1_id": 0 - }, "TableName": "`user`_`user`", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Projection", + "Expressions": null, "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(5)", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) ASC", - "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", - "Table": "`user`" - } - ] - }, - { - "OperatorType": "Limit", - "Count": "INT64(5)", - "Inputs": [ + "OperatorType": "Limit", + "Count": "INT64(5)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) ASC", + "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", + "Table": "`user`" + } + ] + }, { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", - "Table": "`user`" + "OperatorType": "Limit", + "Count": "INT64(5)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", + "Table": "`user`" + } + ] } ] } @@ -1052,18 +1027,14 @@ }, { "OperatorType": "Route", - "Variant": "EqualUnique", + "Variant": "Scatter", "Keyspace": { "Name": "user", "Sharded": true }, "FieldQuery": "select tbl2.id from `user` as tbl2 where 1 != 1", - "Query": "select tbl2.id from `user` as tbl2 where tbl2.id = :tbl1_id", - "Table": "`user`", - "Values": [ - ":tbl1_id" - ], - "Vindex": "user_index" + "Query": "select tbl2.id from `user` as tbl2 where tbl1.id = tbl2.id", + "Table": "`user`" } ] }, @@ -1106,6 +1077,10 @@ "Inputs": [ { "OperatorType": "Distinct", + "Collations": [ + "(0:1)", + "(1:2)" + ], "Inputs": [ { "OperatorType": "Route", @@ -1114,8 +1089,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt where 1 != 1", - "Query": "select id, weight_string(id) from (select id from `user` union select 3 from dual) as dt", + "FieldQuery": "select id, weight_string(id), weight_string(weight_string(id)) from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id), weight_string(weight_string(id)) from (select id from `user` union select 3 from dual) as dt", "Table": "`user`, dual" } ] @@ -1141,35 +1116,41 @@ ], "Inputs": [ { - "OperatorType": "Distinct", - "Collations": [ - "(0:1)" - ], + "OperatorType": "Projection", + "Expressions": null, "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id + 42 as foo, weight_string(id + 42) from `user` where 1 != 1", - "Query": "select distinct id + 42 as foo, weight_string(id + 42) from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 + id as foo, weight_string(1 + id) from unsharded where 1 != 1", - "Query": "select distinct 1 + id as foo, weight_string(1 + id) from unsharded", - "Table": "unsharded" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id + 42 as foo, weight_string(id + 42) from `user` where 1 != 1", + "Query": "select distinct id + 42 as foo, weight_string(id + 42) from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 + id as foo, weight_string(1 + id) from unsharded where 1 != 1", + "Query": "select distinct 1 + id as foo, weight_string(1 + id) from unsharded", + "Table": "unsharded" + } + ] } ] } @@ -1186,49 +1167,7 @@ { "comment": "systable union query in derived table with constraint on outside (without star projection)", "query": "select * from (select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `COLUMN_NAME` = 'primary'", - "plan": { - "QueryType": "SELECT", - "Original": "select * from (select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `COLUMN_NAME` = 'primary'", - "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "(0:1)" - ], - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select kcu.COLUMN_NAME, weight_string(kcu.COLUMN_NAME) from information_schema.key_column_usage as kcu where 1 != 1", - "Query": "select distinct kcu.COLUMN_NAME, weight_string(kcu.COLUMN_NAME) from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name /* VARCHAR */ and COLUMN_NAME = 'primary'", - "SysTableTableName": "[kcu_table_name:VARCHAR(\"user_extra\")]", - "SysTableTableSchema": "[VARCHAR(\"user\")]", - "Table": "information_schema.key_column_usage" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select kcu.COLUMN_NAME, weight_string(kcu.COLUMN_NAME) from information_schema.key_column_usage as kcu where 1 != 1", - "Query": "select distinct kcu.COLUMN_NAME, weight_string(kcu.COLUMN_NAME) from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name1 /* VARCHAR */ and COLUMN_NAME = 'primary'", - "SysTableTableName": "[kcu_table_name1:VARCHAR(\"music\")]", - "SysTableTableSchema": "[VARCHAR(\"user\")]", - "Table": "information_schema.key_column_usage" - } - ] - } - ] - } - } + "plan": "VT13001: [BUG] cannot push predicates on concatenate, missing columns from the UNION" }, { "comment": "pushes predicate on both sides of UNION", @@ -1243,8 +1182,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select `name`, id as foo from `user` where 1 != 1 union select 'extra', user_id from user_extra where 1 != 1", - "Query": "select `name`, id as foo from `user` where id = 3 union select 'extra', user_id from user_extra where user_id = 3", + "FieldQuery": "select X.`name`, X.foo from (select `name`, id as foo from `user` where 1 != 1 union select 'extra', user_id from user_extra where 1 != 1) as X where 1 != 1", + "Query": "select X.`name`, X.foo from (select `name`, id as foo from `user` where id = 3 union select 'extra', user_id from user_extra where user_id = 3) as X", "Table": "`user`, user_extra", "Values": [ "INT64(3)" @@ -1260,60 +1199,7 @@ { "comment": "systable union query in derived table with constraint on outside (star projection)", "query": "select * from (select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `constraint_name` = 'primary'", - "plan": { - "QueryType": "SELECT", - "Original": "select * from (select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `constraint_name` = 'primary'", - "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "(0:12)", - "(1:13)", - "(2:14)", - "(3:15)", - "(4:16)", - "(5:17)", - "(6:18)", - "(7:19)", - "(8:20)", - "(9:21)", - "(10:22)", - "(11:23)" - ], - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME, weight_string(kcu.CONSTRAINT_CATALOG), weight_string(kcu.CONSTRAINT_SCHEMA), weight_string(kcu.CONSTRAINT_NAME), weight_string(kcu.TABLE_CATALOG), weight_string(kcu.TABLE_SCHEMA), weight_string(kcu.TABLE_NAME), weight_string(kcu.COLUMN_NAME), weight_string(kcu.ORDINAL_POSITION), weight_string(kcu.POSITION_IN_UNIQUE_CONSTRAINT), weight_string(kcu.REFERENCED_TABLE_SCHEMA), weight_string(kcu.REFERENCED_TABLE_NAME), weight_string(kcu.REFERENCED_COLUMN_NAME) from information_schema.key_column_usage as kcu where 1 != 1", - "Query": "select distinct kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME, weight_string(kcu.CONSTRAINT_CATALOG), weight_string(kcu.CONSTRAINT_SCHEMA), weight_string(kcu.CONSTRAINT_NAME), weight_string(kcu.TABLE_CATALOG), weight_string(kcu.TABLE_SCHEMA), weight_string(kcu.TABLE_NAME), weight_string(kcu.COLUMN_NAME), weight_string(kcu.ORDINAL_POSITION), weight_string(kcu.POSITION_IN_UNIQUE_CONSTRAINT), weight_string(kcu.REFERENCED_TABLE_SCHEMA), weight_string(kcu.REFERENCED_TABLE_NAME), weight_string(kcu.REFERENCED_COLUMN_NAME) from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name /* VARCHAR */ and CONSTRAINT_NAME = 'primary'", - "SysTableTableName": "[kcu_table_name:VARCHAR(\"user_extra\")]", - "SysTableTableSchema": "[VARCHAR(\"user\")]", - "Table": "information_schema.key_column_usage" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME, weight_string(kcu.CONSTRAINT_CATALOG), weight_string(kcu.CONSTRAINT_SCHEMA), weight_string(kcu.CONSTRAINT_NAME), weight_string(kcu.TABLE_CATALOG), weight_string(kcu.TABLE_SCHEMA), weight_string(kcu.TABLE_NAME), weight_string(kcu.COLUMN_NAME), weight_string(kcu.ORDINAL_POSITION), weight_string(kcu.POSITION_IN_UNIQUE_CONSTRAINT), weight_string(kcu.REFERENCED_TABLE_SCHEMA), weight_string(kcu.REFERENCED_TABLE_NAME), weight_string(kcu.REFERENCED_COLUMN_NAME) from information_schema.key_column_usage as kcu where 1 != 1", - "Query": "select distinct kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME, weight_string(kcu.CONSTRAINT_CATALOG), weight_string(kcu.CONSTRAINT_SCHEMA), weight_string(kcu.CONSTRAINT_NAME), weight_string(kcu.TABLE_CATALOG), weight_string(kcu.TABLE_SCHEMA), weight_string(kcu.TABLE_NAME), weight_string(kcu.COLUMN_NAME), weight_string(kcu.ORDINAL_POSITION), weight_string(kcu.POSITION_IN_UNIQUE_CONSTRAINT), weight_string(kcu.REFERENCED_TABLE_SCHEMA), weight_string(kcu.REFERENCED_TABLE_NAME), weight_string(kcu.REFERENCED_COLUMN_NAME) from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name1 /* VARCHAR */ and CONSTRAINT_NAME = 'primary'", - "SysTableTableName": "[kcu_table_name1:VARCHAR(\"music\")]", - "SysTableTableSchema": "[VARCHAR(\"user\")]", - "Table": "information_schema.key_column_usage" - } - ] - } - ] - } - } + "plan": "VT13001: [BUG] cannot push predicates on concatenate, missing columns from the UNION" }, { "comment": "unknown columns are OK as long as the whole query is unsharded", @@ -1463,8 +1349,8 @@ "OperatorType": "Distinct", "Collations": [ "(0:3)", - "(0:0)", - "(0:0)" + "(0:3)", + "(0:3)" ], "ResultColumns": 3, "Inputs": [ @@ -1475,8 +1361,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select weight_string(foo) from (select foo, foo, foo from `user` where 1 != 1 union select bar, baz, toto from music where 1 != 1) as dt where 1 != 1", - "Query": "select weight_string(foo) from (select foo, foo, foo from `user` union select bar, baz, toto from music) as dt", + "FieldQuery": "select foo, foo, foo, weight_string(foo) from (select foo, foo, foo from `user` where 1 != 1 union select bar, baz, toto from music where 1 != 1) as dt where 1 != 1", + "Query": "select foo, foo, foo, weight_string(foo) from (select foo, foo, foo from `user` union select bar, baz, toto from music) as dt", "Table": "`user`, music" } ] @@ -1497,8 +1383,8 @@ "OperatorType": "Distinct", "Collations": [ "(0:3)", - "(1:0)", - "(2:1)" + "(1:4)", + "(2:5)" ], "ResultColumns": 3, "Inputs": [ @@ -1509,8 +1395,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select weight_string(baz), weight_string(toto) from (select bar, baz, toto from music where 1 != 1 union select foo, foo, foo from `user` where 1 != 1) as dt where 1 != 1", - "Query": "select weight_string(baz), weight_string(toto) from (select bar, baz, toto from music union select foo, foo, foo from `user`) as dt", + "FieldQuery": "select bar, baz, toto, weight_string(bar), weight_string(baz), weight_string(toto) from (select bar, baz, toto from music where 1 != 1 union select foo, foo, foo from `user` where 1 != 1) as dt where 1 != 1", + "Query": "select bar, baz, toto, weight_string(bar), weight_string(baz), weight_string(toto) from (select bar, baz, toto from music union select foo, foo, foo from `user`) as dt", "Table": "`user`, music" } ] diff --git a/go/vt/vtgate/semantics/derived_table.go b/go/vt/vtgate/semantics/derived_table.go index e0e4ca528a9..4c32fdfd84c 100644 --- a/go/vt/vtgate/semantics/derived_table.go +++ b/go/vt/vtgate/semantics/derived_table.go @@ -27,18 +27,25 @@ import ( // DerivedTable contains the information about the projection, tables involved in derived table. type DerivedTable struct { - tableName string - ASTNode *sqlparser.AliasedTableExpr - columnNames []string - cols []sqlparser.Expr - tables TableSet - isAuthoritative bool + tableName string + ASTNode *sqlparser.AliasedTableExpr + columnNames []string + cols []sqlparser.Expr + tables TableSet + isAuthoritative bool + exprsNotExpanded bool } var _ TableInfo = (*DerivedTable)(nil) -func createDerivedTableForExpressions(expressions sqlparser.SelectExprs, cols sqlparser.Columns, tables []TableInfo, org originable) *DerivedTable { - vTbl := &DerivedTable{isAuthoritative: true} +func createDerivedTableForExpressions( + expressions sqlparser.SelectExprs, + cols sqlparser.Columns, + tables []TableInfo, + org originable, + exprsNotExpanded bool, +) *DerivedTable { + vTbl := &DerivedTable{isAuthoritative: true, exprsNotExpanded: exprsNotExpanded} for i, selectExpr := range expressions { switch expr := selectExpr.(type) { case *sqlparser.AliasedExpr: @@ -135,6 +142,9 @@ func (dt *DerivedTable) getTableSet(_ originable) TableSet { // GetExprFor implements the TableInfo interface func (dt *DerivedTable) getExprFor(s string) (sqlparser.Expr, error) { + if dt.exprsNotExpanded { + return nil, vterrors.VT09015() + } for i, colName := range dt.columnNames { if colName == s { return dt.cols[i], nil diff --git a/go/vt/vtgate/semantics/table_collector.go b/go/vt/vtgate/semantics/table_collector.go index b1da4893187..1219b54d2ea 100644 --- a/go/vt/vtgate/semantics/table_collector.go +++ b/go/vt/vtgate/semantics/table_collector.go @@ -52,7 +52,7 @@ func (tc *tableCollector) up(cursor *sqlparser.Cursor) error { switch sel := t.Select.(type) { case *sqlparser.Select: tables := tc.scoper.wScope[sel] - tableInfo := createDerivedTableForExpressions(sqlparser.GetFirstSelect(sel).SelectExprs, node.Columns, tables.tables, tc.org) + tableInfo := createDerivedTableForExpressions(sqlparser.GetFirstSelect(sel).SelectExprs, node.Columns, tables.tables, tc.org, false) if err := tableInfo.checkForDuplicates(); err != nil { return err } @@ -67,7 +67,8 @@ func (tc *tableCollector) up(cursor *sqlparser.Cursor) error { case *sqlparser.Union: firstSelect := sqlparser.GetFirstSelect(sel) tables := tc.scoper.wScope[firstSelect] - tableInfo := createDerivedTableForExpressions(firstSelect.SelectExprs, node.Columns, tables.tables, tc.org) + unableToExpandUnion, selectExprs := sqlparser.GetColumnNames(firstSelect.SelectExprs) + tableInfo := createDerivedTableForExpressions(selectExprs, node.Columns, tables.tables, tc.org, unableToExpandUnion) if err := tableInfo.checkForDuplicates(); err != nil { return err } From 613ff29c39b2892f820f8c4887aad02a161e1e08 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Wed, 19 Jul 2023 11:15:10 +0200 Subject: [PATCH 17/44] handle union columns in the semtable so dependencies are handled correctly everywhere Signed-off-by: Andres Taylor --- go/vt/sqlparser/ast_funcs.go | 30 +- .../planbuilder/operators/SQL_builder.go | 13 + .../planbuilder/operators/aggregator.go | 3 +- go/vt/vtgate/planbuilder/operators/ast2op.go | 26 +- go/vt/vtgate/planbuilder/operators/horizon.go | 39 +-- .../planbuilder/operators/horizon_planning.go | 6 +- go/vt/vtgate/planbuilder/operators/route.go | 8 +- go/vt/vtgate/planbuilder/operators/union.go | 63 ++-- .../planbuilder/operators/union_merging.go | 2 +- .../testdata/info_schema57_cases.json | 2 - .../testdata/info_schema80_cases.json | 2 - .../planbuilder/testdata/union_cases.json | 231 +++++++------- go/vt/vtgate/semantics/analyzer.go | 1 + go/vt/vtgate/semantics/analyzer_dml_test.go | 16 +- go/vt/vtgate/semantics/analyzer_test.go | 289 ++++++++++-------- go/vt/vtgate/semantics/derived_table.go | 82 +++-- go/vt/vtgate/semantics/semantic_state.go | 37 +++ go/vt/vtgate/semantics/table_collector.go | 98 ++++-- 18 files changed, 532 insertions(+), 416 deletions(-) diff --git a/go/vt/sqlparser/ast_funcs.go b/go/vt/sqlparser/ast_funcs.go index c096af3848b..67af57eac53 100644 --- a/go/vt/sqlparser/ast_funcs.go +++ b/go/vt/sqlparser/ast_funcs.go @@ -2505,15 +2505,27 @@ func (ty KillType) ToString() string { } } -func GetColumnNames(exprs SelectExprs) (expanded bool, selectExprs SelectExprs) { - for _, col := range exprs { - switch col := col.(type) { - case *AliasedExpr: - expr := NewColName(col.ColumnName()) - selectExprs = append(selectExprs, &AliasedExpr{Expr: expr}) - default: - return false, exprs +func VisitAllSelects(in SelectStatement, f func(p *Select, idx int) error) error { + v := visitor{} + return v.visitAllSelects(in, f) +} + +type visitor struct { + idx int +} + +func (v *visitor) visitAllSelects(in SelectStatement, f func(p *Select, idx int) error) error { + switch sel := in.(type) { + case *Select: + err := f(sel, v.idx) + v.idx++ + return err + case *Union: + err := v.visitAllSelects(sel.Left, f) + if err != nil { + return err } + return v.visitAllSelects(sel.Right, f) } - return true, selectExprs + panic("switch should be exhaustive") } diff --git a/go/vt/vtgate/planbuilder/operators/SQL_builder.go b/go/vt/vtgate/planbuilder/operators/SQL_builder.go index 2893abeb3f4..e7a84839cbc 100644 --- a/go/vt/vtgate/planbuilder/operators/SQL_builder.go +++ b/go/vt/vtgate/planbuilder/operators/SQL_builder.go @@ -141,6 +141,19 @@ func (qb *queryBuilder) pushUnionInsideDerived() { qb.sel = sel } +func unionSelects(exprs sqlparser.SelectExprs) (selectExprs sqlparser.SelectExprs) { + for _, col := range exprs { + switch col := col.(type) { + case *sqlparser.AliasedExpr: + expr := sqlparser.NewColName(col.ColumnName()) + selectExprs = append(selectExprs, &sqlparser.AliasedExpr{Expr: expr}) + default: + selectExprs = append(selectExprs, col) + } + } + return +} + func checkUnionColumnByName(column *sqlparser.ColName, sel sqlparser.SelectStatement) error { colName := column.Name.String() exprs := sqlparser.GetFirstSelect(sel).SelectExprs diff --git a/go/vt/vtgate/planbuilder/operators/aggregator.go b/go/vt/vtgate/planbuilder/operators/aggregator.go index 6e6f349ae01..c90c38b1da9 100644 --- a/go/vt/vtgate/planbuilder/operators/aggregator.go +++ b/go/vt/vtgate/planbuilder/operators/aggregator.go @@ -349,7 +349,8 @@ func (a *Aggregator) addIfAggregationColumn(ctx *plancontext.PlanningContext, co continue } - newSrc, offset, err := a.Source.AddColumn(ctx, aeWrap(aggr.getPushDownColumn()), false, false) + wrap := aeWrap(aggr.getPushDownColumn()) + newSrc, offset, err := a.Source.AddColumn(ctx, wrap, false, false) if err != nil { return 0, err } diff --git a/go/vt/vtgate/planbuilder/operators/ast2op.go b/go/vt/vtgate/planbuilder/operators/ast2op.go index 6259f532599..dc3298316df 100644 --- a/go/vt/vtgate/planbuilder/operators/ast2op.go +++ b/go/vt/vtgate/planbuilder/operators/ast2op.go @@ -100,23 +100,14 @@ func createOperatorFromUnion(ctx *plancontext.PlanningContext, node *sqlparser.U return nil, err } - lexprs := getExpressions(node.Left) - rexprs := getExpressions(node.Right) + lexprs := ctx.SemTable.SelectExprs(node.Left) + rexprs := ctx.SemTable.SelectExprs(node.Right) - union := newUnion([]ops.Operator{opLHS, opRHS}, []sqlparser.SelectExprs{lexprs, rexprs}, node.Distinct) + unionCols := ctx.SemTable.SelectExprs(node) + union := newUnion([]ops.Operator{opLHS, opRHS}, []sqlparser.SelectExprs{lexprs, rexprs}, unionCols, node.Distinct) return &Horizon{Source: union, Query: node}, nil } -func getExpressions(stmt sqlparser.SelectStatement) sqlparser.SelectExprs { - switch stmt := stmt.(type) { - case *sqlparser.Select: - return stmt.SelectExprs - case *sqlparser.Union: - return unionSelects(sqlparser.GetFirstSelect(stmt).SelectExprs) - } - return nil -} - func createOperatorFromUpdate(ctx *plancontext.PlanningContext, updStmt *sqlparser.Update) (ops.Operator, error) { tableInfo, qt, err := createQueryTableForDML(ctx, updStmt.TableExprs[0], updStmt.Where) if err != nil { @@ -607,11 +598,10 @@ func getOperatorFromAliasedTableExpr(ctx *plancontext.PlanningContext, tableExpr inner = horizon.Source } - stmt := sqlparser.CloneSelectStatement(tbl.Select) - if onlyTable && stmt.GetLimit() == nil { - stmt.SetOrderBy(nil) + if onlyTable && tbl.Select.GetLimit() == nil { + tbl.Select.SetOrderBy(nil) } - qp, err := CreateQPFromSelectStatement(ctx, stmt) + qp, err := CreateQPFromSelectStatement(ctx, tbl.Select) if err != nil { return nil, err } @@ -620,7 +610,7 @@ func getOperatorFromAliasedTableExpr(ctx *plancontext.PlanningContext, tableExpr TableId: &tableID, Alias: tableExpr.As.String(), Source: inner, - Query: stmt, + Query: tbl.Select, ColumnAliases: tableExpr.Columns, QP: qp, }, nil diff --git a/go/vt/vtgate/planbuilder/operators/horizon.go b/go/vt/vtgate/planbuilder/operators/horizon.go index d859d1d1fe9..af48df40991 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon.go +++ b/go/vt/vtgate/planbuilder/operators/horizon.go @@ -170,6 +170,7 @@ func (h *Horizon) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.Al h.Columns = append(h.Columns, col) // add it to the source if we were not already passing it through if i <= -1 { + // TODO: this does not look correct newSrc, _, err := h.Source.AddColumn(ctx, aeWrap(sqlparser.NewColName(col.Name.String())), true, addToGroupBy) if err != nil { return nil, 0, err @@ -210,40 +211,16 @@ func (h *Horizon) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) return -1, nil } -func (h *Horizon) GetColumns(*plancontext.PlanningContext) (exprs []*sqlparser.AliasedExpr, err error) { - switch sel := h.Query.(type) { - case *sqlparser.Select: - for _, expr := range sel.SelectExprs { - ae, ok := expr.(*sqlparser.AliasedExpr) - if !ok { - return nil, vterrors.VT09015() - } - exprs = append(exprs, ae) - } - case *sqlparser.Union: - selectExprs := unionSelects(sqlparser.GetFirstSelect(h.Query).SelectExprs) - for _, expr := range selectExprs { - ae, ok := expr.(*sqlparser.AliasedExpr) - if !ok { - return nil, vterrors.VT09015() - } - exprs = append(exprs, ae) +func (h *Horizon) GetColumns(ctx *plancontext.PlanningContext) (exprs []*sqlparser.AliasedExpr, err error) { + for _, expr := range ctx.SemTable.SelectExprs(h.Query) { + ae, ok := expr.(*sqlparser.AliasedExpr) + if !ok { + return nil, vterrors.VT09015() } + exprs = append(exprs, ae) } - return exprs, nil -} -func unionSelects(exprs sqlparser.SelectExprs) (selectExprs sqlparser.SelectExprs) { - for _, col := range exprs { - switch col := col.(type) { - case *sqlparser.AliasedExpr: - expr := sqlparser.NewColName(col.ColumnName()) - selectExprs = append(selectExprs, aeWrap(expr)) - default: - selectExprs = append(selectExprs, col) - } - } - return + return exprs, nil } func (h *Horizon) GetSelectExprs(*plancontext.PlanningContext) (sqlparser.SelectExprs, error) { diff --git a/go/vt/vtgate/planbuilder/operators/horizon_planning.go b/go/vt/vtgate/planbuilder/operators/horizon_planning.go index c2f37b557c7..8f7c7068271 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_planning.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_planning.go @@ -684,7 +684,11 @@ func tryPushDownUnion(ctx *plancontext.PlanningContext, op *Union) (ops.Operator if len(sources) == len(op.Sources) { return op, rewrite.SameTree, nil } - return newUnion(sources, selects, op.distinct), rewrite.NewTree("merged union inputs", op), nil + + // TODO: this is a hack + columns := op.unionColumns + + return newUnion(sources, selects, columns, op.distinct), rewrite.NewTree("merged union inputs", op), nil } // makeSureOutputIsCorrect uses the original Horizon to make sure that the output columns line up with what the user asked for diff --git a/go/vt/vtgate/planbuilder/operators/route.go b/go/vt/vtgate/planbuilder/operators/route.go index 1ed7d3f7439..a13baf1e74a 100644 --- a/go/vt/vtgate/planbuilder/operators/route.go +++ b/go/vt/vtgate/planbuilder/operators/route.go @@ -623,13 +623,17 @@ func addColumnToInput(ctx *plancontext.PlanningContext, operator ops.Operator, e case *Union: tableID := semantics.SingleTableSet(len(ctx.SemTable.Tables)) ctx.SemTable.Tables = append(ctx.SemTable.Tables, nil) + unionColumns, err := op.GetColumns(ctx) + if err != nil { + return nil, false, 0 + } return &Projection{ Source: op, - Columns: append(op.columns, expr), + Columns: unionColumns, Projections: nil, TableID: &tableID, Alias: "dt", - }, true, len(op.columns) + }, true, len(op.unionColumns) default: return op, false, 0 } diff --git a/go/vt/vtgate/planbuilder/operators/union.go b/go/vt/vtgate/planbuilder/operators/union.go index 595f34b9bc1..e1b1f064073 100644 --- a/go/vt/vtgate/planbuilder/operators/union.go +++ b/go/vt/vtgate/planbuilder/operators/union.go @@ -19,6 +19,8 @@ package operators import ( "fmt" + "vitess.io/vitess/go/slice" + "golang.org/x/exp/slices" "vitess.io/vitess/go/vt/sqlparser" @@ -26,23 +28,29 @@ import ( "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/rewrite" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" - "vitess.io/vitess/go/vt/vtgate/semantics" ) type Union struct { - Sources []ops.Operator + Sources []ops.Operator + + // These are the select expressions coming from each source Selects []sqlparser.SelectExprs distinct bool - columns []*sqlparser.AliasedExpr - offsetPlanned bool + unionColumns sqlparser.SelectExprs + unionColumnsAsAlisedExprs []*sqlparser.AliasedExpr + offsetPlanned bool } -func newUnion(srcs []ops.Operator, stmts []sqlparser.SelectExprs, distinct bool) *Union { +func newUnion(srcs []ops.Operator, sourceSelects []sqlparser.SelectExprs, columns sqlparser.SelectExprs, distinct bool) *Union { + if columns == nil { + panic("rt") + } return &Union{ - Sources: srcs, - Selects: stmts, - distinct: distinct, + Sources: srcs, + Selects: sourceSelects, + distinct: distinct, + unionColumns: columns, } } @@ -287,40 +295,23 @@ func (u *Union) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) ( } func (u *Union) GetColumns(ctx *plancontext.PlanningContext) (result []*sqlparser.AliasedExpr, err error) { - if u.columns != nil { - return u.columns, nil - } - - var columns [][]*sqlparser.AliasedExpr - for _, source := range u.Sources { - getColumns, err := source.GetColumns(ctx) - if err != nil { - return nil, err + if u.unionColumnsAsAlisedExprs == nil { + allOk := true + u.unionColumnsAsAlisedExprs = slice.Map(u.unionColumns, func(from sqlparser.SelectExpr) *sqlparser.AliasedExpr { + expr, ok := from.(*sqlparser.AliasedExpr) + allOk = allOk && ok + return expr + }) + if !allOk { + return nil, vterrors.VT09015() } - columns = append(columns, getColumns) } - for idx, column := range columns[0] { - col := sqlparser.NewColName(column.ColumnName()) - result = append(result, aeWrap(col)) - - dd := semantics.EmptyTableSet() - rd := semantics.EmptyTableSet() - for _, cols := range columns { - e := cols[idx].Expr - dd = dd.Merge(ctx.SemTable.DirectDeps(e)) - rd = rd.Merge(ctx.SemTable.RecursiveDeps(e)) - } - - ctx.SemTable.Direct[col] = dd - ctx.SemTable.Recursive[col] = rd - } - u.columns = result - return + return u.unionColumnsAsAlisedExprs, nil } func (u *Union) GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.SelectExprs, error) { - return u.Sources[0].GetSelectExprs(ctx) + return u.unionColumns, nil } func (u *Union) NoLHSTableSet() {} diff --git a/go/vt/vtgate/planbuilder/operators/union_merging.go b/go/vt/vtgate/planbuilder/operators/union_merging.go index aa016d5b534..83740ecff88 100644 --- a/go/vt/vtgate/planbuilder/operators/union_merging.go +++ b/go/vt/vtgate/planbuilder/operators/union_merging.go @@ -137,7 +137,7 @@ func createMergedUnion( lhsExprs, rhsExprs sqlparser.SelectExprs, distinct bool, routing Routing) (ops.Operator, sqlparser.SelectExprs, error) { - union := newUnion([]ops.Operator{lhsRoute.Source, rhsRoute.Source}, []sqlparser.SelectExprs{lhsExprs, rhsExprs}, distinct) + union := newUnion([]ops.Operator{lhsRoute.Source, rhsRoute.Source}, []sqlparser.SelectExprs{lhsExprs, rhsExprs}, lhsExprs, distinct) selectExprs := unionSelects(lhsExprs) return &Route{ Source: union, diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json index c92e661374b..668157cc148 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json @@ -105,7 +105,6 @@ "Collations": [ "(0:1)" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Concatenate", @@ -169,7 +168,6 @@ "(19:40)", "(20:41)" ], - "ResultColumns": 21, "Inputs": [ { "OperatorType": "Concatenate", diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json index d724bfcbc09..a20695d3868 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json @@ -105,7 +105,6 @@ "Collations": [ "(0:1)" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Concatenate", @@ -169,7 +168,6 @@ "(19:40)", "(20:41)" ], - "ResultColumns": 21, "Inputs": [ { "OperatorType": "Concatenate", diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 5863dfe3b94..3f3ea92f564 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -87,49 +87,41 @@ "QueryType": "SELECT", "Original": "(SELECT id FROM user ORDER BY id DESC LIMIT 1) UNION ALL (SELECT id FROM music ORDER BY id DESC LIMIT 1)", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Limit", + "Count": "INT64(1)", "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(1)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", - "Table": "`user`" - } - ] - }, + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", + "Table": "`user`" + } + ] + }, + { + "OperatorType": "Limit", + "Count": "INT64(1)", + "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(1)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from music where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", - "Table": "music" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from music where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", + "Table": "music" } ] } @@ -217,49 +209,41 @@ "QueryType": "SELECT", "Original": "(select id from user order by id limit 5) union all (select id from music order by id desc limit 5)", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Limit", + "Count": "INT64(5)", "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(5)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) ASC", - "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", - "Table": "`user`" - } - ] - }, + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) ASC", + "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", + "Table": "`user`" + } + ] + }, + { + "OperatorType": "Limit", + "Count": "INT64(5)", + "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(5)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from music where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", - "Table": "music" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from music where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", + "Table": "music" } ] } @@ -304,7 +288,6 @@ "Collations": [ "(0:1)" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Concatenate", @@ -516,7 +499,6 @@ "(0:2)", "(1:3)" ], - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Concatenate", @@ -584,7 +566,6 @@ "(0:2)", "(1:3)" ], - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Concatenate", @@ -651,7 +632,6 @@ "Collations": [ "(0:1)" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Concatenate", @@ -770,7 +750,6 @@ "Collations": [ "(0:1)" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Concatenate", @@ -785,15 +764,14 @@ { "OperatorType": "Sort", "Variant": "Memory", - "OrderBy": "(3|1) ASC", + "OrderBy": "(0|1) ASC", "Inputs": [ { "OperatorType": "Distinct", "Collations": [ "(0:1)", "(1:2)", - "(2:4)", - "(3:1)" + "(2:3)" ], "Inputs": [ { @@ -803,8 +781,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id, weight_string(id), weight_string(weight_string(id)), id, weight_string(weight_string(weight_string(id))) from (select id from `user` where 1 != 1 union select id from music where 1 != 1) as dt where 1 != 1", - "Query": "select id, weight_string(id), weight_string(weight_string(id)), id, weight_string(weight_string(weight_string(id))) from (select id from `user` union select id from music) as dt", + "FieldQuery": "select id, weight_string(id), weight_string(weight_string(id)), weight_string(weight_string(weight_string(id))) from (select id from `user` where 1 != 1 union select id from music where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id), weight_string(weight_string(id)), weight_string(weight_string(weight_string(id))) from (select id from `user` union select id from music) as dt", "Table": "`user`, music" } ] @@ -906,7 +884,6 @@ "Collations": [ "(0:1)" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Concatenate", @@ -976,50 +953,47 @@ "OperatorType": "Join", "Variant": "Join", "JoinColumnIndexes": "R:0", + "JoinVars": { + "tbl1_id": 0 + }, "TableName": "`user`_`user`", "Inputs": [ { - "OperatorType": "Projection", - "Expressions": null, + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Limit", + "Count": "INT64(5)", "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(5)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) ASC", - "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", - "Table": "`user`" - } - ] - }, + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) ASC", + "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", + "Table": "`user`" + } + ] + }, + { + "OperatorType": "Limit", + "Count": "INT64(5)", + "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(5)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", - "Table": "`user`" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", + "Table": "`user`" } ] } @@ -1027,14 +1001,18 @@ }, { "OperatorType": "Route", - "Variant": "Scatter", + "Variant": "EqualUnique", "Keyspace": { "Name": "user", "Sharded": true }, "FieldQuery": "select tbl2.id from `user` as tbl2 where 1 != 1", - "Query": "select tbl2.id from `user` as tbl2 where tbl1.id = tbl2.id", - "Table": "`user`" + "Query": "select tbl2.id from `user` as tbl2 where tbl2.id = :tbl1_id", + "Table": "`user`", + "Values": [ + ":tbl1_id" + ], + "Vindex": "user_index" } ] }, @@ -1236,7 +1214,6 @@ "(1:4)", "(2:5)" ], - "ResultColumns": 3, "Inputs": [ { "OperatorType": "Concatenate", diff --git a/go/vt/vtgate/semantics/analyzer.go b/go/vt/vtgate/semantics/analyzer.go index d08212d0ad0..2f61d97300a 100644 --- a/go/vt/vtgate/semantics/analyzer.go +++ b/go/vt/vtgate/semantics/analyzer.go @@ -116,6 +116,7 @@ func (a *analyzer) newSemTable(statement sqlparser.Statement, coll collations.ID ColumnEqualities: map[columnName][]sqlparser.Expr{}, Collation: coll, ExpandedColumns: a.rewriter.expandedColumns, + columns: a.tables.columns, } } diff --git a/go/vt/vtgate/semantics/analyzer_dml_test.go b/go/vt/vtgate/semantics/analyzer_dml_test.go index bb72a21811e..7c87066dced 100644 --- a/go/vt/vtgate/semantics/analyzer_dml_test.go +++ b/go/vt/vtgate/semantics/analyzer_dml_test.go @@ -45,8 +45,8 @@ func TestUpdBindingColName(t *testing.T) { updExpr := extractFromUpdateSet(upd, 0) recursiveDeps := semTable.RecursiveDeps(updExpr.Name) - assert.Equal(t, T1, recursiveDeps, query) - assert.Equal(t, T1, semTable.DirectDeps(updExpr.Name), query) + assert.Equal(t, TS0, recursiveDeps, query) + assert.Equal(t, TS0, semTable.DirectDeps(updExpr.Name), query) assert.Equal(t, 1, recursiveDeps.NumberOfTables(), "number of tables is wrong") recursiveDeps = semTable.RecursiveDeps(updExpr.Expr) @@ -73,13 +73,13 @@ func TestUpdBindingExpr(t *testing.T) { updExpr := extractFromUpdateSet(upd, 0) recursiveDeps := semTable.RecursiveDeps(updExpr.Name) - assert.Equal(t, T1, recursiveDeps, query) - assert.Equal(t, T1, semTable.DirectDeps(updExpr.Name), query) + assert.Equal(t, TS0, recursiveDeps, query) + assert.Equal(t, TS0, semTable.DirectDeps(updExpr.Name), query) assert.Equal(t, 1, recursiveDeps.NumberOfTables(), "number of tables is wrong") recursiveDeps = semTable.RecursiveDeps(updExpr.Expr) - assert.Equal(t, T1, recursiveDeps, query) - assert.Equal(t, T1, semTable.DirectDeps(updExpr.Expr), query) + assert.Equal(t, TS0, recursiveDeps, query) + assert.Equal(t, TS0, semTable.DirectDeps(updExpr.Expr), query) assert.Equal(t, 1, recursiveDeps.NumberOfTables(), "number of tables is wrong") }) } @@ -102,8 +102,8 @@ func TestUpdSetSubquery(t *testing.T) { updExpr := extractFromUpdateSet(upd, 0) recursiveDeps := semTable.RecursiveDeps(updExpr.Name) - assert.Equal(t, T1, recursiveDeps, query) - assert.Equal(t, T1, semTable.DirectDeps(updExpr.Name), query) + assert.Equal(t, TS0, recursiveDeps, query) + assert.Equal(t, TS0, semTable.DirectDeps(updExpr.Name), query) assert.Equal(t, 1, recursiveDeps.NumberOfTables(), "number of tables is wrong") extractedSubqs := semTable.SubqueryMap[upd] diff --git a/go/vt/vtgate/semantics/analyzer_test.go b/go/vt/vtgate/semantics/analyzer_test.go index c43498aecdb..ec6c69960b0 100644 --- a/go/vt/vtgate/semantics/analyzer_test.go +++ b/go/vt/vtgate/semantics/analyzer_test.go @@ -35,11 +35,11 @@ var T0 TableSet var ( // Just here to make outputs more readable None = EmptyTableSet() - T1 = SingleTableSet(0) - T2 = SingleTableSet(1) - T3 = SingleTableSet(2) - T4 = SingleTableSet(3) - T5 = SingleTableSet(4) + TS0 = SingleTableSet(0) + TS1 = SingleTableSet(1) + TS2 = SingleTableSet(2) + TS3 = SingleTableSet(3) + TS4 = SingleTableSet(4) ) func extract(in *sqlparser.Select, idx int) sqlparser.Expr { @@ -68,8 +68,8 @@ func TestBindingSingleTablePositive(t *testing.T) { assert.Equal(t, SingleTableSet(0), ts) recursiveDeps := semTable.RecursiveDeps(extract(sel, 0)) - assert.Equal(t, T1, recursiveDeps, query) - assert.Equal(t, T1, semTable.DirectDeps(extract(sel, 0)), query) + assert.Equal(t, TS0, recursiveDeps, query) + assert.Equal(t, TS0, semTable.DirectDeps(extract(sel, 0)), query) assert.Equal(t, 1, recursiveDeps.NumberOfTables(), "number of tables is wrong") }) } @@ -105,7 +105,7 @@ func TestBindingSingleAliasedTablePositive(t *testing.T) { assert.Equal(t, SingleTableSet(0), ts) recursiveDeps := semTable.RecursiveDeps(extract(sel, 0)) - require.Equal(t, T1, recursiveDeps, query) + require.Equal(t, TS0, recursiveDeps, query) assert.Equal(t, 1, recursiveDeps.NumberOfTables(), "number of tables is wrong") }) } @@ -163,35 +163,35 @@ func TestBindingMultiTablePositive(t *testing.T) { } queries := []testCase{{ query: "select t.col from t, s", - deps: T1, + deps: TS0, numberOfTables: 1, }, { query: "select s.col from t join s", - deps: T2, + deps: TS1, numberOfTables: 1, }, { query: "select max(t.col+s.col) from t, s", - deps: MergeTableSets(T1, T2), + deps: MergeTableSets(TS0, TS1), numberOfTables: 2, }, { query: "select max(t.col+s.col) from t join s", - deps: MergeTableSets(T1, T2), + deps: MergeTableSets(TS0, TS1), numberOfTables: 2, }, { query: "select case t.col when s.col then r.col else u.col end from t, s, r, w, u", - deps: MergeTableSets(T1, T2, T3, T5), + deps: MergeTableSets(TS0, TS1, TS2, TS4), numberOfTables: 4, // }, { // TODO: move to subquery // make sure that we don't let sub-query dependencies leak out by mistake // query: "select t.col + (select 42 from s) from t", - // deps: T1, + // deps: TS0, // }, { // query: "select (select 42 from s where r.id = s.id) from r", - // deps: T1 | T2, + // deps: TS0 | TS1, }, { query: "select u1.a + u2.a from u1, u2", - deps: MergeTableSets(T1, T2), + deps: MergeTableSets(TS0, TS1), numberOfTables: 2, }} for _, query := range queries { @@ -213,19 +213,19 @@ func TestBindingMultiAliasedTablePositive(t *testing.T) { } queries := []testCase{{ query: "select X.col from t as X, s as S", - deps: T1, + deps: TS0, numberOfTables: 1, }, { query: "select X.col+S.col from t as X, s as S", - deps: MergeTableSets(T1, T2), + deps: MergeTableSets(TS0, TS1), numberOfTables: 2, }, { query: "select max(X.col+S.col) from t as X, s as S", - deps: MergeTableSets(T1, T2), + deps: MergeTableSets(TS0, TS1), numberOfTables: 2, }, { query: "select max(X.col+s.col) from t as X, s", - deps: MergeTableSets(T1, T2), + deps: MergeTableSets(TS0, TS1), numberOfTables: 2, }} for _, query := range queries { @@ -487,13 +487,13 @@ func TestScopeForSubqueries(t *testing.T) { }{ { sql: `select t.col1, (select t.col2 from z as t) from x as t`, - deps: T2, + deps: TS1, }, { sql: `select t.col1, (select t.col2 from z) from x as t`, - deps: T1, + deps: TS0, }, { sql: `select t.col1, (select (select z.col2 from y) from z) from x as t`, - deps: T2, + deps: TS1, }, { sql: `select t.col1, (select (select y.col2 from y) from z) from x as t`, deps: None, @@ -502,7 +502,7 @@ func TestScopeForSubqueries(t *testing.T) { deps: None, }, { sql: `select t.col1, (select id from t) from x as t`, - deps: T2, + deps: TS1, }, } for _, tc := range tcases { @@ -615,22 +615,22 @@ func TestSubqueryOrderByBinding(t *testing.T) { expected TableSet }{{ query: "select * from user u where exists (select * from user order by col)", - expected: T2, + expected: TS1, }, { query: "select * from user u where exists (select * from user order by user.col)", - expected: T2, + expected: TS1, }, { query: "select * from user u where exists (select * from user order by u.col)", - expected: T1, + expected: TS0, }, { query: "select * from dbName.user as u where exists (select * from dbName.user order by u.col)", - expected: T1, + expected: TS0, }, { query: "select * from dbName.user where exists (select * from otherDb.user order by dbName.user.col)", - expected: T1, + expected: TS0, }, { query: "select id from dbName.t1 where exists (select * from dbName.t2 order by dbName.t1.id)", - expected: T1, + expected: TS0, }} for _, tc := range queries { @@ -655,52 +655,52 @@ func TestOrderByBindingTable(t *testing.T) { deps TableSet }{{ "select col from tabl order by col", - T1, + TS0, }, { "select tabl.col from d.tabl order by col", - T1, + TS0, }, { "select d.tabl.col from d.tabl order by col", - T1, + TS0, }, { "select col from tabl order by tabl.col", - T1, + TS0, }, { "select col from tabl order by d.tabl.col", - T1, + TS0, }, { "select col from tabl order by 1", - T1, + TS0, }, { "select col as c from tabl order by c", - T1, + TS0, }, { "select 1 as c from tabl order by c", T0, }, { "select name, name from t1, t2 order by name", - T2, + TS1, }, { "(select id from t1) union (select uid from t2) order by id", - MergeTableSets(T1, T2), + MergeTableSets(TS0, TS1), }, { "select id from t1 union (select uid from t2) order by 1", - MergeTableSets(T1, T2), + MergeTableSets(TS0, TS1), }, { "select id from t1 union select uid from t2 union (select name from t) order by 1", - MergeTableSets(T1, T2, T3), + MergeTableSets(TS0, TS1, TS2), }, { "select a.id from t1 as a union (select uid from t2) order by 1", - MergeTableSets(T1, T2), + MergeTableSets(TS0, TS1), }, { "select b.id as a from t1 as b union (select uid as c from t2) order by 1", - MergeTableSets(T1, T2), + MergeTableSets(TS0, TS1), }, { "select a.id from t1 as a union (select uid from t2, t union (select name from t) order by 1) order by 1", - MergeTableSets(T1, T2, T4), + MergeTableSets(TS0, TS1, TS3), }, { "select a.id from t1 as a union (select uid from t2, t union (select name from t) order by 1) order by id", - MergeTableSets(T1, T2, T4), + MergeTableSets(TS0, TS1, TS3), }} for _, tc := range tcases { t.Run(tc.sql, func(t *testing.T) { @@ -727,49 +727,49 @@ func TestGroupByBinding(t *testing.T) { deps TableSet }{{ "select col from tabl group by col", - T1, + TS0, }, { "select col from tabl group by tabl.col", - T1, + TS0, }, { "select col from tabl group by d.tabl.col", - T1, + TS0, }, { "select tabl.col as x from tabl group by x", - T1, + TS0, }, { "select tabl.col as x from tabl group by col", - T1, + TS0, }, { "select d.tabl.col as x from tabl group by x", - T1, + TS0, }, { "select d.tabl.col as x from tabl group by col", - T1, + TS0, }, { "select col from tabl group by 1", - T1, + TS0, }, { "select col as c from tabl group by c", - T1, + TS0, }, { "select 1 as c from tabl group by c", T0, }, { "select t1.id from t1, t2 group by id", - T1, + TS0, }, { "select id from t, t1 group by id", - T2, + TS1, }, { "select id from t, t1 group by id", - T2, + TS1, }, { "select a.id from t as a, t1 group by id", - T1, + TS0, }, { "select a.id from t, t1 as a group by id", - T2, + TS1, }} for _, tc := range tcases { t.Run(tc.sql, func(t *testing.T) { @@ -788,43 +788,43 @@ func TestHavingBinding(t *testing.T) { deps TableSet }{{ "select col from tabl having col = 1", - T1, + TS0, }, { "select col from tabl having tabl.col = 1", - T1, + TS0, }, { "select col from tabl having d.tabl.col = 1", - T1, + TS0, }, { "select tabl.col as x from tabl having x = 1", - T1, + TS0, }, { "select tabl.col as x from tabl having col", - T1, + TS0, }, { "select col from tabl having 1 = 1", T0, }, { "select col as c from tabl having c = 1", - T1, + TS0, }, { "select 1 as c from tabl having c = 1", T0, }, { "select t1.id from t1, t2 having id = 1", - T1, + TS0, }, { "select t.id from t, t1 having id = 1", - T1, + TS0, }, { "select t.id, count(*) as a from t, t1 group by t.id having a = 1", - MergeTableSets(T1, T2), + MergeTableSets(TS0, TS1), }, { "select t.id, sum(t2.name) as a from t, t2 group by t.id having a = 1", - T2, + TS1, }, { sql: "select u2.a, u1.a from u1, u2 having u2.a = 2", - deps: T2, + deps: TS1, }} for _, tc := range tcases { t.Run(tc.sql, func(t *testing.T) { @@ -854,8 +854,8 @@ func TestUnionCheckFirstAndLastSelectsDeps(t *testing.T) { d1 := semTable.RecursiveDeps(extract(sel1, 0)) d2 := semTable.RecursiveDeps(extract(sel2, 0)) - assert.Equal(t, T1, d1) - assert.Equal(t, T2, d2) + assert.Equal(t, TS0, d1) + assert.Equal(t, TS1, d2) } func TestUnionOrderByRewrite(t *testing.T) { @@ -957,8 +957,8 @@ func TestUnionWithOrderBy(t *testing.T) { d1 := semTable.RecursiveDeps(extract(sel1, 0)) d2 := semTable.RecursiveDeps(extract(sel2, 0)) - assert.Equal(t, T1, d1) - assert.Equal(t, T2, d2) + assert.Equal(t, TS0, d1) + assert.Equal(t, TS1, d2) } func TestScopingWDerivedTables(t *testing.T) { @@ -970,31 +970,31 @@ func TestScopingWDerivedTables(t *testing.T) { }{ { query: "select id from (select x as id from user) as t", - recursiveExpectation: T1, - expectation: T2, + recursiveExpectation: TS0, + expectation: TS1, }, { query: "select id from (select foo as id from user) as t", - recursiveExpectation: T1, - expectation: T2, + recursiveExpectation: TS0, + expectation: TS1, }, { query: "select id from (select foo as id from (select x as foo from user) as c) as t", - recursiveExpectation: T1, - expectation: T3, + recursiveExpectation: TS0, + expectation: TS2, }, { query: "select t.id from (select foo as id from user) as t", - recursiveExpectation: T1, - expectation: T2, + recursiveExpectation: TS0, + expectation: TS1, }, { query: "select t.id2 from (select foo as id from user) as t", errorMessage: "column 't.id2' not found", }, { query: "select id from (select 42 as id) as t", recursiveExpectation: T0, - expectation: T2, + expectation: TS1, }, { query: "select t.id from (select 42 as id) as t", recursiveExpectation: T0, - expectation: T2, + expectation: TS1, }, { query: "select ks.t.id from (select 42 as id) as t", errorMessage: "column 'ks.t.id' not found", @@ -1003,24 +1003,24 @@ func TestScopingWDerivedTables(t *testing.T) { errorMessage: "Duplicate column name 'id'", }, { query: "select t.baz = 1 from (select id as baz from user) as t", - expectation: T2, - recursiveExpectation: T1, + expectation: TS1, + recursiveExpectation: TS0, }, { query: "select t.id from (select * from user, music) as t", - expectation: T3, - recursiveExpectation: MergeTableSets(T1, T2), + expectation: TS2, + recursiveExpectation: MergeTableSets(TS0, TS1), }, { query: "select t.id from (select * from user, music) as t order by t.id", - expectation: T3, - recursiveExpectation: MergeTableSets(T1, T2), + expectation: TS2, + recursiveExpectation: MergeTableSets(TS0, TS1), }, { query: "select t.id from (select * from user) as t join user as u on t.id = u.id", - expectation: T2, - recursiveExpectation: T1, + expectation: TS1, + recursiveExpectation: TS0, }, { query: "select t.col1 from t3 ua join (select t1.id, t1.col1 from t1 join t2) as t", - expectation: T4, - recursiveExpectation: T2, + expectation: TS3, + recursiveExpectation: TS1, }, { query: "select uu.test from (select id from t1) uu", errorMessage: "column 'uu.test' not found", @@ -1032,8 +1032,8 @@ func TestScopingWDerivedTables(t *testing.T) { errorMessage: "column 'uu.id' not found", }, { query: "select uu.id from (select id from t1) as uu where exists (select * from t2 as uu where uu.id = uu.uid)", - expectation: T2, - recursiveExpectation: T1, + expectation: TS1, + recursiveExpectation: TS0, }, { query: "select 1 from user uu where exists (select 1 from user where exists (select 1 from (select 1 from t1) uu where uu.user_id = uu.id))", expectation: T0, @@ -1064,6 +1064,48 @@ func TestScopingWDerivedTables(t *testing.T) { } } +func TestJoinPredicateDependencies(t *testing.T) { + // create table t() + // create table t1(id bigint) + // create table t2(uid bigint, name varchar(255)) + + queries := []struct { + query string + recursiveExpect TableSet + directExpect TableSet + }{{ + query: "select 1 from t1 join t2 on t1.id = t2.uid", + recursiveExpect: MergeTableSets(TS0, TS1), + directExpect: MergeTableSets(TS0, TS1), + }, { + query: "select 1 from (select * from t1) x join t2 on x.id = t2.uid", + recursiveExpect: MergeTableSets(TS0, TS2), + directExpect: MergeTableSets(TS1, TS2), + }, { + query: "select 1 from (select id from t1) x join t2 on x.id = t2.uid", + recursiveExpect: MergeTableSets(TS0, TS2), + directExpect: MergeTableSets(TS1, TS2), + }, { + query: "select 1 from (select id from t1 union select id from t) x join t2 on x.id = t2.uid", + recursiveExpect: MergeTableSets(TS0, TS1, TS3), + directExpect: MergeTableSets(TS2, TS3), + }} + for _, query := range queries { + t.Run(query.query, func(t *testing.T) { + parse, err := sqlparser.Parse(query.query) + require.NoError(t, err) + + st, err := Analyze(parse, "user", fakeSchemaInfo()) + require.NoError(t, err) + + sel := parse.(*sqlparser.Select) + expr := sel.From[0].(*sqlparser.JoinTableExpr).Condition.On + assert.Equal(t, query.recursiveExpect, st.RecursiveDeps(expr), "RecursiveDeps") + assert.Equal(t, query.directExpect, st.DirectDeps(expr), "DirectDeps") + }) + } +} + func TestDerivedTablesOrderClause(t *testing.T) { queries := []struct { query string @@ -1071,40 +1113,40 @@ func TestDerivedTablesOrderClause(t *testing.T) { expectation TableSet }{{ query: "select 1 from (select id from user) as t order by id", - recursiveExpectation: T1, - expectation: T2, + recursiveExpectation: TS0, + expectation: TS1, }, { query: "select id from (select id from user) as t order by id", - recursiveExpectation: T1, - expectation: T2, + recursiveExpectation: TS0, + expectation: TS1, }, { query: "select id from (select id from user) as t order by t.id", - recursiveExpectation: T1, - expectation: T2, + recursiveExpectation: TS0, + expectation: TS1, }, { query: "select id as foo from (select id from user) as t order by foo", - recursiveExpectation: T1, - expectation: T2, + recursiveExpectation: TS0, + expectation: TS1, }, { query: "select bar from (select id as bar from user) as t order by bar", - recursiveExpectation: T1, - expectation: T2, + recursiveExpectation: TS0, + expectation: TS1, }, { query: "select bar as foo from (select id as bar from user) as t order by bar", - recursiveExpectation: T1, - expectation: T2, + recursiveExpectation: TS0, + expectation: TS1, }, { query: "select bar as foo from (select id as bar from user) as t order by foo", - recursiveExpectation: T1, - expectation: T2, + recursiveExpectation: TS0, + expectation: TS1, }, { query: "select bar as foo from (select id as bar, oo from user) as t order by oo", - recursiveExpectation: T1, - expectation: T2, + recursiveExpectation: TS0, + expectation: TS1, }, { query: "select bar as foo from (select id, oo from user) as t(bar,oo) order by bar", - recursiveExpectation: T1, - expectation: T2, + recursiveExpectation: TS0, + expectation: TS1, }} si := &FakeSI{Tables: map[string]*vindexes.Table{"t": {Name: sqlparser.NewIdentifierCS("t")}}} for _, query := range queries { @@ -1132,13 +1174,13 @@ func TestScopingWComplexDerivedTables(t *testing.T) { }{ { query: "select 1 from user uu where exists (select 1 from user where exists (select 1 from (select 1 from t1) uu where uu.user_id = uu.id))", - rightExpectation: T1, - leftExpectation: T1, + rightExpectation: TS0, + leftExpectation: TS0, }, { query: "select 1 from user.user uu where exists (select 1 from user.user as uu where exists (select 1 from (select 1 from user.t1) uu where uu.user_id = uu.id))", - rightExpectation: T2, - leftExpectation: T2, + rightExpectation: TS1, + leftExpectation: TS1, }, } for _, query := range queries { @@ -1174,12 +1216,12 @@ func TestScopingWVindexTables(t *testing.T) { }{ { query: "select id from user_index where id = 1", - recursiveExpectation: T1, - expectation: T1, + recursiveExpectation: TS0, + expectation: TS0, }, { query: "select u.id + t.id from t as t join user_index as u where u.id = 1 and u.id = t.id", - recursiveExpectation: MergeTableSets(T1, T2), - expectation: MergeTableSets(T1, T2), + recursiveExpectation: MergeTableSets(TS0, TS1), + expectation: MergeTableSets(TS0, TS1), }, } for _, query := range queries { @@ -1536,6 +1578,9 @@ var ks3 = &vindexes.Keyspace{ Sharded: true, } +// create table t() +// create table t1(id bigint) +// create table t2(uid bigint, name varchar(255)) func fakeSchemaInfo() *FakeSI { cols1 := []vindexes.Column{{ Name: sqlparser.NewIdentifierCI("id"), diff --git a/go/vt/vtgate/semantics/derived_table.go b/go/vt/vtgate/semantics/derived_table.go index 4c32fdfd84c..66e10922a2e 100644 --- a/go/vt/vtgate/semantics/derived_table.go +++ b/go/vt/vtgate/semantics/derived_table.go @@ -27,13 +27,15 @@ import ( // DerivedTable contains the information about the projection, tables involved in derived table. type DerivedTable struct { - tableName string - ASTNode *sqlparser.AliasedTableExpr - columnNames []string - cols []sqlparser.Expr - tables TableSet - isAuthoritative bool - exprsNotExpanded bool + tableName string + ASTNode *sqlparser.AliasedTableExpr + columnNames []string + cols []sqlparser.Expr + tables TableSet + isAuthoritative bool + + recursive []TableSet + types []*Type } var _ TableInfo = (*DerivedTable)(nil) @@ -43,38 +45,53 @@ func createDerivedTableForExpressions( cols sqlparser.Columns, tables []TableInfo, org originable, - exprsNotExpanded bool, + expanded bool, + recursiveDeps []TableSet, + types []*Type, ) *DerivedTable { - vTbl := &DerivedTable{isAuthoritative: true, exprsNotExpanded: exprsNotExpanded} + vTbl := &DerivedTable{isAuthoritative: expanded, recursive: recursiveDeps, types: types} for i, selectExpr := range expressions { switch expr := selectExpr.(type) { case *sqlparser.AliasedExpr: - vTbl.cols = append(vTbl.cols, expr.Expr) - if len(cols) > 0 { - vTbl.columnNames = append(vTbl.columnNames, cols[i].String()) - } else if expr.As.IsEmpty() { - switch expr := expr.Expr.(type) { - case *sqlparser.ColName: - // for projections, we strip out the qualifier and keep only the column name - vTbl.columnNames = append(vTbl.columnNames, expr.Name.String()) - default: - vTbl.columnNames = append(vTbl.columnNames, sqlparser.String(expr)) - } - } else { - vTbl.columnNames = append(vTbl.columnNames, expr.As.String()) - } + handleAliasedExpr(vTbl, expr, cols, i) case *sqlparser.StarExpr: - for _, table := range tables { - vTbl.tables = vTbl.tables.Merge(table.getTableSet(org)) - if !table.authoritative() { - vTbl.isAuthoritative = false - } - } + handleUnexpandedStarExpression(tables, vTbl, org) } } return vTbl } +func handleAliasedExpr(vTbl *DerivedTable, expr *sqlparser.AliasedExpr, cols sqlparser.Columns, i int) { + vTbl.cols = append(vTbl.cols, expr.Expr) + + if len(cols) > 0 { + vTbl.columnNames = append(vTbl.columnNames, cols[i].String()) + return + } + + if !expr.As.IsEmpty() { + vTbl.columnNames = append(vTbl.columnNames, expr.As.String()) + return + } + + switch expr := expr.Expr.(type) { + case *sqlparser.ColName: + // for projections, we strip out the qualifier and keep only the column name + vTbl.columnNames = append(vTbl.columnNames, expr.Name.String()) + default: + vTbl.columnNames = append(vTbl.columnNames, sqlparser.String(expr)) + } +} + +func handleUnexpandedStarExpression(tables []TableInfo, vTbl *DerivedTable, org originable) { + for _, table := range tables { + vTbl.tables = vTbl.tables.Merge(table.getTableSet(org)) + if !table.authoritative() { + vTbl.isAuthoritative = false + } + } +} + // dependencies implements the TableInfo interface func (dt *DerivedTable) dependencies(colName string, org originable) (dependencies, error) { directDeps := org.tableSetFor(dt.ASTNode) @@ -82,7 +99,7 @@ func (dt *DerivedTable) dependencies(colName string, org originable) (dependenci if !strings.EqualFold(name, colName) { continue } - _, recursiveDeps, qt := org.depsForExpr(dt.cols[i]) + recursiveDeps, qt := dt.recursive[i], dt.types[i] return createCertain(directDeps, recursiveDeps, qt), nil } @@ -142,11 +159,14 @@ func (dt *DerivedTable) getTableSet(_ originable) TableSet { // GetExprFor implements the TableInfo interface func (dt *DerivedTable) getExprFor(s string) (sqlparser.Expr, error) { - if dt.exprsNotExpanded { + if !dt.isAuthoritative { return nil, vterrors.VT09015() } for i, colName := range dt.columnNames { if colName == s { + if i >= len(dt.cols) { + panic("oops") + } return dt.cols[i], nil } } diff --git a/go/vt/vtgate/semantics/semantic_state.go b/go/vt/vtgate/semantics/semantic_state.go index 7adcd4598a4..b050d7979be 100644 --- a/go/vt/vtgate/semantics/semantic_state.go +++ b/go/vt/vtgate/semantics/semantic_state.go @@ -111,6 +111,8 @@ type ( // The columns were added because of the use of `*` in the query ExpandedColumns map[sqlparser.TableName][]*sqlparser.ColName + columns map[*sqlparser.Union]sqlparser.SelectExprs + comparator *sqlparser.Comparator } @@ -137,6 +139,40 @@ func (st *SemTable) CopyDependencies(from, to sqlparser.Expr) { st.Direct[to] = st.DirectDeps(from) } +func (st *SemTable) SelectExprs(sel sqlparser.SelectStatement) sqlparser.SelectExprs { + switch sel := sel.(type) { + case *sqlparser.Select: + return sel.SelectExprs + case *sqlparser.Union: + exprs, found := st.columns[sel] + if found { + return exprs + } + + firstSelect := sqlparser.GetFirstSelect(sel) + _, selectExprs := getColumnNames(firstSelect.SelectExprs) + st.columns[sel] = selectExprs + return selectExprs + } + + return nil +} + +func getColumnNames(exprs sqlparser.SelectExprs) (expanded bool, selectExprs sqlparser.SelectExprs) { + expanded = true + for _, col := range exprs { + switch col := col.(type) { + case *sqlparser.AliasedExpr: + expr := sqlparser.NewColName(col.ColumnName()) + selectExprs = append(selectExprs, &sqlparser.AliasedExpr{Expr: expr}) + default: + selectExprs = append(selectExprs, col) + expanded = false + } + } + return +} + // CopyDependenciesOnSQLNodes copies the dependencies from one expression into the other func (st *SemTable) CopyDependenciesOnSQLNodes(from, to sqlparser.SQLNode) { f, ok := from.(sqlparser.Expr) @@ -166,6 +202,7 @@ func EmptySemTable() *SemTable { Recursive: map[sqlparser.Expr]TableSet{}, Direct: map[sqlparser.Expr]TableSet{}, ColumnEqualities: map[columnName][]sqlparser.Expr{}, + columns: map[*sqlparser.Union]sqlparser.SelectExprs{}, } } diff --git a/go/vt/vtgate/semantics/table_collector.go b/go/vt/vtgate/semantics/table_collector.go index 1219b54d2ea..57621062e7a 100644 --- a/go/vt/vtgate/semantics/table_collector.go +++ b/go/vt/vtgate/semantics/table_collector.go @@ -32,6 +32,7 @@ type tableCollector struct { si SchemaInformation currentDb string org originable + columns map[*sqlparser.Union]sqlparser.SelectExprs } func newTableCollector(scoper *scoper, si SchemaInformation, currentDb string) *tableCollector { @@ -39,6 +40,7 @@ func newTableCollector(scoper *scoper, si SchemaInformation, currentDb string) * scoper: scoper, si: si, currentDb: currentDb, + columns: map[*sqlparser.Union]sqlparser.SelectExprs{}, } } @@ -51,33 +53,10 @@ func (tc *tableCollector) up(cursor *sqlparser.Cursor) error { case *sqlparser.DerivedTable: switch sel := t.Select.(type) { case *sqlparser.Select: - tables := tc.scoper.wScope[sel] - tableInfo := createDerivedTableForExpressions(sqlparser.GetFirstSelect(sel).SelectExprs, node.Columns, tables.tables, tc.org, false) - if err := tableInfo.checkForDuplicates(); err != nil { - return err - } - - tableInfo.ASTNode = node - tableInfo.tableName = node.As.String() - - tc.Tables = append(tc.Tables, tableInfo) - scope := tc.scoper.currentScope() - return scope.addTable(tableInfo) + return tc.addSelectDerivedTable(sel, node) case *sqlparser.Union: - firstSelect := sqlparser.GetFirstSelect(sel) - tables := tc.scoper.wScope[firstSelect] - unableToExpandUnion, selectExprs := sqlparser.GetColumnNames(firstSelect.SelectExprs) - tableInfo := createDerivedTableForExpressions(selectExprs, node.Columns, tables.tables, tc.org, unableToExpandUnion) - if err := tableInfo.checkForDuplicates(); err != nil { - return err - } - tableInfo.ASTNode = node - tableInfo.tableName = node.As.String() - - tc.Tables = append(tc.Tables, tableInfo) - scope := tc.scoper.currentScope() - return scope.addTable(tableInfo) + return tc.addUnionDerivedTable(sel, node) default: return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] %T in a derived table", sel) @@ -106,6 +85,75 @@ func (tc *tableCollector) up(cursor *sqlparser.Cursor) error { return nil } +func (tc *tableCollector) addSelectDerivedTable(sel *sqlparser.Select, node *sqlparser.AliasedTableExpr) error { + tables := tc.scoper.wScope[sel] + size := len(sel.SelectExprs) + deps := make([]TableSet, size) + types := make([]*Type, size) + expanded := true + for i, expr := range sel.SelectExprs { + ae, ok := expr.(*sqlparser.AliasedExpr) + if !ok { + expanded = false + continue + } + _, deps[i], types[i] = tc.org.depsForExpr(ae.Expr) + } + + tableInfo := createDerivedTableForExpressions(sel.SelectExprs, node.Columns, tables.tables, tc.org, expanded, deps, types) + if err := tableInfo.checkForDuplicates(); err != nil { + return err + } + + tableInfo.ASTNode = node + tableInfo.tableName = node.As.String() + + tc.Tables = append(tc.Tables, tableInfo) + scope := tc.scoper.currentScope() + return scope.addTable(tableInfo) +} + +func (tc *tableCollector) addUnionDerivedTable(union *sqlparser.Union, node *sqlparser.AliasedTableExpr) error { + firstSelect := sqlparser.GetFirstSelect(union) + expanded, selectExprs := getColumnNames(firstSelect.SelectExprs) + tables := tc.scoper.wScope[firstSelect] + var deps []TableSet + var types []*Type + if expanded { + tc.columns[union] = selectExprs + size := len(firstSelect.SelectExprs) + deps = make([]TableSet, size) + types = make([]*Type, size) + + _ = sqlparser.VisitAllSelects(union, func(s *sqlparser.Select, idx int) error { + for i, expr := range s.SelectExprs { + ae, ok := expr.(*sqlparser.AliasedExpr) + if !ok { + continue + } + _, recursiveDeps, qt := tc.org.depsForExpr(ae.Expr) + deps[i] = deps[i].Merge(recursiveDeps) + if idx == 0 { + // we probably should coerce these types together somehow, but I'm not sure how + types = append(types, qt) + } + } + return nil + }) + } + + tableInfo := createDerivedTableForExpressions(selectExprs, node.Columns, tables.tables, tc.org, expanded, deps, types) + if err := tableInfo.checkForDuplicates(); err != nil { + return err + } + tableInfo.ASTNode = node + tableInfo.tableName = node.As.String() + + tc.Tables = append(tc.Tables, tableInfo) + scope := tc.scoper.currentScope() + return scope.addTable(tableInfo) +} + func newVindexTable(t sqlparser.IdentifierCS) *vindexes.Table { vindexCols := []vindexes.Column{ {Name: sqlparser.NewIdentifierCI("id"), Type: querypb.Type_VARBINARY}, From 6eb1e87c6b56a65bfa192207f9d5147744945e50 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Wed, 19 Jul 2023 13:30:15 +0200 Subject: [PATCH 18/44] make sure that UNION reports enough columns so column truncation can happen correctly Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/operators/union.go | 26 +++ .../testdata/info_schema57_cases.json | 2 + .../testdata/info_schema80_cases.json | 2 + .../planbuilder/testdata/union_cases.json | 211 ++++++++++-------- 4 files changed, 151 insertions(+), 90 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/union.go b/go/vt/vtgate/planbuilder/operators/union.go index e1b1f064073..6ecd1130170 100644 --- a/go/vt/vtgate/planbuilder/operators/union.go +++ b/go/vt/vtgate/planbuilder/operators/union.go @@ -307,10 +307,36 @@ func (u *Union) GetColumns(ctx *plancontext.PlanningContext) (result []*sqlparse } } + // if any of the inputs has more columns that we expect, we want to show on top of UNION, so the results can + // be truncated to the expected result columns and nothing else + for _, src := range u.Sources { + columns, err := src.GetColumns(ctx) + if err != nil { + return nil, err + } + + for len(columns) > len(u.unionColumnsAsAlisedExprs) { + u.unionColumnsAsAlisedExprs = append(u.unionColumnsAsAlisedExprs, aeWrap(sqlparser.NewIntLiteral("0"))) + } + } + return u.unionColumnsAsAlisedExprs, nil } func (u *Union) GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.SelectExprs, error) { + // if any of the inputs has more columns that we expect, we want to show on top of UNION, so the results can + // be truncated to the expected result columns and nothing else + for _, src := range u.Sources { + columns, err := src.GetSelectExprs(ctx) + if err != nil { + return nil, err + } + + for len(columns) > len(u.unionColumns) { + u.unionColumns = append(u.unionColumns, aeWrap(sqlparser.NewIntLiteral("0"))) + } + } + return u.unionColumns, nil } diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json index 668157cc148..c92e661374b 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json @@ -105,6 +105,7 @@ "Collations": [ "(0:1)" ], + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Concatenate", @@ -168,6 +169,7 @@ "(19:40)", "(20:41)" ], + "ResultColumns": 21, "Inputs": [ { "OperatorType": "Concatenate", diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json index a20695d3868..d724bfcbc09 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json @@ -105,6 +105,7 @@ "Collations": [ "(0:1)" ], + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Concatenate", @@ -168,6 +169,7 @@ "(19:40)", "(20:41)" ], + "ResultColumns": 21, "Inputs": [ { "OperatorType": "Concatenate", diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 3f3ea92f564..d03a5fd5b17 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -87,41 +87,49 @@ "QueryType": "SELECT", "Original": "(SELECT id FROM user ORDER BY id DESC LIMIT 1) UNION ALL (SELECT id FROM music ORDER BY id DESC LIMIT 1)", "Instructions": { - "OperatorType": "Concatenate", + "OperatorType": "SimpleProjection", + "Columns": [ + 0 + ], "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(1)", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", - "Table": "`user`" - } - ] - }, - { - "OperatorType": "Limit", - "Count": "INT64(1)", - "Inputs": [ + "OperatorType": "Limit", + "Count": "INT64(1)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", + "Table": "`user`" + } + ] + }, { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from music where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", - "Table": "music" + "OperatorType": "Limit", + "Count": "INT64(1)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from music where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", + "Table": "music" + } + ] } ] } @@ -209,41 +217,49 @@ "QueryType": "SELECT", "Original": "(select id from user order by id limit 5) union all (select id from music order by id desc limit 5)", "Instructions": { - "OperatorType": "Concatenate", + "OperatorType": "SimpleProjection", + "Columns": [ + 0 + ], "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(5)", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) ASC", - "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", - "Table": "`user`" - } - ] - }, - { - "OperatorType": "Limit", - "Count": "INT64(5)", - "Inputs": [ + "OperatorType": "Limit", + "Count": "INT64(5)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) ASC", + "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", + "Table": "`user`" + } + ] + }, { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from music where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", - "Table": "music" + "OperatorType": "Limit", + "Count": "INT64(5)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from music where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", + "Table": "music" + } + ] } ] } @@ -288,6 +304,7 @@ "Collations": [ "(0:1)" ], + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Concatenate", @@ -499,6 +516,7 @@ "(0:2)", "(1:3)" ], + "ResultColumns": 2, "Inputs": [ { "OperatorType": "Concatenate", @@ -566,6 +584,7 @@ "(0:2)", "(1:3)" ], + "ResultColumns": 2, "Inputs": [ { "OperatorType": "Concatenate", @@ -632,6 +651,7 @@ "Collations": [ "(0:1)" ], + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Concatenate", @@ -750,6 +770,7 @@ "Collations": [ "(0:1)" ], + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Concatenate", @@ -884,6 +905,7 @@ "Collations": [ "(0:1)" ], + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Concatenate", @@ -959,41 +981,49 @@ "TableName": "`user`_`user`", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "SimpleProjection", + "Columns": [ + 0 + ], "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(5)", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) ASC", - "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", - "Table": "`user`" - } - ] - }, - { - "OperatorType": "Limit", - "Count": "INT64(5)", - "Inputs": [ + "OperatorType": "Limit", + "Count": "INT64(5)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) ASC", + "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", + "Table": "`user`" + } + ] + }, { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", - "Table": "`user`" + "OperatorType": "Limit", + "Count": "INT64(5)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", + "Table": "`user`" + } + ] } ] } @@ -1214,6 +1244,7 @@ "(1:4)", "(2:5)" ], + "ResultColumns": 3, "Inputs": [ { "OperatorType": "Concatenate", From fed1124894d2ac9ab21d2b00eaaf8ec141fec5e9 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Wed, 19 Jul 2023 16:49:12 +0200 Subject: [PATCH 19/44] handle types and dependencies better for UNIONs not in derived tables Signed-off-by: Andres Taylor --- .../testdata/info_schema57_cases.json | 72 ++++++++--------- .../testdata/info_schema80_cases.json | 72 ++++++++--------- .../planbuilder/testdata/union_cases.json | 80 +++++++++---------- go/vt/vtgate/semantics/analyzer.go | 17 ++-- go/vt/vtgate/semantics/binder.go | 13 +++ go/vt/vtgate/semantics/derived_table.go | 7 ++ go/vt/vtgate/semantics/semantic_state.go | 6 +- go/vt/vtgate/semantics/table_collector.go | 76 +++++++++++------- 8 files changed, 186 insertions(+), 157 deletions(-) diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json index c92e661374b..c0beebde7aa 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json @@ -103,9 +103,8 @@ "Instructions": { "OperatorType": "Distinct", "Collations": [ - "(0:1)" + "0: utf8mb4_0900_ai_ci" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Concatenate", @@ -117,8 +116,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns` where 1 != 1", - "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns`", + "FieldQuery": "select TABLE_NAME from information_schema.`columns` where 1 != 1", + "Query": "select distinct TABLE_NAME from information_schema.`columns`", "Table": "information_schema.`columns`" }, { @@ -128,8 +127,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select table_schema, weight_string(table_schema) from information_schema.`tables` where 1 != 1", - "Query": "select distinct table_schema, weight_string(table_schema) from information_schema.`tables`", + "FieldQuery": "select table_schema from information_schema.`tables` where 1 != 1", + "Query": "select distinct table_schema from information_schema.`tables`", "Table": "information_schema.`tables`" } ] @@ -147,29 +146,28 @@ "Instructions": { "OperatorType": "Distinct", "Collations": [ - "(0:21)", - "(1:22)", - "(2:23)", - "(3:24)", - "(4:25)", - "(5:26)", - "(6:27)", - "(7:28)", - "(8:29)", - "(9:30)", - "(10:31)", - "(11:32)", - "(12:33)", - "(13:34)", - "(14:35)", - "(15:36)", - "(16:37)", - "(17:38)", - "(18:39)", - "(19:40)", - "(20:41)" + "0: utf8mb4_0900_ai_ci", + "1: utf8mb4_0900_ai_ci", + "2: utf8mb4_0900_ai_ci", + "3: utf8mb4_0900_ai_ci", + "4: utf8mb4_0900_ai_ci", + "5", + "6: utf8mb4_0900_ai_ci", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17: utf8mb4_0900_ai_ci", + "18", + "19: utf8mb4_0900_ai_ci", + "20: utf8mb4_0900_ai_ci" ], - "ResultColumns": 21, "Inputs": [ { "OperatorType": "Concatenate", @@ -181,8 +179,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where 1 != 1", - "Query": "select distinct TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where 1 != 1", + "Query": "select distinct TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", "SysTableTableSchema": "[VARCHAR(\"user\")]", "Table": "information_schema.`tables`" }, @@ -193,8 +191,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where 1 != 1", - "Query": "select distinct TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where 1 != 1", + "Query": "select distinct TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", "SysTableTableSchema": "[VARCHAR(\"main\")]", "Table": "information_schema.`tables`" } @@ -1014,7 +1012,7 @@ { "OperatorType": "Distinct", "Collations": [ - "(0:1)" + "0: utf8mb4_0900_ai_ci" ], "Inputs": [ { @@ -1027,8 +1025,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`tables` as t where 1 != 1", - "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */", + "FieldQuery": "select TABLE_NAME from information_schema.`tables` as t where 1 != 1", + "Query": "select distinct TABLE_NAME from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */", "SysTableTableSchema": "[VARCHAR(\"a\")]", "Table": "information_schema.`tables`" }, @@ -1039,8 +1037,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns` where 1 != 1", - "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns`", + "FieldQuery": "select TABLE_NAME from information_schema.`columns` where 1 != 1", + "Query": "select distinct TABLE_NAME from information_schema.`columns`", "Table": "information_schema.`columns`" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json index d724bfcbc09..648c434e396 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json @@ -103,9 +103,8 @@ "Instructions": { "OperatorType": "Distinct", "Collations": [ - "(0:1)" + "0: utf8mb4_0900_ai_ci" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Concatenate", @@ -117,8 +116,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns` where 1 != 1", - "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns`", + "FieldQuery": "select TABLE_NAME from information_schema.`columns` where 1 != 1", + "Query": "select distinct TABLE_NAME from information_schema.`columns`", "Table": "information_schema.`columns`" }, { @@ -128,8 +127,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select table_schema, weight_string(table_schema) from information_schema.`tables` where 1 != 1", - "Query": "select distinct table_schema, weight_string(table_schema) from information_schema.`tables`", + "FieldQuery": "select table_schema from information_schema.`tables` where 1 != 1", + "Query": "select distinct table_schema from information_schema.`tables`", "Table": "information_schema.`tables`" } ] @@ -147,29 +146,28 @@ "Instructions": { "OperatorType": "Distinct", "Collations": [ - "(0:21)", - "(1:22)", - "(2:23)", - "(3:24)", - "(4:25)", - "(5:26)", - "(6:27)", - "(7:28)", - "(8:29)", - "(9:30)", - "(10:31)", - "(11:32)", - "(12:33)", - "(13:34)", - "(14:35)", - "(15:36)", - "(16:37)", - "(17:38)", - "(18:39)", - "(19:40)", - "(20:41)" + "0: utf8mb4_0900_ai_ci", + "1: utf8mb4_0900_ai_ci", + "2: utf8mb4_0900_ai_ci", + "3", + "4: utf8mb4_0900_ai_ci", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17: utf8mb4_0900_ai_ci", + "18", + "19: utf8mb4_0900_ai_ci", + "20: utf8mb4_0900_ai_ci" ], - "ResultColumns": 21, "Inputs": [ { "OperatorType": "Concatenate", @@ -181,8 +179,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where 1 != 1", - "Query": "select distinct TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where 1 != 1", + "Query": "select distinct TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", "SysTableTableSchema": "[VARCHAR(\"user\")]", "Table": "information_schema.`tables`" }, @@ -193,8 +191,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where 1 != 1", - "Query": "select distinct TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT, weight_string(TABLE_CATALOG), weight_string(TABLE_SCHEMA), weight_string(TABLE_NAME), weight_string(TABLE_TYPE), weight_string(`ENGINE`), weight_string(VERSION), weight_string(`ROW_FORMAT`), weight_string(TABLE_ROWS), weight_string(`AVG_ROW_LENGTH`), weight_string(DATA_LENGTH), weight_string(MAX_DATA_LENGTH), weight_string(INDEX_LENGTH), weight_string(DATA_FREE), weight_string(`AUTO_INCREMENT`), weight_string(CREATE_TIME), weight_string(UPDATE_TIME), weight_string(CHECK_TIME), weight_string(TABLE_COLLATION), weight_string(`CHECKSUM`), weight_string(CREATE_OPTIONS), weight_string(TABLE_COMMENT) from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "FieldQuery": "select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where 1 != 1", + "Query": "select distinct TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, `ENGINE`, VERSION, `ROW_FORMAT`, TABLE_ROWS, `AVG_ROW_LENGTH`, DATA_LENGTH, MAX_DATA_LENGTH, INDEX_LENGTH, DATA_FREE, `AUTO_INCREMENT`, CREATE_TIME, UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, `CHECKSUM`, CREATE_OPTIONS, TABLE_COMMENT from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", "SysTableTableSchema": "[VARCHAR(\"main\")]", "Table": "information_schema.`tables`" } @@ -1079,7 +1077,7 @@ { "OperatorType": "Distinct", "Collations": [ - "(0:1)" + "0: utf8mb4_0900_ai_ci" ], "Inputs": [ { @@ -1092,8 +1090,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`tables` as t where 1 != 1", - "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */", + "FieldQuery": "select TABLE_NAME from information_schema.`tables` as t where 1 != 1", + "Query": "select distinct TABLE_NAME from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */", "SysTableTableSchema": "[VARCHAR(\"a\")]", "Table": "information_schema.`tables`" }, @@ -1104,8 +1102,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns` where 1 != 1", - "Query": "select distinct TABLE_NAME, weight_string(TABLE_NAME) from information_schema.`columns`", + "FieldQuery": "select TABLE_NAME from information_schema.`columns` where 1 != 1", + "Query": "select distinct TABLE_NAME from information_schema.`columns`", "Table": "information_schema.`columns`" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index d03a5fd5b17..13120cff973 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -302,9 +302,8 @@ "Instructions": { "OperatorType": "Distinct", "Collations": [ - "(0:1)" + "0: utf8mb4_0900_ai_ci" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Concatenate", @@ -316,8 +315,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select CHARACTER_SET_NAME, weight_string(CHARACTER_SET_NAME) from information_schema.CHARACTER_SETS where 1 != 1", - "Query": "select distinct CHARACTER_SET_NAME, weight_string(CHARACTER_SET_NAME) from information_schema.CHARACTER_SETS", + "FieldQuery": "select CHARACTER_SET_NAME from information_schema.CHARACTER_SETS where 1 != 1", + "Query": "select distinct CHARACTER_SET_NAME from information_schema.CHARACTER_SETS", "Table": "information_schema.CHARACTER_SETS" }, { @@ -327,8 +326,8 @@ "Name": "main", "Sharded": false }, - "FieldQuery": "select user_name, weight_string(user_name) from unsharded where 1 != 1", - "Query": "select distinct user_name, weight_string(user_name) from unsharded", + "FieldQuery": "select user_name from unsharded where 1 != 1", + "Query": "select distinct user_name from unsharded", "Table": "unsharded" } ] @@ -481,9 +480,8 @@ "Instructions": { "OperatorType": "Distinct", "Collations": [ - "(0:1)" + "0" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Route", @@ -492,8 +490,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select `1`, weight_string(`1`) from (select 1 from dual where 1 != 1 union select null from dual where 1 != 1 union select 1.0 from dual where 1 != 1 union select '1' from dual where 1 != 1 union select 2 from dual where 1 != 1 union select 2.0 from `user` where 1 != 1) as dt where 1 != 1", - "Query": "select `1`, weight_string(`1`) from (select 1 from dual union select null from dual union select 1.0 from dual union select '1' from dual union select 2 from dual union select 2.0 from `user`) as dt", + "FieldQuery": "select 1 from dual where 1 != 1 union select null from dual where 1 != 1 union select 1.0 from dual where 1 != 1 union select '1' from dual where 1 != 1 union select 2 from dual where 1 != 1 union select 2.0 from `user` where 1 != 1", + "Query": "select 1 from dual union select null from dual union select 1.0 from dual union select '1' from dual union select 2 from dual union select 2.0 from `user`", "Table": "`user`, dual" } ] @@ -581,10 +579,9 @@ "Instructions": { "OperatorType": "Distinct", "Collations": [ - "(0:2)", - "(1:3)" + "0: utf8mb4_0900_ai_ci", + "1: utf8mb4_0900_ai_ci" ], - "ResultColumns": 2, "Inputs": [ { "OperatorType": "Concatenate", @@ -596,14 +593,14 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select 'b', 'c', weight_string('b'), weight_string('c') from `user` where 1 != 1", - "Query": "select distinct 'b', 'c', weight_string('b'), weight_string('c') from `user`", + "FieldQuery": "select 'b', 'c' from `user` where 1 != 1", + "Query": "select distinct 'b', 'c' from `user`", "Table": "`user`" }, { "OperatorType": "Join", "Variant": "Join", - "JoinColumnIndexes": "L:0,L:1,L:2,L:3", + "JoinColumnIndexes": "L:0,L:1", "TableName": "`user`_user_extra", "Inputs": [ { @@ -613,8 +610,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select `user`.id, `user`.`name`, weight_string(`user`.id), weight_string(`user`.`name`) from `user` where 1 != 1", - "Query": "select distinct `user`.id, `user`.`name`, weight_string(`user`.id), weight_string(`user`.`name`) from `user`", + "FieldQuery": "select `user`.id, `user`.`name` from `user` where 1 != 1", + "Query": "select distinct `user`.id, `user`.`name` from `user`", "Table": "`user`" }, { @@ -649,9 +646,8 @@ "Instructions": { "OperatorType": "Distinct", "Collations": [ - "(0:1)" + "0" ], - "ResultColumns": 1, "Inputs": [ { "OperatorType": "Concatenate", @@ -659,14 +655,13 @@ { "OperatorType": "Distinct", "Collations": [ - "0", - "(1:2)" + "0" ], "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Scalar", - "Aggregates": "sum_count_star(0) AS s, any_value(1), any_value(2)", + "Aggregates": "sum_count_star(0) AS s", "Inputs": [ { "OperatorType": "Route", @@ -675,8 +670,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select count(*) as s, weight_string(count(*)), weight_string(weight_string(count(*))) from `user` where 1 != 1", - "Query": "select count(*) as s, weight_string(count(*)), weight_string(weight_string(count(*))) from `user`", + "FieldQuery": "select count(*) as s from `user` where 1 != 1", + "Query": "select count(*) as s from `user`", "Table": "`user`" } ] @@ -686,14 +681,13 @@ { "OperatorType": "Distinct", "Collations": [ - "0", - "(1:2)" + "0" ], "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Scalar", - "Aggregates": "sum_count_star(0) AS s, any_value(1), any_value(2)", + "Aggregates": "sum_count_star(0) AS s", "Inputs": [ { "OperatorType": "Route", @@ -702,8 +696,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select count(*) as s, weight_string(count(*)), weight_string(weight_string(count(*))) from music where 1 != 1", - "Query": "select count(*) as s, weight_string(count(*)), weight_string(weight_string(count(*))) from music", + "FieldQuery": "select count(*) as s from music where 1 != 1", + "Query": "select count(*) as s from music", "Table": "music" } ] @@ -729,13 +723,14 @@ "Instructions": { "OperatorType": "SimpleProjection", "Columns": [ - 0 + 1 ], "Inputs": [ { "OperatorType": "Distinct", "Collations": [ - "(0:1)" + "(0:2)", + "(1:3)" ], "Inputs": [ { @@ -745,8 +740,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select id + 1 from `user` where 1 != 1 union select user_id from user_extra where 1 != 1) as dt where 1 != 1", - "Query": "select id, weight_string(id) from (select id from `user` union select id + 1 from `user` union select user_id from user_extra) as dt", + "FieldQuery": "select id, weight_string(id), weight_string(id) from (select id from `user` where 1 != 1 union select id + 1 from `user` where 1 != 1 union select user_id from user_extra where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id), weight_string(id) from (select id from `user` union select id + 1 from `user` union select user_id from user_extra) as dt", "Table": "`user`, user_extra" } ] @@ -778,21 +773,22 @@ { "OperatorType": "Distinct", "Collations": [ - "(0:1)", - "(1:2)" + "(0:2)", + "(1:3)" ], "Inputs": [ { "OperatorType": "Sort", "Variant": "Memory", - "OrderBy": "(0|1) ASC", + "OrderBy": "(0|2) ASC", "Inputs": [ { "OperatorType": "Distinct", "Collations": [ - "(0:1)", - "(1:2)", - "(2:3)" + "(0:2)", + "(1:3)", + "(2:4)", + "(3:5)" ], "Inputs": [ { @@ -802,8 +798,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id, weight_string(id), weight_string(weight_string(id)), weight_string(weight_string(weight_string(id))) from (select id from `user` where 1 != 1 union select id from music where 1 != 1) as dt where 1 != 1", - "Query": "select id, weight_string(id), weight_string(weight_string(id)), weight_string(weight_string(weight_string(id))) from (select id from `user` union select id from music) as dt", + "FieldQuery": "select id, weight_string(id), weight_string(id), weight_string(weight_string(id)), weight_string(weight_string(id)), weight_string(weight_string(weight_string(id))) from (select id from `user` where 1 != 1 union select id from music where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id), weight_string(id), weight_string(weight_string(id)), weight_string(weight_string(id)), weight_string(weight_string(weight_string(id))) from (select id from `user` union select id from music) as dt", "Table": "`user`, music" } ] diff --git a/go/vt/vtgate/semantics/analyzer.go b/go/vt/vtgate/semantics/analyzer.go index 2f61d97300a..5b560ec7075 100644 --- a/go/vt/vtgate/semantics/analyzer.go +++ b/go/vt/vtgate/semantics/analyzer.go @@ -101,6 +101,10 @@ func (a *analyzer) newSemTable(statement sqlparser.Statement, coll collations.ID if isCommented { comments = commentedStmt.GetParsedComments() } + columns := map[*sqlparser.Union]sqlparser.SelectExprs{} + for union, info := range a.tables.unionInfo { + columns[union] = info.exprs + } return &SemTable{ Recursive: a.binder.recursive, @@ -116,7 +120,7 @@ func (a *analyzer) newSemTable(statement sqlparser.Statement, coll collations.ID ColumnEqualities: map[columnName][]sqlparser.Expr{}, Collation: coll, ExpandedColumns: a.rewriter.expandedColumns, - columns: a.tables.columns, + columns: columns, } } @@ -169,11 +173,6 @@ func (a *analyzer) analyzeUp(cursor *sqlparser.Cursor) bool { return false } - if err := a.binder.up(cursor); err != nil { - a.setError(err) - return true - } - if err := a.scoper.up(cursor); err != nil { a.setError(err) return false @@ -182,6 +181,12 @@ func (a *analyzer) analyzeUp(cursor *sqlparser.Cursor) bool { a.setError(err) return false } + + if err := a.binder.up(cursor); err != nil { + a.setError(err) + return true + } + if err := a.typer.up(cursor); err != nil { a.setError(err) return false diff --git a/go/vt/vtgate/semantics/binder.go b/go/vt/vtgate/semantics/binder.go index b9239fae69f..dd65bc712c4 100644 --- a/go/vt/vtgate/semantics/binder.go +++ b/go/vt/vtgate/semantics/binder.go @@ -116,6 +116,19 @@ func (b *binder) up(cursor *sqlparser.Cursor) error { } case *sqlparser.CountStar: b.bindCountStar(node) + case *sqlparser.Union: + info := b.tc.unionInfo[node] + if !info.isAuthoritative { + return nil + } + + for i, expr := range info.exprs { + ae := expr.(*sqlparser.AliasedExpr) + b.recursive[ae.Expr] = info.recursive[i] + if t := info.types[i]; t != nil { + b.typer.exprTypes[ae.Expr] = *t + } + } } return nil } diff --git a/go/vt/vtgate/semantics/derived_table.go b/go/vt/vtgate/semantics/derived_table.go index 66e10922a2e..584665a1f7f 100644 --- a/go/vt/vtgate/semantics/derived_table.go +++ b/go/vt/vtgate/semantics/derived_table.go @@ -38,6 +38,13 @@ type DerivedTable struct { types []*Type } +type unionInfo struct { + isAuthoritative bool + recursive []TableSet + types []*Type + exprs sqlparser.SelectExprs +} + var _ TableInfo = (*DerivedTable)(nil) func createDerivedTableForExpressions( diff --git a/go/vt/vtgate/semantics/semantic_state.go b/go/vt/vtgate/semantics/semantic_state.go index b050d7979be..9163ef910a3 100644 --- a/go/vt/vtgate/semantics/semantic_state.go +++ b/go/vt/vtgate/semantics/semantic_state.go @@ -148,11 +148,7 @@ func (st *SemTable) SelectExprs(sel sqlparser.SelectStatement) sqlparser.SelectE if found { return exprs } - - firstSelect := sqlparser.GetFirstSelect(sel) - _, selectExprs := getColumnNames(firstSelect.SelectExprs) - st.columns[sel] = selectExprs - return selectExprs + panic("what the what") } return nil diff --git a/go/vt/vtgate/semantics/table_collector.go b/go/vt/vtgate/semantics/table_collector.go index 57621062e7a..92795cee880 100644 --- a/go/vt/vtgate/semantics/table_collector.go +++ b/go/vt/vtgate/semantics/table_collector.go @@ -32,7 +32,7 @@ type tableCollector struct { si SchemaInformation currentDb string org originable - columns map[*sqlparser.Union]sqlparser.SelectExprs + unionInfo map[*sqlparser.Union]unionInfo } func newTableCollector(scoper *scoper, si SchemaInformation, currentDb string) *tableCollector { @@ -40,15 +40,52 @@ func newTableCollector(scoper *scoper, si SchemaInformation, currentDb string) * scoper: scoper, si: si, currentDb: currentDb, - columns: map[*sqlparser.Union]sqlparser.SelectExprs{}, + unionInfo: map[*sqlparser.Union]unionInfo{}, } } func (tc *tableCollector) up(cursor *sqlparser.Cursor) error { - node, ok := cursor.Node().(*sqlparser.AliasedTableExpr) - if !ok { - return nil + switch node := cursor.Node().(type) { + case *sqlparser.AliasedTableExpr: + return tc.visitAliasedTableExpr(node) + case *sqlparser.Union: + firstSelect := sqlparser.GetFirstSelect(node) + expanded, selectExprs := getColumnNames(firstSelect.SelectExprs) + info := unionInfo{ + isAuthoritative: expanded, + exprs: selectExprs, + } + tc.unionInfo[node] = info + if !expanded { + return nil + } + + size := len(firstSelect.SelectExprs) + info.recursive = make([]TableSet, size) + info.types = make([]*Type, size) + + _ = sqlparser.VisitAllSelects(node, func(s *sqlparser.Select, idx int) error { + for i, expr := range s.SelectExprs { + ae, ok := expr.(*sqlparser.AliasedExpr) + if !ok { + continue + } + _, recursiveDeps, qt := tc.org.depsForExpr(ae.Expr) + info.recursive[i] = info.recursive[i].Merge(recursiveDeps) + if idx == 0 { + // TODO: we probably should coerce these types together somehow, but I'm not sure how + info.types[i] = qt + } + } + return nil + }) + tc.unionInfo[node] = info } + + return nil +} + +func (tc *tableCollector) visitAliasedTableExpr(node *sqlparser.AliasedTableExpr) error { switch t := node.Expr.(type) { case *sqlparser.DerivedTable: switch sel := t.Select.(type) { @@ -115,34 +152,13 @@ func (tc *tableCollector) addSelectDerivedTable(sel *sqlparser.Select, node *sql func (tc *tableCollector) addUnionDerivedTable(union *sqlparser.Union, node *sqlparser.AliasedTableExpr) error { firstSelect := sqlparser.GetFirstSelect(union) - expanded, selectExprs := getColumnNames(firstSelect.SelectExprs) tables := tc.scoper.wScope[firstSelect] - var deps []TableSet - var types []*Type - if expanded { - tc.columns[union] = selectExprs - size := len(firstSelect.SelectExprs) - deps = make([]TableSet, size) - types = make([]*Type, size) - - _ = sqlparser.VisitAllSelects(union, func(s *sqlparser.Select, idx int) error { - for i, expr := range s.SelectExprs { - ae, ok := expr.(*sqlparser.AliasedExpr) - if !ok { - continue - } - _, recursiveDeps, qt := tc.org.depsForExpr(ae.Expr) - deps[i] = deps[i].Merge(recursiveDeps) - if idx == 0 { - // we probably should coerce these types together somehow, but I'm not sure how - types = append(types, qt) - } - } - return nil - }) + info, found := tc.unionInfo[union] + if !found { + panic("what the what") } - tableInfo := createDerivedTableForExpressions(selectExprs, node.Columns, tables.tables, tc.org, expanded, deps, types) + tableInfo := createDerivedTableForExpressions(info.exprs, node.Columns, tables.tables, tc.org, info.isAuthoritative, info.recursive, info.types) if err := tableInfo.checkForDuplicates(); err != nil { return err } From 07cf4f854596be13b6ce3cfd71ad240f60615183 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 21 Jul 2023 15:16:10 +0200 Subject: [PATCH 20/44] clean up Disinct operator handling Signed-off-by: Andres Taylor --- .../vtgate/planbuilder/operators/distinct.go | 49 +++++------ .../operators/horizon_expanding.go | 2 +- .../planbuilder/operators/horizon_planning.go | 26 ++++-- .../planbuilder/operators/offset_planning.go | 2 +- .../planbuilder/operators/projection.go | 8 +- go/vt/vtgate/planbuilder/operators/union.go | 2 +- .../planbuilder/testdata/union_cases.json | 81 ++++++------------- 7 files changed, 74 insertions(+), 96 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/distinct.go b/go/vt/vtgate/planbuilder/operators/distinct.go index b03047d8d7b..c3f08642139 100644 --- a/go/vt/vtgate/planbuilder/operators/distinct.go +++ b/go/vt/vtgate/planbuilder/operators/distinct.go @@ -22,20 +22,24 @@ import ( "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/engine" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" - "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/rewrite" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" ) type ( Distinct struct { - // When splitting a distinct up, we only need one total DISTINCT at the route, any other - // intermediate DISTINCTs while we are pushing down can simply be removed - Original bool - Source ops.Operator - QP *QueryProjection - Pushed bool - - // When offset planning, we'll fill in this field + Source ops.Operator + QP *QueryProjection + + // When we go from AST to operator, we place DISTINCT ops in the required places in the op tree + // These are marked as `Required`, because they are semantically important to the results of the query. + // During planning, when we can't push down the DISTINCT op any further, we sometimes create and push down + // additional DISTINCT ops that are not strictly required, but that limit the number of incoming rows so less + // work has to be done. When we have pushed down these performance DISTINCTs, we set the `PushedPerformance` + // field to true on the originating op + Required bool + PushedPerformance bool + + // This is only filled in during offset planning Columns []engine.CheckCol Truncate int @@ -80,12 +84,12 @@ func (d *Distinct) planOffsets(ctx *plancontext.PlanningContext) error { func (d *Distinct) Clone(inputs []ops.Operator) ops.Operator { return &Distinct{ - Original: d.Original, - Source: inputs[0], - Columns: slices.Clone(d.Columns), - QP: d.QP, - Pushed: d.Pushed, - Truncate: d.Truncate, + Required: d.Required, + Source: inputs[0], + Columns: slices.Clone(d.Columns), + QP: d.QP, + PushedPerformance: d.PushedPerformance, + Truncate: d.Truncate, } } @@ -128,10 +132,10 @@ func (d *Distinct) GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.S } func (d *Distinct) ShortDescription() string { - if d.Original { - return "ORG" + if d.Required { + return "Required" } - return "" + return "Performance" } func (d *Distinct) GetOrdering() ([]ops.OrderBy, error) { @@ -141,12 +145,3 @@ func (d *Distinct) GetOrdering() ([]ops.OrderBy, error) { func (d *Distinct) setTruncateColumnCount(offset int) { d.Truncate = offset } - -func (d *Distinct) Compact(*plancontext.PlanningContext) (ops.Operator, *rewrite.ApplyResult, error) { - other, ok := d.Source.(*Distinct) - if !ok { - return d, rewrite.SameTree, nil - } - d.Source = other.Source - return d, rewrite.NewTree("removed double distinct", other), nil -} diff --git a/go/vt/vtgate/planbuilder/operators/horizon_expanding.go b/go/vt/vtgate/planbuilder/operators/horizon_expanding.go index e6bef2aa5fe..5a7ae961862 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_expanding.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_expanding.go @@ -88,7 +88,7 @@ func expandSelectHorizon(ctx *plancontext.PlanningContext, horizon *Horizon, sel if qp.NeedsDistinct() { op = &Distinct{ - Original: true, + Required: true, Source: op, QP: qp, } diff --git a/go/vt/vtgate/planbuilder/operators/horizon_planning.go b/go/vt/vtgate/planbuilder/operators/horizon_planning.go index 8f7c7068271..d345d5d573f 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_planning.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_planning.go @@ -603,40 +603,50 @@ func pushFilterUnderProjection(ctx *plancontext.PlanningContext, filter *Filter, } func tryPushingDownDistinct(in *Distinct) (ops.Operator, *rewrite.ApplyResult, error) { - if in.Pushed { + if in.Required && in.PushedPerformance { return in, rewrite.SameTree, nil } - in.Pushed = true switch src := in.Source.(type) { case *Route: if isDistinct(src.Source) && src.IsSingleShard() { return src, rewrite.NewTree("distinct not needed", in), nil } - if src.IsSingleShard() || !in.Original { + if src.IsSingleShard() || !in.Required { return rewrite.Swap(in, src, "push distinct under route") } + if isDistinct(src.Source) { + return in, rewrite.SameTree, nil + } + src.Source = &Distinct{Source: src.Source} + in.PushedPerformance = true return in, rewrite.NewTree("added distinct under route - kept original", src), nil case *Distinct: + src.Required = false + src.PushedPerformance = false return src, rewrite.NewTree("removed double distinct", src), nil - case *Aggregator: - return in, rewrite.SameTree, nil case *Union: for i := range src.Sources { src.Sources[i] = &Distinct{Source: src.Sources[i]} } + in.PushedPerformance = true + return in, rewrite.NewTree("pushed down DISTINCT under UNION", src), nil case *ApplyJoin: src.LHS = &Distinct{Source: src.LHS} src.RHS = &Distinct{Source: src.RHS} + in.PushedPerformance = true - if in.Original { + if in.Required { return in, rewrite.NewTree("pushed distinct under join - kept original", in.Source), nil } return in.Source, rewrite.NewTree("pushed distinct under join", in.Source), nil + case *Ordering: + in.Source = src.Source + return in, rewrite.NewTree("removed ordering under distinct", in), nil } return in, rewrite.SameTree, nil @@ -650,6 +660,8 @@ func isDistinct(op ops.Operator) bool { return op.distinct case *Horizon: return op.Query.IsDistinct() + case *Limit: + return isDistinct(op.Source) default: return false } @@ -677,7 +689,7 @@ func tryPushDownUnion(ctx *plancontext.PlanningContext, op *Union) (ops.Operator return &Distinct{ Source: result, - Original: true, + Required: true, }, rewrite.NewTree("pushed union under route", op), nil } diff --git a/go/vt/vtgate/planbuilder/operators/offset_planning.go b/go/vt/vtgate/planbuilder/operators/offset_planning.go index 4e6fdba5eac..8fe08896b01 100644 --- a/go/vt/vtgate/planbuilder/operators/offset_planning.go +++ b/go/vt/vtgate/planbuilder/operators/offset_planning.go @@ -152,7 +152,7 @@ func pullDistinctFromUNION(root ops.Operator) (ops.Operator, error) { union.distinct = false distinct := &Distinct{ - Original: true, + Required: true, Source: union, } return distinct, rewrite.NewTree("pulled out DISTINCT from union", union), nil diff --git a/go/vt/vtgate/planbuilder/operators/projection.go b/go/vt/vtgate/planbuilder/operators/projection.go index 44c1b3b5722..1d3b9499f4a 100644 --- a/go/vt/vtgate/planbuilder/operators/projection.go +++ b/go/vt/vtgate/planbuilder/operators/projection.go @@ -139,20 +139,22 @@ func (p *Projection) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser return p, offset, nil } + ae := sqlparser.CloneRefOfAliasedExpr(expr) + if p.TableID != nil { vt, err := ctx.SemTable.TableInfoFor(*p.TableID) if err != nil { return nil, 0, err } - expr.Expr = semantics.RewriteDerivedTableExpression(expr.Expr, vt) + ae.Expr = semantics.RewriteDerivedTableExpression(expr.Expr, vt) } - sourceOp, offset, err := p.Source.AddColumn(ctx, expr, true, addToGroupBy) + sourceOp, offset, err := p.Source.AddColumn(ctx, ae, true, addToGroupBy) if err != nil { return nil, 0, err } p.Source = sourceOp - p.Projections = append(p.Projections, Offset{Offset: offset, Expr: expr.Expr}) + p.Projections = append(p.Projections, Offset{Offset: offset, Expr: ae.Expr}) p.Columns = append(p.Columns, expr) return p, len(p.Projections) - 1, nil } diff --git a/go/vt/vtgate/planbuilder/operators/union.go b/go/vt/vtgate/planbuilder/operators/union.go index 6ecd1130170..5241e3211ac 100644 --- a/go/vt/vtgate/planbuilder/operators/union.go +++ b/go/vt/vtgate/planbuilder/operators/union.go @@ -172,7 +172,7 @@ func (u *Union) Compact(*plancontext.PlanningContext) (ops.Operator, *rewrite.Ap // first we remove unnecessary DISTINCTs for idx, source := range u.Sources { d, ok := source.(*Distinct) - if !ok || !d.Original { + if !ok || !d.Required { continue } u.Sources[idx] = d.Source diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 13120cff973..4138a6d9ab8 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -42,8 +42,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select id from music where 1 != 1) as dt where 1 != 1", - "Query": "select id, weight_string(id) from (select id from `user` union select id from music) as dt", + "FieldQuery": "select id from (select id from `user` where 1 != 1 union select id from music where 1 != 1) as dt where 1 != 1", + "Query": "select id from (select id from `user` union select id from music) as dt", "Table": "`user`, music" } ] @@ -460,8 +460,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id, weight_string(id) from ((select id from `user` where 1 != 1) union (select id from `user` where 1 != 1)) as dt where 1 != 1", - "Query": "select id, weight_string(id) from ((select id from `user` order by id desc) union (select id from `user` order by id asc)) as dt", + "FieldQuery": "select id from ((select id from `user` where 1 != 1) union (select id from `user` where 1 != 1)) as dt where 1 != 1", + "Query": "select id from ((select id from `user` order by id desc) union (select id from `user` order by id asc)) as dt", "Table": "`user`" } ] @@ -771,42 +771,15 @@ "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Distinct", - "Collations": [ - "(0:2)", - "(1:3)" - ], - "Inputs": [ - { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|2) ASC", - "Inputs": [ - { - "OperatorType": "Distinct", - "Collations": [ - "(0:2)", - "(1:3)", - "(2:4)", - "(3:5)" - ], - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id), weight_string(id), weight_string(weight_string(id)), weight_string(weight_string(id)), weight_string(weight_string(weight_string(id))) from (select id from `user` where 1 != 1 union select id from music where 1 != 1) as dt where 1 != 1", - "Query": "select id, weight_string(id), weight_string(id), weight_string(weight_string(id)), weight_string(weight_string(id)), weight_string(weight_string(weight_string(id))) from (select id from `user` union select id from music) as dt", - "Table": "`user`, music" - } - ] - } - ] - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select id from music where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id) from (select id from `user` union select id from music) as dt", + "Table": "`user`, music" }, { "OperatorType": "Route", @@ -854,8 +827,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt where 1 != 1", - "Query": "select id, weight_string(id) from (select id from `user` union select 3 from dual limit :__upper_limit) as dt", + "FieldQuery": "select id from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt where 1 != 1", + "Query": "select id from (select id from `user` union select 3 from dual) as dt limit :__upper_limit", "Table": "`user`, dual" } ] @@ -1081,10 +1054,6 @@ "Inputs": [ { "OperatorType": "Distinct", - "Collations": [ - "(0:1)", - "(1:2)" - ], "Inputs": [ { "OperatorType": "Route", @@ -1093,8 +1062,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id, weight_string(id), weight_string(weight_string(id)) from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt where 1 != 1", - "Query": "select id, weight_string(id), weight_string(weight_string(id)) from (select id from `user` union select 3 from dual) as dt", + "FieldQuery": "select id from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt where 1 != 1", + "Query": "select id from (select id from `user` union select 3 from dual) as dt", "Table": "`user`, dual" } ] @@ -1353,8 +1322,8 @@ "OperatorType": "Distinct", "Collations": [ "(0:3)", - "(0:3)", - "(0:3)" + "(0:0)", + "(0:0)" ], "ResultColumns": 3, "Inputs": [ @@ -1365,8 +1334,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select foo, foo, foo, weight_string(foo) from (select foo, foo, foo from `user` where 1 != 1 union select bar, baz, toto from music where 1 != 1) as dt where 1 != 1", - "Query": "select foo, foo, foo, weight_string(foo) from (select foo, foo, foo from `user` union select bar, baz, toto from music) as dt", + "FieldQuery": "select weight_string(foo) from (select foo, foo, foo from `user` where 1 != 1 union select bar, baz, toto from music where 1 != 1) as dt where 1 != 1", + "Query": "select weight_string(foo) from (select foo, foo, foo from `user` union select bar, baz, toto from music) as dt", "Table": "`user`, music" } ] @@ -1387,8 +1356,8 @@ "OperatorType": "Distinct", "Collations": [ "(0:3)", - "(1:4)", - "(2:5)" + "(1:0)", + "(2:1)" ], "ResultColumns": 3, "Inputs": [ @@ -1399,8 +1368,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select bar, baz, toto, weight_string(bar), weight_string(baz), weight_string(toto) from (select bar, baz, toto from music where 1 != 1 union select foo, foo, foo from `user` where 1 != 1) as dt where 1 != 1", - "Query": "select bar, baz, toto, weight_string(bar), weight_string(baz), weight_string(toto) from (select bar, baz, toto from music union select foo, foo, foo from `user`) as dt", + "FieldQuery": "select weight_string(baz), weight_string(toto) from (select bar, baz, toto from music where 1 != 1 union select foo, foo, foo from `user` where 1 != 1) as dt where 1 != 1", + "Query": "select weight_string(baz), weight_string(toto) from (select bar, baz, toto from music union select foo, foo, foo from `user`) as dt", "Table": "`user`, music" } ] From e284b57de3a0c7961077c173e6535155c061f76a Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 21 Jul 2023 15:17:56 +0200 Subject: [PATCH 21/44] instead of failing, we can use a Filter op instead Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/operators/union.go | 35 ++++- .../planbuilder/testdata/union_cases.json | 138 +++++++++++++++++- 2 files changed, 164 insertions(+), 9 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/union.go b/go/vt/vtgate/planbuilder/operators/union.go index 5241e3211ac..c3525c5e952 100644 --- a/go/vt/vtgate/planbuilder/operators/union.go +++ b/go/vt/vtgate/planbuilder/operators/union.go @@ -111,6 +111,31 @@ func (u *Union) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Ex offsets[ae.ColumnName()] = i } + exprPerSource, err := u.predicatePerSource(expr, offsets) + if err == errUseFilter { + return &Filter{ + Source: u, + Predicates: []sqlparser.Expr{expr}, + }, nil + } + if err != nil { + return nil, err + } + + for i, src := range u.Sources { + u.Sources[i], err = src.AddPredicate(ctx, exprPerSource[i]) + if err != nil { + return nil, err + } + } + + return u, nil +} + +var errUseFilter = fmt.Errorf("use filter") + +func (u *Union) predicatePerSource(expr sqlparser.Expr, offsets map[string]int) ([]sqlparser.Expr, error) { + exprPerSource := make([]sqlparser.Expr, len(u.Sources)) for i := range u.Sources { var err error predicate := sqlparser.CopyOnRewrite(expr, nil, func(cursor *sqlparser.CopyOnWriteCursor) { @@ -121,7 +146,7 @@ func (u *Union) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Ex idx, ok := offsets[col.Name.Lowered()] if !ok { - err = vterrors.VT13001("cannot push predicates on concatenate, missing columns from the UNION") + err = errUseFilter cursor.StopTreeWalk() return } @@ -144,13 +169,9 @@ func (u *Union) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Ex if err != nil { return nil, err } - u.Sources[i], err = u.Sources[i].AddPredicate(ctx, predicate) - if err != nil { - return nil, err - } + exprPerSource[i] = predicate } - - return u, nil + return exprPerSource, nil } func (u *Union) GetSelectFor(source int) (*sqlparser.Select, error) { diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 4138a6d9ab8..6239693fde9 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -1140,7 +1140,63 @@ { "comment": "systable union query in derived table with constraint on outside (without star projection)", "query": "select * from (select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `COLUMN_NAME` = 'primary'", - "plan": "VT13001: [BUG] cannot push predicates on concatenate, missing columns from the UNION" + "plan": { + "QueryType": "SELECT", + "Original": "select * from (select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `COLUMN_NAME` = 'primary'", + "Instructions": { + "OperatorType": "SimpleProjection", + "Columns": [ + 0 + ], + "Inputs": [ + { + "OperatorType": "Filter", + "Predicate": "COLUMN_NAME = 'primary'", + "Inputs": [ + { + "OperatorType": "Distinct", + "Collations": [ + "0: utf8mb4_0900_ai_ci" + ], + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select kcu.COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", + "Query": "select distinct kcu.COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name /* VARCHAR */", + "SysTableTableName": "[kcu_table_name:VARCHAR(\"user_extra\")]", + "SysTableTableSchema": "[VARCHAR(\"user\")]", + "Table": "information_schema.key_column_usage" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select kcu.COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", + "Query": "select distinct kcu.COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name1 /* VARCHAR */", + "SysTableTableName": "[kcu_table_name1:VARCHAR(\"music\")]", + "SysTableTableSchema": "[VARCHAR(\"user\")]", + "Table": "information_schema.key_column_usage" + } + ] + } + ] + } + ] + } + ] + } + } }, { "comment": "pushes predicate on both sides of UNION", @@ -1172,7 +1228,85 @@ { "comment": "systable union query in derived table with constraint on outside (star projection)", "query": "select * from (select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `constraint_name` = 'primary'", - "plan": "VT13001: [BUG] cannot push predicates on concatenate, missing columns from the UNION" + "plan": { + "QueryType": "SELECT", + "Original": "select * from (select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `constraint_name` = 'primary'", + "Instructions": { + "OperatorType": "SimpleProjection", + "Columns": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11 + ], + "Inputs": [ + { + "OperatorType": "Filter", + "Predicate": "constraint_name = 'primary'", + "Inputs": [ + { + "OperatorType": "Distinct", + "Collations": [ + "0: utf8mb4_0900_ai_ci", + "1: utf8mb4_0900_ai_ci", + "2: utf8mb4_0900_ai_ci", + "3: utf8mb4_0900_ai_ci", + "4: utf8mb4_0900_ai_ci", + "5: utf8mb4_0900_ai_ci", + "6: utf8mb4_0900_ai_ci", + "7", + "8", + "9: utf8mb4_0900_ai_ci", + "10: utf8mb4_0900_ai_ci", + "11: utf8mb4_0900_ai_ci" + ], + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", + "Query": "select distinct kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name /* VARCHAR */", + "SysTableTableName": "[kcu_table_name:VARCHAR(\"user_extra\")]", + "SysTableTableSchema": "[VARCHAR(\"user\")]", + "Table": "information_schema.key_column_usage" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", + "Query": "select distinct kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name1 /* VARCHAR */", + "SysTableTableName": "[kcu_table_name1:VARCHAR(\"music\")]", + "SysTableTableSchema": "[VARCHAR(\"user\")]", + "Table": "information_schema.key_column_usage" + } + ] + } + ] + } + ] + } + ] + } + } }, { "comment": "unknown columns are OK as long as the whole query is unsharded", From e9eac9841852021076511d3176ac051bc4bac698 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Wed, 26 Jul 2023 12:45:46 +0200 Subject: [PATCH 22/44] move from AddColumn to AddColumns Signed-off-by: Andres Taylor --- .../operators/aggregation_pushing.go | 2 +- .../planbuilder/operators/aggregator.go | 148 +++++++++++------- .../planbuilder/operators/apply_join.go | 63 +++++--- .../vtgate/planbuilder/operators/distinct.go | 19 +-- go/vt/vtgate/planbuilder/operators/filter.go | 9 +- go/vt/vtgate/planbuilder/operators/horizon.go | 45 +++--- .../planbuilder/operators/horizon_planning.go | 10 +- .../operators/info_schema_planning.go | 1 - go/vt/vtgate/planbuilder/operators/limit.go | 10 +- .../planbuilder/operators/offset_planning.go | 5 +- .../vtgate/planbuilder/operators/operator.go | 4 + go/vt/vtgate/planbuilder/operators/ops/op.go | 4 +- .../vtgate/planbuilder/operators/ordering.go | 22 +-- .../planbuilder/operators/projection.go | 137 +++++++++++----- .../planbuilder/operators/queryprojection.go | 3 +- go/vt/vtgate/planbuilder/operators/route.go | 78 ++++----- .../planbuilder/operators/sharded_routing.go | 3 +- .../operators/subquery_planning.go | 24 ++- go/vt/vtgate/planbuilder/operators/table.go | 12 +- go/vt/vtgate/planbuilder/operators/union.go | 62 +++++++- go/vt/vtgate/planbuilder/operators/vindex.go | 32 +++- .../testdata/unsupported_cases.json | 2 +- 22 files changed, 421 insertions(+), 274 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/aggregation_pushing.go b/go/vt/vtgate/planbuilder/operators/aggregation_pushing.go index d724120423f..0d085f2e718 100644 --- a/go/vt/vtgate/planbuilder/operators/aggregation_pushing.go +++ b/go/vt/vtgate/planbuilder/operators/aggregation_pushing.go @@ -352,7 +352,7 @@ func pushDownAggregationThroughJoin(ctx *plancontext.PlanningContext, rootAggr * } join.LHS, join.RHS = lhs.pushed, rhs.pushed - join.ColumnsAST = joinColumns + join.JoinColumns = joinColumns if !rootAggr.Original { // we only keep the root aggregation, if this aggregator was created diff --git a/go/vt/vtgate/planbuilder/operators/aggregator.go b/go/vt/vtgate/planbuilder/operators/aggregator.go index c90c38b1da9..d7da30d4382 100644 --- a/go/vt/vtgate/planbuilder/operators/aggregator.go +++ b/go/vt/vtgate/planbuilder/operators/aggregator.go @@ -20,10 +20,9 @@ import ( "fmt" "strings" - "vitess.io/vitess/go/slice" - "golang.org/x/exp/slices" + "vitess.io/vitess/go/slice" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine/opcode" @@ -114,6 +113,13 @@ func (a *Aggregator) addColumnWithoutPushing(expr *sqlparser.AliasedExpr, addToG return offset } +func (a *Aggregator) addColumnsWithoutPushing(expr []*sqlparser.AliasedExpr, groupby []bool) (offsets []int) { + for i, ae := range expr { + offsets = append(offsets, a.addColumnWithoutPushing(ae, groupby[i])) + } + return +} + func (a *Aggregator) isDerived() bool { return a.TableID != nil } @@ -132,18 +138,79 @@ func (a *Aggregator) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Ex return -1, nil } -func (a *Aggregator) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, _, addToGroupBy bool) (ops.Operator, int, error) { +func (a *Aggregator) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addToGroupBy []bool, exprs []*sqlparser.AliasedExpr) ([]int, error) { + offsets := make([]int, len(exprs)) + + var groupBys []bool + var exprsNeeded []*sqlparser.AliasedExpr + var offsetExpected []int + + for i, expr := range exprs { + addToGroupBy := addToGroupBy[i] + + if reuse { + offset, err := a.findColInternal(ctx, expr, addToGroupBy) + if err != nil { + return nil, err + } + if offset >= 0 { + offsets[i] = offset + continue + } + } + + // If weight string function is received from above operator. Then check if we have a group on the expression used. + // If it is found, then continue to push it down but with addToGroupBy true so that is the added to group by sql down in the AddColumn. + // This also set the weight string column offset so that we would not need to add it later in aggregator operator planOffset. + if wsExpr, isWS := expr.Expr.(*sqlparser.WeightStringFuncExpr); isWS { + idx := slices.IndexFunc(a.Grouping, func(by GroupBy) bool { + return ctx.SemTable.EqualsExprWithDeps(wsExpr.Expr, by.SimplifiedExpr) + }) + if idx >= 0 { + a.Grouping[idx].WSOffset = len(a.Columns) + addToGroupBy = true + } + } + + if !addToGroupBy { + aggr := NewAggr(opcode.AggregateAnyValue, nil, expr, expr.As.String()) + aggr.ColOffset = len(a.Columns) + a.Aggregations = append(a.Aggregations, aggr) + } + + offsets[i] = len(a.Columns) + a.Columns = append(a.Columns, expr) + groupBys = append(groupBys, addToGroupBy) + exprsNeeded = append(exprsNeeded, expr) + offsetExpected = append(offsetExpected, offsets[i]) + } + + incomingOffsets, err := a.Source.AddColumns(ctx, false, groupBys, exprsNeeded) + if err != nil { + return nil, err + } + + for i, offset := range offsetExpected { + if offset != incomingOffsets[i] { + return nil, errFailedToPlan(exprsNeeded[i]) + } + } + + return offsets, nil +} + +func (a *Aggregator) findColInternal(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, addToGroupBy bool) (int, error) { offset, err := a.FindCol(ctx, expr.Expr) if err != nil { - return nil, 0, err + return 0, err } if offset >= 0 { - return a, offset, nil + return offset, err } if a.isDerived() { derivedTBL, err := ctx.SemTable.TableInfoFor(*a.TableID) if err != nil { - return nil, 0, err + return 0, err } expr.Expr = semantics.RewriteDerivedTableExpression(expr.Expr, derivedTBL) } @@ -152,57 +219,24 @@ func (a *Aggregator) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser // So, before pushing anything from above the aggregator offset planning needs to be completed. err = a.planOffsets(ctx) if err != nil { - return nil, 0, err + return 0, err } if offset, found := canReuseColumn(ctx, a.Columns, expr.Expr, extractExpr); found { - return a, offset, nil + return offset, nil } colName, isColName := expr.Expr.(*sqlparser.ColName) for i, col := range a.Columns { if isColName && colName.Name.EqualString(col.As.String()) { - return a, i, nil + return i, nil } } if addToGroupBy { - return nil, 0, vterrors.VT13001("did not expect to add group by here") - } - - // If weight string function is received from above operator. Then check if we have a group on the expression used. - // If it is found, then continue to push it down but with addToGroupBy true so that is the added to group by sql down in the AddColumn. - // This also set the weight string column offset so that we would not need to add it later in aggregator operator planOffset. - - // If the expression is a WeightStringFuncExpr, it checks if a GroupBy - // already exists on the argument of the expression. - // If it is found, the column offset for the WeightStringFuncExpr is set, - // and the column is marked to be added to the GroupBy in the recursive AddColumn call. - if wsExpr, isWS := expr.Expr.(*sqlparser.WeightStringFuncExpr); isWS { - idx := slices.IndexFunc(a.Grouping, func(by GroupBy) bool { - return ctx.SemTable.EqualsExprWithDeps(wsExpr.Expr, by.SimplifiedExpr) - }) - if idx >= 0 { - a.Grouping[idx].WSOffset = len(a.Columns) - addToGroupBy = true - } + return 0, vterrors.VT13001("did not expect to add group by here") } - if !addToGroupBy { - aggr := NewAggr(opcode.AggregateAnyValue, nil, expr, expr.As.String()) - aggr.ColOffset = len(a.Columns) - a.Aggregations = append(a.Aggregations, aggr) - } - a.Columns = append(a.Columns, expr) - expectedOffset := len(a.Columns) - 1 - newSrc, offset, err := a.Source.AddColumn(ctx, expr, false, addToGroupBy) - if err != nil { - return nil, 0, err - } - if offset != expectedOffset { - return nil, 0, vterrors.VT13001("the offset needs to be aligned here") - } - a.Source = newSrc - return a, offset, nil + return -1, nil } func (a *Aggregator) GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { @@ -350,40 +384,40 @@ func (a *Aggregator) addIfAggregationColumn(ctx *plancontext.PlanningContext, co } wrap := aeWrap(aggr.getPushDownColumn()) - newSrc, offset, err := a.Source.AddColumn(ctx, wrap, false, false) + offsets, err := a.Source.AddColumns(ctx, false, []bool{false}, []*sqlparser.AliasedExpr{wrap}) if err != nil { return 0, err } + offset := offsets[0] if aggr.ColOffset != offset { - if _, srcIsAlsoAggr := a.Source.(*Aggregator); srcIsAlsoAggr { - return 0, vterrors.VT12001("aggregation on top of aggregation not supported") - } - return -1, vterrors.VT12001(fmt.Sprintf("failed to plan aggregation on: %s", sqlparser.String(aggr.Original))) + return -1, errFailedToPlan(aggr.Original) } - a.Source = newSrc return offset, nil } return -1, nil } +func errFailedToPlan(original *sqlparser.AliasedExpr) *vterrors.VitessError { + return vterrors.VT12001(fmt.Sprintf("failed to plan aggregation on: %s", sqlparser.String(original))) +} + func (a *Aggregator) addIfGroupingColumn(ctx *plancontext.PlanningContext, colIdx int) (int, error) { for _, gb := range a.Grouping { if gb.ColOffset != colIdx { continue } - newSrc, offset, err := a.Source.AddColumn(ctx, a.Columns[colIdx], false, true) + expr := a.Columns[colIdx] + offsets, err := a.Source.AddColumns(ctx, false, []bool{true}, []*sqlparser.AliasedExpr{expr}) if err != nil { return -1, err } - + offset := offsets[0] if gb.ColOffset != offset { - return -1, vterrors.VT13001(fmt.Sprintf("grouping column on wrong index: want: %d, got: %d", colIdx, offset)) + return -1, errFailedToPlan(expr) } - a.Source = newSrc - return offset, nil } return -1, nil @@ -429,11 +463,11 @@ func (a *Aggregator) setTruncateColumnCount(offset int) { } func (a *Aggregator) internalAddColumn(ctx *plancontext.PlanningContext, aliasedExpr *sqlparser.AliasedExpr, addToGroupBy bool) (int, error) { - newSrc, offset, err := a.Source.AddColumn(ctx, aliasedExpr, true, addToGroupBy) + offsets, err := a.Source.AddColumns(ctx, true, []bool{addToGroupBy}, []*sqlparser.AliasedExpr{aliasedExpr}) if err != nil { return 0, err } - a.Source = newSrc + offset := offsets[0] if offset == len(a.Columns) { // if we get an offset at the end of our current column list, it means we added a new column a.Columns = append(a.Columns, aliasedExpr) diff --git a/go/vt/vtgate/planbuilder/operators/apply_join.go b/go/vt/vtgate/planbuilder/operators/apply_join.go index 31bcc32abe7..424cbaf450b 100644 --- a/go/vt/vtgate/planbuilder/operators/apply_join.go +++ b/go/vt/vtgate/planbuilder/operators/apply_join.go @@ -20,11 +20,10 @@ import ( "fmt" "strings" - "vitess.io/vitess/go/slice" - "golang.org/x/exp/maps" "golang.org/x/exp/slices" + "vitess.io/vitess/go/slice" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" @@ -46,8 +45,8 @@ type ApplyJoin struct { // Before offset planning Predicate sqlparser.Expr - // ColumnsAST keeps track of what AST expression is represented in the Columns array - ColumnsAST []JoinColumn + // JoinColumns keeps track of what AST expression is represented in the Columns array + JoinColumns []JoinColumn // JoinPredicates are join predicates that have been broken up into left hand side and right hand side parts. JoinPredicates []JoinColumn @@ -96,7 +95,7 @@ func (a *ApplyJoin) Clone(inputs []ops.Operator) ops.Operator { LHS: inputs[0], RHS: inputs[1], Columns: slices.Clone(a.Columns), - ColumnsAST: slices.Clone(a.ColumnsAST), + JoinColumns: slices.Clone(a.JoinColumns), JoinPredicates: slices.Clone(a.JoinPredicates), Vars: maps.Clone(a.Vars), LeftJoin: a.LeftJoin, @@ -163,25 +162,23 @@ func (a *ApplyJoin) AddJoinPredicate(ctx *plancontext.PlanningContext, expr sqlp } func (a *ApplyJoin) pushColLeft(ctx *plancontext.PlanningContext, e *sqlparser.AliasedExpr, addToGroupBy bool) (int, error) { - newLHS, offset, err := a.LHS.AddColumn(ctx, e, true, addToGroupBy) + offsets, err := a.LHS.AddColumns(ctx, true, []bool{addToGroupBy}, []*sqlparser.AliasedExpr{e}) if err != nil { return 0, err } - a.LHS = newLHS - return offset, nil + return offsets[0], nil } func (a *ApplyJoin) pushColRight(ctx *plancontext.PlanningContext, e *sqlparser.AliasedExpr, addToGroupBy bool) (int, error) { - newRHS, offset, err := a.RHS.AddColumn(ctx, e, true, addToGroupBy) + offsets, err := a.RHS.AddColumns(ctx, true, []bool{addToGroupBy}, []*sqlparser.AliasedExpr{e}) if err != nil { return 0, err } - a.RHS = newRHS - return offset, nil + return offsets[0], nil } func (a *ApplyJoin) GetColumns(*plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { - return slice.Map(a.ColumnsAST, joinColumnToAliasedExpr), nil + return slice.Map(a.JoinColumns, joinColumnToAliasedExpr), nil } func (a *ApplyJoin) GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.SelectExprs, error) { @@ -229,7 +226,7 @@ func (a *ApplyJoin) getJoinColumnFor(ctx *plancontext.PlanningContext, e *sqlpar } func (a *ApplyJoin) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { - offset, found := canReuseColumn(ctx, a.ColumnsAST, expr, joinColumnToExpr) + offset, found := canReuseColumn(ctx, a.JoinColumns, expr, joinColumnToExpr) if !found { return -1, nil } @@ -241,19 +238,49 @@ func (a *ApplyJoin) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser. return a, offset, err } - if offset, found := canReuseColumn(ctx, a.ColumnsAST, expr.Expr, joinColumnToExpr); found { + if offset, found := canReuseColumn(ctx, a.JoinColumns, expr.Expr, joinColumnToExpr); found { return a, offset, nil } col, err := a.getJoinColumnFor(ctx, expr, addToGroupBy) if err != nil { return nil, 0, err } - a.ColumnsAST = append(a.ColumnsAST, col) - return a, len(a.ColumnsAST) - 1, nil + a.JoinColumns = append(a.JoinColumns, col) + return a, len(a.JoinColumns) - 1, nil +} + +func (a *ApplyJoin) AddColumns( + ctx *plancontext.PlanningContext, + reuse bool, + addToGroupBy []bool, + exprs []*sqlparser.AliasedExpr, +) (offsets []int, err error) { + offsets = make([]int, len(exprs)) + for i, expr := range exprs { + if reuse { + offset, err := a.FindCol(ctx, expr.Expr) + if err != nil { + return nil, err + } + if offset != -1 { + offsets[i] = offset + continue + } + } + + col, err := a.getJoinColumnFor(ctx, expr, addToGroupBy[i]) + if err != nil { + return nil, err + } + + offsets[i] = len(a.JoinColumns) + a.JoinColumns = append(a.JoinColumns, col) + } + return } func (a *ApplyJoin) planOffsets(ctx *plancontext.PlanningContext) (err error) { - for _, col := range a.ColumnsAST { + for _, col := range a.JoinColumns { // Read the type description for JoinColumn to understand the following code for i, lhsExpr := range col.LHSExprs { offset, err := a.pushColLeft(ctx, aeWrap(lhsExpr), col.GroupBy) @@ -306,7 +333,7 @@ func (a *ApplyJoin) addOffset(offset int) { func (a *ApplyJoin) ShortDescription() string { pred := sqlparser.String(a.Predicate) - columns := slice.Map(a.ColumnsAST, func(from JoinColumn) string { + columns := slice.Map(a.JoinColumns, func(from JoinColumn) string { return sqlparser.String(from.Original) }) return fmt.Sprintf("on %s columns: %s", pred, strings.Join(columns, ", ")) diff --git a/go/vt/vtgate/planbuilder/operators/distinct.go b/go/vt/vtgate/planbuilder/operators/distinct.go index c3f08642139..e91ab370b84 100644 --- a/go/vt/vtgate/planbuilder/operators/distinct.go +++ b/go/vt/vtgate/planbuilder/operators/distinct.go @@ -54,16 +54,15 @@ func (d *Distinct) planOffsets(ctx *plancontext.PlanningContext) error { d.Columns = nil var exprs []sqlparser.Expr for _, col := range columns { - newSrc, offset, err := d.Source.AddColumn(ctx, col, true, false) + offsets, err := d.Source.AddColumns(ctx, true, []bool{false}, []*sqlparser.AliasedExpr{col}) if err != nil { return err } - d.Source = newSrc e := d.QP.GetSimplifiedExpr(col.Expr) exprs = append(exprs, e) typ, coll, _ := ctx.SemTable.TypeForExpr(e) d.Columns = append(d.Columns, engine.CheckCol{ - Col: offset, + Col: offsets[0], Type: typ, Collation: coll, }) @@ -72,12 +71,11 @@ func (d *Distinct) planOffsets(ctx *plancontext.PlanningContext) error { if !ctx.SemTable.NeedsWeightString(e) { continue } - newSrc, offset, err := d.Source.AddColumn(ctx, aeWrap(weightStringFor(e)), true, false) + offsets, err := d.Source.AddColumns(ctx, true, []bool{false}, []*sqlparser.AliasedExpr{aeWrap(weightStringFor(e))}) if err != nil { return err } - d.Source = newSrc - d.Columns[i].WsCol = &offset + d.Columns[i].WsCol = &offsets[0] } return nil } @@ -110,13 +108,8 @@ func (d *Distinct) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser return d, nil } -func (d *Distinct) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, reuseExisting, addToGroupBy bool) (ops.Operator, int, error) { - newSrc, offset, err := d.Source.AddColumn(ctx, expr, reuseExisting, addToGroupBy) - if err != nil { - return nil, 0, err - } - d.Source = newSrc - return d, offset, nil +func (d *Distinct) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addToGroupBy []bool, exprs []*sqlparser.AliasedExpr) ([]int, error) { + return d.Source.AddColumns(ctx, reuse, addToGroupBy, exprs) } func (d *Distinct) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { diff --git a/go/vt/vtgate/planbuilder/operators/filter.go b/go/vt/vtgate/planbuilder/operators/filter.go index 203e2ca2d79..2ffc3e1da32 100644 --- a/go/vt/vtgate/planbuilder/operators/filter.go +++ b/go/vt/vtgate/planbuilder/operators/filter.go @@ -87,13 +87,8 @@ func (f *Filter) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.E return f, nil } -func (f *Filter) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, reuseExisting, addToGroupBy bool) (ops.Operator, int, error) { - newSrc, offset, err := f.Source.AddColumn(ctx, expr, reuseExisting, addToGroupBy) - if err != nil { - return nil, 0, err - } - f.Source = newSrc - return f, offset, nil +func (f *Filter) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addToGroupBy []bool, exprs []*sqlparser.AliasedExpr) ([]int, error) { + return f.Source.AddColumns(ctx, reuse, addToGroupBy, exprs) } func (f *Filter) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { diff --git a/go/vt/vtgate/planbuilder/operators/horizon.go b/go/vt/vtgate/planbuilder/operators/horizon.go index af48df40991..a3c833f2b31 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon.go +++ b/go/vt/vtgate/planbuilder/operators/horizon.go @@ -149,37 +149,32 @@ func (h *Horizon) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser. return h, nil } -func (h *Horizon) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, _, addToGroupBy bool) (ops.Operator, int, error) { - col, ok := expr.Expr.(*sqlparser.ColName) - if !ok { - return nil, 0, vterrors.VT13001("cannot push non-colname expression to a derived table") +func (h *Horizon) AddColumns(ctx *plancontext.PlanningContext, reuse bool, _ []bool, exprs []*sqlparser.AliasedExpr) ([]int, error) { + if !reuse { + return nil, errNoNewColumns } - - identity := func(c *sqlparser.ColName) sqlparser.Expr { return c } - if offset, found := canReuseColumn(ctx, h.Columns, col, identity); found { - return h, offset, nil - } - - i, err := h.findOutputColumn(col) - if err != nil { - return nil, 0, err - } - var pos int - h.ColumnsOffset, pos = addToIntSlice(h.ColumnsOffset, i) - - h.Columns = append(h.Columns, col) - // add it to the source if we were not already passing it through - if i <= -1 { - // TODO: this does not look correct - newSrc, _, err := h.Source.AddColumn(ctx, aeWrap(sqlparser.NewColName(col.Name.String())), true, addToGroupBy) + offsets := make([]int, len(exprs)) + for i, expr := range exprs { + col, ok := expr.Expr.(*sqlparser.ColName) + if !ok { + return nil, vterrors.VT13001("cannot push non-ColName expression to horizon") + } + offset, err := h.FindCol(ctx, col) if err != nil { - return nil, 0, err + return nil, err + } + + if offset < 0 { + return nil, errNoNewColumns } - h.Source = newSrc + offsets[i] = offset } - return h, pos, nil + + return offsets, nil } +var errNoNewColumns = vterrors.VT13001("can't add new columns to Horizon") + // canReuseColumn is generic, so it can be used with slices of different types. // We don't care about the actual type, as long as we know it's a sqlparser.Expr func canReuseColumn[T any]( diff --git a/go/vt/vtgate/planbuilder/operators/horizon_planning.go b/go/vt/vtgate/planbuilder/operators/horizon_planning.go index d345d5d573f..494c17f7e67 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_planning.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_planning.go @@ -223,7 +223,7 @@ func pushDownProjectionInVindex( ) (ops.Operator, *rewrite.ApplyResult, error) { for _, column := range p.Projections { expr := column.GetExpr() - _, _, err := src.AddColumn(ctx, aeWrap(expr), true, false) + _, err := src.AddColumns(ctx, true, []bool{false}, []*sqlparser.AliasedExpr{aeWrap(expr)}) if err != nil { return nil, nil, err } @@ -251,7 +251,7 @@ func pushDownProjectionInApplyJoin( } lhs, rhs := &projector{}, &projector{} - src.ColumnsAST = nil + src.JoinColumns = nil for idx := 0; idx < len(p.Projections); idx++ { err := splitProjectionAcrossJoin(ctx, src, lhs, rhs, p.Projections[idx], p.Columns[idx]) if err != nil { @@ -294,7 +294,7 @@ func splitProjectionAcrossJoin( expr := in.GetExpr() // Check if the current expression can reuse an existing column in the ApplyJoin. - if _, found := canReuseColumn(ctx, join.ColumnsAST, expr, joinColumnToExpr); found { + if _, found := canReuseColumn(ctx, join.JoinColumns, expr, joinColumnToExpr); found { return nil } @@ -317,8 +317,8 @@ func splitProjectionAcrossJoin( rhs.add(&UnexploredExpression{E: col.RHSExpr}, &sqlparser.AliasedExpr{Expr: col.RHSExpr, As: colName.As}) } - // Add the new JoinColumn to the ApplyJoin's ColumnsAST. - join.ColumnsAST = append(join.ColumnsAST, col) + // Add the new JoinColumn to the ApplyJoin's JoinColumns. + join.JoinColumns = append(join.JoinColumns, col) return nil } diff --git a/go/vt/vtgate/planbuilder/operators/info_schema_planning.go b/go/vt/vtgate/planbuilder/operators/info_schema_planning.go index 20b3d29e427..a1c6df441a1 100644 --- a/go/vt/vtgate/planbuilder/operators/info_schema_planning.go +++ b/go/vt/vtgate/planbuilder/operators/info_schema_planning.go @@ -23,7 +23,6 @@ import ( "golang.org/x/exp/slices" "vitess.io/vitess/go/mysql/collations" - "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/servenv" "vitess.io/vitess/go/vt/sqlparser" diff --git a/go/vt/vtgate/planbuilder/operators/limit.go b/go/vt/vtgate/planbuilder/operators/limit.go index 5b219c2a4e3..844cd7135a5 100644 --- a/go/vt/vtgate/planbuilder/operators/limit.go +++ b/go/vt/vtgate/planbuilder/operators/limit.go @@ -56,14 +56,10 @@ func (l *Limit) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Ex return l, nil } -func (l *Limit) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, reuseExisting, addToGroupBy bool) (ops.Operator, int, error) { - newSrc, offset, err := l.Source.AddColumn(ctx, expr, reuseExisting, addToGroupBy) - if err != nil { - return nil, 0, err - } - l.Source = newSrc - return l, offset, nil +func (l *Limit) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addToGroupBy []bool, exprs []*sqlparser.AliasedExpr) ([]int, error) { + return l.Source.AddColumns(ctx, reuse, addToGroupBy, exprs) } + func (l *Limit) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { return l.Source.FindCol(ctx, expr) } diff --git a/go/vt/vtgate/planbuilder/operators/offset_planning.go b/go/vt/vtgate/planbuilder/operators/offset_planning.go index 8fe08896b01..e39e1e8d36a 100644 --- a/go/vt/vtgate/planbuilder/operators/offset_planning.go +++ b/go/vt/vtgate/planbuilder/operators/offset_planning.go @@ -79,12 +79,11 @@ func useOffsets(ctx *plancontext.PlanningContext, expr sqlparser.Expr, op ops.Op notFound := func(e sqlparser.Expr) error { _, addToGroupBy := e.(*sqlparser.ColName) - newSrc, offset, err := in.AddColumn(ctx, aeWrap(e), true, addToGroupBy) + offsets, err := in.AddColumns(ctx, true, []bool{addToGroupBy}, []*sqlparser.AliasedExpr{aeWrap(e)}) if err != nil { return err } - op.SetInputs([]ops.Operator{newSrc}) - exprOffset = sqlparser.NewOffset(offset, e) + exprOffset = sqlparser.NewOffset(offsets[0], e) return nil } diff --git a/go/vt/vtgate/planbuilder/operators/operator.go b/go/vt/vtgate/planbuilder/operators/operator.go index 9d2033d483a..bcbfb76996e 100644 --- a/go/vt/vtgate/planbuilder/operators/operator.go +++ b/go/vt/vtgate/planbuilder/operators/operator.go @@ -109,6 +109,10 @@ func (noColumns) AddColumn(*plancontext.PlanningContext, *sqlparser.AliasedExpr, return nil, 0, vterrors.VT13001("noColumns operators have no column") } +func (noColumns) AddColumns(*plancontext.PlanningContext, bool, []bool, []*sqlparser.AliasedExpr) ([]int, error) { + return nil, vterrors.VT13001("noColumns operators have no column") +} + func (noColumns) GetColumns(*plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { return nil, vterrors.VT13001("noColumns operators have no column") } diff --git a/go/vt/vtgate/planbuilder/operators/ops/op.go b/go/vt/vtgate/planbuilder/operators/ops/op.go index b031403133c..4ca3c74ee08 100644 --- a/go/vt/vtgate/planbuilder/operators/ops/op.go +++ b/go/vt/vtgate/planbuilder/operators/ops/op.go @@ -44,9 +44,7 @@ type ( // TODO: we should remove this and replace it with rewriters AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (Operator, error) - // AddColumn tells an operator to also output an additional column specified. - // The offset to the column is returned. - AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, reuseExisting, addToGroupBy bool) (Operator, int, error) + AddColumns(ctx *plancontext.PlanningContext, reuseExisting bool, addToGroupBy []bool, exprs []*sqlparser.AliasedExpr) ([]int, error) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) diff --git a/go/vt/vtgate/planbuilder/operators/ordering.go b/go/vt/vtgate/planbuilder/operators/ordering.go index ca895f4bb2c..a1b074301d2 100644 --- a/go/vt/vtgate/planbuilder/operators/ordering.go +++ b/go/vt/vtgate/planbuilder/operators/ordering.go @@ -19,10 +19,9 @@ package operators import ( "strings" - "vitess.io/vitess/go/slice" - "golang.org/x/exp/slices" + "vitess.io/vitess/go/slice" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" @@ -64,13 +63,8 @@ func (o *Ordering) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser return o, nil } -func (o *Ordering) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, reuseExisting, addToGroupBy bool) (ops.Operator, int, error) { - newSrc, offset, err := o.Source.AddColumn(ctx, expr, reuseExisting, addToGroupBy) - if err != nil { - return nil, 0, err - } - o.Source = newSrc - return o, offset, nil +func (o *Ordering) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addToGroupBy []bool, exprs []*sqlparser.AliasedExpr) ([]int, error) { + return o.Source.AddColumns(ctx, reuse, addToGroupBy, exprs) } func (o *Ordering) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { @@ -91,12 +85,11 @@ func (o *Ordering) GetOrdering() ([]ops.OrderBy, error) { func (o *Ordering) planOffsets(ctx *plancontext.PlanningContext) error { for _, order := range o.Order { - newSrc, offset, err := o.Source.AddColumn(ctx, aeWrap(order.SimplifiedExpr), true, false) + offsets, err := o.Source.AddColumns(ctx, true, []bool{false}, []*sqlparser.AliasedExpr{aeWrap(order.SimplifiedExpr)}) if err != nil { return err } - o.Source = newSrc - o.Offset = append(o.Offset, offset) + o.Offset = append(o.Offset, offsets[0]) if !ctx.SemTable.NeedsWeightString(order.SimplifiedExpr) { o.WOffset = append(o.WOffset, -1) @@ -104,12 +97,11 @@ func (o *Ordering) planOffsets(ctx *plancontext.PlanningContext) error { } wsExpr := &sqlparser.WeightStringFuncExpr{Expr: order.SimplifiedExpr} - newSrc, offset, err = o.Source.AddColumn(ctx, aeWrap(wsExpr), true, false) + offsets, err = o.Source.AddColumns(ctx, true, []bool{false}, []*sqlparser.AliasedExpr{aeWrap(wsExpr)}) if err != nil { return err } - o.Source = newSrc - o.WOffset = append(o.WOffset, offset) + o.WOffset = append(o.WOffset, offsets[0]) } return nil diff --git a/go/vt/vtgate/planbuilder/operators/projection.go b/go/vt/vtgate/planbuilder/operators/projection.go index 1d3b9499f4a..9734ac7913b 100644 --- a/go/vt/vtgate/planbuilder/operators/projection.go +++ b/go/vt/vtgate/planbuilder/operators/projection.go @@ -22,6 +22,7 @@ import ( "golang.org/x/exp/slices" + "vitess.io/vitess/go/slice" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/evalengine" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" @@ -36,6 +37,7 @@ type ( Projection struct { Source ops.Operator + // TODO: we should replace these two slices with a single slice that contains both items. Keeping these two slices in sync leads to fragile code (systay 2023-07-25) // Columns contain the expressions as viewed from the outside of this operator Columns []*sqlparser.AliasedExpr @@ -85,17 +87,21 @@ func createSimpleProjection(ctx *plancontext.PlanningContext, qp *QueryProjectio Source: src, } - for _, e := range qp.SelectExprs { - ae, err := e.GetAliasedExpr() - if err != nil { - return nil, err - } - newSrc, offset, err := p.Source.AddColumn(ctx, ae, true, false) - if err != nil { - return nil, err - } + var groupby []bool + exprs, err := slice.MapWithError(qp.SelectExprs, func(from SelectExpr) (*sqlparser.AliasedExpr, error) { + groupby = append(groupby, false) + return from.GetAliasedExpr() + }) + if err != nil { + return nil, err + } - p.Source = newSrc + offsets, err := p.Source.AddColumns(ctx, true, groupby, exprs) + if err != nil { + return nil, err + } + for i := range exprs { + offset, ae := offsets[i], exprs[i] p.Projections = append(p.Projections, Offset{Expr: ae.Expr, Offset: offset}) p.Columns = append(p.Columns, ae) } @@ -112,17 +118,19 @@ func (p *Projection) addColumnWithoutPushing(expr *sqlparser.AliasedExpr, _ bool return p.addUnexploredExpr(expr, expr.Expr) } +func (p *Projection) addColumnsWithoutPushing(expr []*sqlparser.AliasedExpr, _ []bool) []int { + return slice.Map(expr, func(ae *sqlparser.AliasedExpr) int { + return p.addUnexploredExpr(ae, ae.Expr) + }) +} + func (p *Projection) isDerived() bool { return p.TableID != nil } func (p *Projection) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { if p.isDerived() { - derivedTBL, err := ctx.SemTable.TableInfoFor(*p.TableID) - if err != nil { - return 0, err - } - expr = semantics.RewriteDerivedTableExpression(expr, derivedTBL) + return -1, nil } if offset, found := canReuseColumn(ctx, p.Columns, expr, extractExpr); found { return offset, nil @@ -130,33 +138,84 @@ func (p *Projection) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Ex return -1, nil } -func (p *Projection) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, _, addToGroupBy bool) (ops.Operator, int, error) { - offset, err := p.FindCol(ctx, expr.Expr) - if err != nil { - return nil, 0, err - } - if offset >= 0 { - return p, offset, nil - } +// fetchExpr is used to accumulate all expressions we'll need from the input, +// and store in which column on the projection we want to store the offset returned +type fetchExpr struct { + expr sqlparser.Expr + colIdx []int + groupBy bool +} - ae := sqlparser.CloneRefOfAliasedExpr(expr) +func (p *Projection) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addToGroupBy []bool, exprs []*sqlparser.AliasedExpr) ([]int, error) { + offsets := make([]int, len(exprs)) + var fetch []fetchExpr + startOffset := len(p.Columns) + for i, ae := range exprs { + colIdx := i + startOffset + expr := ae.Expr + + if reuse { + offset, err := p.FindCol(ctx, expr) + if err != nil { + return nil, err + } + if offset >= 0 { + offsets[i] = offset + continue + } + } - if p.TableID != nil { - vt, err := ctx.SemTable.TableInfoFor(*p.TableID) - if err != nil { - return nil, 0, err + if p.TableID != nil { + vt, err := ctx.SemTable.TableInfoFor(*p.TableID) + if err != nil { + return nil, err + } + expr = semantics.RewriteDerivedTableExpression(expr, vt) + } + + // we add the column here, so we can find the expression in the next iteration of this loop, + // but we wait with the actual projection until we have fetched it from the input + offsets[i] = len(p.Columns) + p.Columns = append(p.Columns, aeWrap(expr)) + p.Projections = append(p.Projections, nil) + + // even if the receiver of the Projection output does not want to reuse column, + // we can reuse columns from this input + fIdx := slices.IndexFunc(fetch, func(f fetchExpr) bool { + return ctx.SemTable.EqualsExprWithDeps(expr, f.expr) + }) + + if fIdx == -1 { + // if we are not already asking for this expression, we add it to the list of expressions we'll ask for + fIdx = len(fetch) + fetch = append(fetch, fetchExpr{ + expr: expr, + }) } - ae.Expr = semantics.RewriteDerivedTableExpression(expr.Expr, vt) + + fetch[fIdx].colIdx = append(fetch[fIdx].colIdx, colIdx) + fetch[fIdx].groupBy = fetch[fIdx].groupBy || addToGroupBy[i] } - sourceOp, offset, err := p.Source.AddColumn(ctx, ae, true, addToGroupBy) + askForExprs := make([]*sqlparser.AliasedExpr, len(fetch)) + askForGB := make([]bool, len(fetch)) + for i, f := range fetch { + askForExprs[i] = aeWrap(f.expr) + askForGB[i] = f.groupBy + } + + inputOffsets, err := p.Source.AddColumns(ctx, true, askForGB, askForExprs) if err != nil { - return nil, 0, err + return nil, err } - p.Source = sourceOp - p.Projections = append(p.Projections, Offset{Offset: offset, Expr: ae.Expr}) - p.Columns = append(p.Columns, expr) - return p, len(p.Projections) - 1, nil + + for fIdx, fetched := range fetch { + for _, colIdx := range fetched.colIdx { + p.Projections[colIdx] = Offset{Offset: inputOffsets[fIdx], Expr: fetched.expr} + } + } + + return offsets, nil } func (po Offset) GetExpr() sqlparser.Expr { return po.Expr } @@ -254,13 +313,13 @@ func (p *Projection) compactWithJoin(ctx *plancontext.PlanningContext, src *Appl switch col := col.(type) { case Offset: newColumns = append(newColumns, src.Columns[col.Offset]) - newColumnsAST = append(newColumnsAST, src.ColumnsAST[col.Offset]) + newColumnsAST = append(newColumnsAST, src.JoinColumns[col.Offset]) case UnexploredExpression: if !ctx.SemTable.EqualsExprWithDeps(col.E, p.Columns[idx].Expr) { // the inner expression is different from what we are presenting to the outside - this means we need to evaluate return p, rewrite.SameTree, nil } - offset := slices.IndexFunc(src.ColumnsAST, func(jc JoinColumn) bool { + offset := slices.IndexFunc(src.JoinColumns, func(jc JoinColumn) bool { return ctx.SemTable.EqualsExprWithDeps(jc.Original.Expr, col.E) }) if offset < 0 { @@ -269,13 +328,13 @@ func (p *Projection) compactWithJoin(ctx *plancontext.PlanningContext, src *Appl if len(src.Columns) > 0 { newColumns = append(newColumns, src.Columns[offset]) } - newColumnsAST = append(newColumnsAST, src.ColumnsAST[offset]) + newColumnsAST = append(newColumnsAST, src.JoinColumns[offset]) default: return p, rewrite.SameTree, nil } } src.Columns = newColumns - src.ColumnsAST = newColumnsAST + src.JoinColumns = newColumnsAST return src, rewrite.NewTree("remove projection from before join", src), nil } diff --git a/go/vt/vtgate/planbuilder/operators/queryprojection.go b/go/vt/vtgate/planbuilder/operators/queryprojection.go index a5d83057453..4244fbe2402 100644 --- a/go/vt/vtgate/planbuilder/operators/queryprojection.go +++ b/go/vt/vtgate/planbuilder/operators/queryprojection.go @@ -24,9 +24,8 @@ import ( "golang.org/x/exp/slices" - "vitess.io/vitess/go/sqltypes" - "vitess.io/vitess/go/mysql/collations" + "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine/opcode" diff --git a/go/vt/vtgate/planbuilder/operators/route.go b/go/vt/vtgate/planbuilder/operators/route.go index a13baf1e74a..e8ff537e22b 100644 --- a/go/vt/vtgate/planbuilder/operators/route.go +++ b/go/vt/vtgate/planbuilder/operators/route.go @@ -543,70 +543,74 @@ func createProjection(ctx *plancontext.PlanningContext, src ops.Operator) (*Proj return proj, nil } -func (r *Route) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, reuseExisting, addToGroupBy bool) (ops.Operator, int, error) { - removeKeyspaceFromSelectExpr(expr) - - if reuseExisting { - // check if columns is already added. - cols, err := r.GetColumns(ctx) - if err != nil { - return nil, 0, err - } - colAsExpr := func(e *sqlparser.AliasedExpr) sqlparser.Expr { - return e.Expr - } - if offset, found := canReuseColumn(ctx, cols, expr.Expr, colAsExpr); found { - return r, offset, nil +func (r *Route) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addToGroupBy []bool, exprs []*sqlparser.AliasedExpr) ([]int, error) { + offsets := make([]int, len(exprs)) + notFound := false + for idx, expr := range exprs { + removeKeyspaceFromSelectExpr(expr) + + if reuse { + offset, err := r.FindCol(ctx, expr.Expr) + if err != nil { + return nil, err + } + if offset != -1 { + offsets[idx] = offset + continue + } } + notFound = true + } + + if !notFound { + // we were able to find all columns, so we don't need to fetch anything else + return offsets, nil } - // if column is not already present, we check if we can easily find a projection + + // if at least one column is not already present, we check if we can easily find a projection // or aggregation in our source that we can add to - if op, ok, offset := addColumnToInput(ctx, r.Source, expr, addToGroupBy); ok { + if op, ok, offset := addMultipleColumnsToInput(ctx, r.Source, reuse, addToGroupBy, exprs); ok { r.Source = op - return r, offset, nil + return offset, nil } // If no-one could be found, we probably don't have one yet, so we add one here src, err := createProjection(ctx, r.Source) if err != nil { - return nil, 0, err + return nil, err } r.Source = src - // And since we are under the route, we don't need to continue pushing anything further down - offset := src.addColumnWithoutPushing(expr, false) - if err != nil { - return nil, 0, err - } - return r, offset, nil + return src.addColumnsWithoutPushing(exprs, addToGroupBy), nil } type selectExpressions interface { ops.Operator addColumnWithoutPushing(expr *sqlparser.AliasedExpr, addToGroupBy bool) int + addColumnsWithoutPushing(expr []*sqlparser.AliasedExpr, addToGroupBy []bool) []int isDerived() bool } // addColumnToInput adds a column to an operator without pushing it down. // It will return a bool indicating whether the addition was succesful or not, and an offset to where the column can be found -func addColumnToInput(ctx *plancontext.PlanningContext, operator ops.Operator, expr *sqlparser.AliasedExpr, addToGroupBy bool) (ops.Operator, bool, int) { +func addMultipleColumnsToInput(ctx *plancontext.PlanningContext, operator ops.Operator, reuse bool, addToGroupBy []bool, expr []*sqlparser.AliasedExpr) (ops.Operator, bool, []int) { switch op := operator.(type) { case *CorrelatedSubQueryOp: - src, added, offset := addColumnToInput(ctx, op.Outer, expr, addToGroupBy) + src, added, offset := addMultipleColumnsToInput(ctx, op.Outer, reuse, addToGroupBy, expr) if added { op.Outer = src } return op, added, offset case *Limit: - src, added, offset := addColumnToInput(ctx, op.Source, expr, addToGroupBy) + src, added, offset := addMultipleColumnsToInput(ctx, op.Source, reuse, addToGroupBy, expr) if added { op.Source = src } return op, added, offset case *Ordering: - src, added, offset := addColumnToInput(ctx, op.Source, expr, addToGroupBy) + src, added, offset := addMultipleColumnsToInput(ctx, op.Source, reuse, addToGroupBy, expr) if added { op.Source = src } @@ -616,16 +620,16 @@ func addColumnToInput(ctx *plancontext.PlanningContext, operator ops.Operator, e if op.isDerived() { // if the only thing we can push to is a derived table, // we have to add a new projection and can't build on this one - return op, false, 0 + return op, false, nil } - offset := op.addColumnWithoutPushing(expr, addToGroupBy) + offset := op.addColumnsWithoutPushing(expr, addToGroupBy) return op, true, offset case *Union: tableID := semantics.SingleTableSet(len(ctx.SemTable.Tables)) ctx.SemTable.Tables = append(ctx.SemTable.Tables, nil) unionColumns, err := op.GetColumns(ctx) if err != nil { - return nil, false, 0 + return nil, false, nil } return &Projection{ Source: op, @@ -633,9 +637,9 @@ func addColumnToInput(ctx *plancontext.PlanningContext, operator ops.Operator, e Projections: nil, TableID: &tableID, Alias: "dt", - }, true, len(op.unionColumns) + }, true, []int{len(op.unionColumns)} default: - return op, false, 0 + return op, false, nil } } @@ -712,11 +716,11 @@ func (r *Route) planOffsets(ctx *plancontext.PlanningContext) (err error) { } if ctx.SemTable.NeedsWeightString(order.SimplifiedExpr) { wrap := aeWrap(weightStringFor(order.SimplifiedExpr)) - _, offset, err = r.AddColumn(ctx, wrap, true, false) + offsets, err := r.AddColumns(ctx, true, []bool{false}, []*sqlparser.AliasedExpr{wrap}) if err != nil { return err } - o.WOffset = offset + o.WOffset = offsets[0] } r.Ordering = append(r.Ordering, o) } @@ -735,11 +739,11 @@ func (r *Route) getOffsetFor(ctx *plancontext.PlanningContext, order ops.OrderBy } } - _, offset, err := r.AddColumn(ctx, aeWrap(order.Inner.Expr), true, false) + offsets, err := r.AddColumns(ctx, true, []bool{false}, []*sqlparser.AliasedExpr{aeWrap(order.Inner.Expr)}) if err != nil { return 0, err } - return offset, nil + return offsets[0], nil } func (r *Route) ShortDescription() string { diff --git a/go/vt/vtgate/planbuilder/operators/sharded_routing.go b/go/vt/vtgate/planbuilder/operators/sharded_routing.go index 0a082c8460a..eb55c34b9bd 100644 --- a/go/vt/vtgate/planbuilder/operators/sharded_routing.go +++ b/go/vt/vtgate/planbuilder/operators/sharded_routing.go @@ -19,9 +19,8 @@ package operators import ( "golang.org/x/exp/slices" - "vitess.io/vitess/go/slice" - "vitess.io/vitess/go/mysql/collations" + "vitess.io/vitess/go/slice" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" diff --git a/go/vt/vtgate/planbuilder/operators/subquery_planning.go b/go/vt/vtgate/planbuilder/operators/subquery_planning.go index 86c7e29efb8..61f71024626 100644 --- a/go/vt/vtgate/planbuilder/operators/subquery_planning.go +++ b/go/vt/vtgate/planbuilder/operators/subquery_planning.go @@ -278,7 +278,6 @@ func rewriteColumnsInSubqueryOpForJoin( outerTree *ApplyJoin, subQueryInner *SubQueryInner, ) (ops.Operator, error) { - resultInnerOp := innerOp var rewriteError error // go over the entire expression in the subquery sqlparser.SafeRewrite(subQueryInner.ExtractedSubquery.Original, nil, func(cursor *sqlparser.Cursor) bool { @@ -288,7 +287,7 @@ func rewriteColumnsInSubqueryOpForJoin( } // check whether the column name belongs to the other side of the join tree - if !ctx.SemTable.RecursiveDeps(node).IsSolvedBy(TableID(resultInnerOp)) { + if !ctx.SemTable.RecursiveDeps(node).IsSolvedBy(TableID(innerOp)) { return true } @@ -304,24 +303,23 @@ func rewriteColumnsInSubqueryOpForJoin( return true } // if it does not exist, then push this as an output column there and add it to the joinVars - newInnerOp, offset, err := resultInnerOp.AddColumn(ctx, aeWrap(node), true, false) + offsets, err := innerOp.AddColumns(ctx, true, []bool{false}, []*sqlparser.AliasedExpr{aeWrap(node)}) if err != nil { rewriteError = err return false } - resultInnerOp = newInnerOp - outerTree.Vars[bindVar] = offset + outerTree.Vars[bindVar] = offsets[0] return true }) // update the dependencies for the subquery by removing the dependencies from the innerOp tableSet := ctx.SemTable.Direct[subQueryInner.ExtractedSubquery.Subquery] - ctx.SemTable.Direct[subQueryInner.ExtractedSubquery.Subquery] = tableSet.Remove(TableID(resultInnerOp)) + ctx.SemTable.Direct[subQueryInner.ExtractedSubquery.Subquery] = tableSet.Remove(TableID(innerOp)) tableSet = ctx.SemTable.Recursive[subQueryInner.ExtractedSubquery.Subquery] - ctx.SemTable.Recursive[subQueryInner.ExtractedSubquery.Subquery] = tableSet.Remove(TableID(resultInnerOp)) + ctx.SemTable.Recursive[subQueryInner.ExtractedSubquery.Subquery] = tableSet.Remove(TableID(innerOp)) // return any error while rewriting - return resultInnerOp, rewriteError + return innerOp, rewriteError } func createCorrelatedSubqueryOp( @@ -335,7 +333,6 @@ func createCorrelatedSubqueryOp( return nil, vterrors.VT12001("EXISTS sub-queries are only supported with AND clause") } - resultOuterOp := newOuter vars := map[string]int{} bindVars := map[*sqlparser.ColName]string{} var lhsCols []*sqlparser.ColName @@ -348,7 +345,7 @@ func createCorrelatedSubqueryOp( } nodeDeps := ctx.SemTable.RecursiveDeps(node) - if !nodeDeps.IsSolvedBy(TableID(resultOuterOp)) { + if !nodeDeps.IsSolvedBy(TableID(newOuter)) { return true } @@ -370,14 +367,13 @@ func createCorrelatedSubqueryOp( bindVars[node] = bindVar // if it does not exist, then push this as an output column in the outerOp and add it to the joinVars - newOuterOp, offset, err := resultOuterOp.AddColumn(ctx, aeWrap(node), true, false) + offsets, err := newOuter.AddColumns(ctx, true, []bool{false}, []*sqlparser.AliasedExpr{aeWrap(node)}) if err != nil { rewriteError = err return true } - resultOuterOp = newOuterOp lhsCols = append(lhsCols, node) - vars[bindVar] = offset + vars[bindVar] = offsets[0] return true }) if rewriteError != nil { @@ -390,7 +386,7 @@ func createCorrelatedSubqueryOp( } } return &CorrelatedSubQueryOp{ - Outer: resultOuterOp, + Outer: newOuter, Inner: innerOp, Extracted: extractedSubquery, Vars: vars, diff --git a/go/vt/vtgate/planbuilder/operators/table.go b/go/vt/vtgate/planbuilder/operators/table.go index 09f5927a574..8f50c4cc386 100644 --- a/go/vt/vtgate/planbuilder/operators/table.go +++ b/go/vt/vtgate/planbuilder/operators/table.go @@ -65,16 +65,8 @@ func (to *Table) AddPredicate(_ *plancontext.PlanningContext, expr sqlparser.Exp return newFilter(to, expr), nil } -func (to *Table) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, _, addToGroupBy bool) (ops.Operator, int, error) { - if addToGroupBy { - return nil, 0, vterrors.VT13001("tried to add group by to a table") - } - offset, err := addColumn(ctx, to, expr.Expr) - if err != nil { - return nil, 0, err - } - - return to, offset, nil +func (to *Table) AddColumns(*plancontext.PlanningContext, bool, []bool, []*sqlparser.AliasedExpr) ([]int, error) { + return nil, vterrors.VT13001("did not expect this method to be called") } func (to *Table) FindCol(_ *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { diff --git a/go/vt/vtgate/planbuilder/operators/union.go b/go/vt/vtgate/planbuilder/operators/union.go index c3525c5e952..f5dea3e6fb3 100644 --- a/go/vt/vtgate/planbuilder/operators/union.go +++ b/go/vt/vtgate/planbuilder/operators/union.go @@ -19,10 +19,9 @@ package operators import ( "fmt" - "vitess.io/vitess/go/slice" - "golang.org/x/exp/slices" + "vitess.io/vitess/go/slice" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" @@ -227,6 +226,59 @@ func (u *Union) Compact(*plancontext.PlanningContext) (ops.Operator, *rewrite.Ap return u, rewrite.NewTree("merged UNIONs", u), nil } +func (u *Union) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addToGroupBy []bool, exprs []*sqlparser.AliasedExpr) ([]int, error) { + offsets := make([]int, len(exprs)) + cols, err := u.GetColumns(ctx) + if err != nil { + return nil, err + } + for i, ae := range exprs { + if reuse { + offset, err := u.FindCol(ctx, ae.Expr) + if err != nil { + return nil, err + } + + if offset >= 0 { + offsets[i] = offset + continue + } + } + + switch e := ae.Expr.(type) { + case *sqlparser.ColName: + // here we deal with pure column access on top of the union + offset := slices.IndexFunc(cols, func(expr *sqlparser.AliasedExpr) bool { + return e.Name.EqualString(expr.ColumnName()) + }) + if offset == -1 { + return nil, vterrors.VT13001(fmt.Sprintf("could not find the column '%s' on the UNION", sqlparser.String(e))) + } + offsets[i] = offset + case *sqlparser.WeightStringFuncExpr: + wsArg := e.Expr + argIdx := slices.IndexFunc(cols, func(expr *sqlparser.AliasedExpr) bool { + return ctx.SemTable.EqualsExprWithDeps(wsArg, expr.Expr) + }) + + if argIdx == -1 { + return nil, vterrors.VT13001(fmt.Sprintf("could not find the argument to the weight_string function: %s", sqlparser.String(wsArg))) + } + + outputOffset, err := u.addWeightStringToOffset(ctx, argIdx, addToGroupBy[i]) + if err != nil { + return nil, err + } + + offsets[i] = outputOffset + default: + return nil, vterrors.VT13001(fmt.Sprintf("only weight_string function is expected - got %s", sqlparser.String(ae))) + } + } + + return offsets, nil +} + func (u *Union) AddColumn(ctx *plancontext.PlanningContext, ae *sqlparser.AliasedExpr, _, addToGroupBy bool) (ops.Operator, int, error) { col, err := u.FindCol(ctx, ae.Expr) if err != nil { @@ -281,11 +333,11 @@ func (u *Union) addWeightStringToOffset(ctx *plancontext.PlanningContext, argIdx if !ok { return 0, vterrors.VT09015() } - newSrc, thisOffset, err := src.AddColumn(ctx, aeWrap(weightStringFor(ae.Expr)), false, addToGroupBy) + offsets, err := src.AddColumns(ctx, false, []bool{addToGroupBy}, []*sqlparser.AliasedExpr{aeWrap(weightStringFor(ae.Expr))}) if err != nil { return 0, err } - + thisOffset := offsets[0] // all offsets for the newly added ws need to line up if i == 0 { outputOffset = thisOffset @@ -294,8 +346,6 @@ func (u *Union) addWeightStringToOffset(ctx *plancontext.PlanningContext, argIdx return 0, vterrors.VT12001("weight_string offsets did not line up for UNION") } } - - u.Sources[i] = newSrc } return } diff --git a/go/vt/vtgate/planbuilder/operators/vindex.go b/go/vt/vtgate/planbuilder/operators/vindex.go index 2864110dc0b..64e0d366e26 100644 --- a/go/vt/vtgate/planbuilder/operators/vindex.go +++ b/go/vt/vtgate/planbuilder/operators/vindex.go @@ -62,17 +62,33 @@ func (v *Vindex) Clone([]ops.Operator) ops.Operator { return &clone } -func (v *Vindex) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, _, addToGroupBy bool) (ops.Operator, int, error) { - if addToGroupBy { - return nil, 0, vterrors.VT13001("tried to add group by to a table") - } +func (v *Vindex) AddColumns(ctx *plancontext.PlanningContext, reuse bool, groupBys []bool, exprs []*sqlparser.AliasedExpr) ([]int, error) { + offsets := make([]int, len(exprs)) + for idx, ae := range exprs { + if groupBys[idx] { + return nil, vterrors.VT13001("tried to add group by to a table") + } + + if reuse { + offset, err := v.FindCol(ctx, ae.Expr) + if err != nil { + return nil, err + } + if offset > -1 { + offsets[idx] = offset + continue + } + } + + offset, err := addColumn(ctx, v, ae.Expr) + if err != nil { + return nil, err + } - offset, err := addColumn(ctx, v, expr.Expr) - if err != nil { - return nil, 0, err + offsets[idx] = offset } - return v, offset, nil + return offsets, nil } func colNameToExpr(c *sqlparser.ColName) *sqlparser.AliasedExpr { diff --git a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json index e3598695674..b500b993041 100644 --- a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json @@ -473,6 +473,6 @@ { "comment": "aggregation on top of aggregation not supported", "query": "select distinct count(*) from user, (select distinct count(*) from user) X", - "plan": "VT12001: unsupported: aggregation on top of aggregation not supported" + "plan": "VT12001: unsupported: failed to plan aggregation on: count(*)" } ] From f939787e62a42ff2d5b1566f9ea031d4c2622e4f Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Thu, 27 Jul 2023 09:35:41 +0200 Subject: [PATCH 23/44] clean up projections around aggregation and derived tables Signed-off-by: Andres Taylor --- .../planbuilder/operators/aggregator.go | 5 +- .../planbuilder/operators/apply_join.go | 6 +- .../vtgate/planbuilder/operators/distinct.go | 4 +- go/vt/vtgate/planbuilder/operators/filter.go | 4 +- go/vt/vtgate/planbuilder/operators/horizon.go | 4 +- go/vt/vtgate/planbuilder/operators/limit.go | 4 +- .../planbuilder/operators/offset_planning.go | 4 +- .../vtgate/planbuilder/operators/operator.go | 2 +- go/vt/vtgate/planbuilder/operators/ops/op.go | 2 +- .../vtgate/planbuilder/operators/ordering.go | 4 +- .../planbuilder/operators/projection.go | 45 +- go/vt/vtgate/planbuilder/operators/route.go | 6 +- go/vt/vtgate/planbuilder/operators/table.go | 2 +- go/vt/vtgate/planbuilder/operators/union.go | 6 +- go/vt/vtgate/planbuilder/operators/vindex.go | 4 +- .../planbuilder/testdata/aggr_cases.json | 742 +++++++++--------- .../planbuilder/testdata/filter_cases.json | 148 ++-- .../planbuilder/testdata/from_cases.json | 128 ++- .../testdata/info_schema57_cases.json | 112 ++- .../testdata/info_schema80_cases.json | 112 ++- .../planbuilder/testdata/select_cases.json | 50 +- .../planbuilder/testdata/tpch_cases.json | 4 +- .../planbuilder/testdata/union_cases.json | 309 ++++---- .../testdata/unsupported_cases.json | 5 - 24 files changed, 799 insertions(+), 913 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/aggregator.go b/go/vt/vtgate/planbuilder/operators/aggregator.go index d7da30d4382..0507c719e27 100644 --- a/go/vt/vtgate/planbuilder/operators/aggregator.go +++ b/go/vt/vtgate/planbuilder/operators/aggregator.go @@ -124,7 +124,7 @@ func (a *Aggregator) isDerived() bool { return a.TableID != nil } -func (a *Aggregator) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { +func (a *Aggregator) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr, _ bool) (int, error) { if a.isDerived() { derivedTBL, err := ctx.SemTable.TableInfoFor(*a.TableID) if err != nil { @@ -200,7 +200,7 @@ func (a *Aggregator) AddColumns(ctx *plancontext.PlanningContext, reuse bool, ad } func (a *Aggregator) findColInternal(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, addToGroupBy bool) (int, error) { - offset, err := a.FindCol(ctx, expr.Expr) + offset, err := a.FindCol(ctx, expr.Expr, false) if err != nil { return 0, err } @@ -354,6 +354,7 @@ func (aggr Aggr) getPushDownColumn() sqlparser.Expr { } func (a *Aggregator) planOffsetsNotPushed(ctx *plancontext.PlanningContext) error { + a.Source = &Projection{Source: a.Source} // we need to keep things in the column order, so we can't iterate over the aggregations or groupings for colIdx := range a.Columns { idx, err := a.addIfGroupingColumn(ctx, colIdx) diff --git a/go/vt/vtgate/planbuilder/operators/apply_join.go b/go/vt/vtgate/planbuilder/operators/apply_join.go index 424cbaf450b..ee95ff2c010 100644 --- a/go/vt/vtgate/planbuilder/operators/apply_join.go +++ b/go/vt/vtgate/planbuilder/operators/apply_join.go @@ -225,7 +225,7 @@ func (a *ApplyJoin) getJoinColumnFor(ctx *plancontext.PlanningContext, e *sqlpar return } -func (a *ApplyJoin) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { +func (a *ApplyJoin) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr, _ bool) (int, error) { offset, found := canReuseColumn(ctx, a.JoinColumns, expr, joinColumnToExpr) if !found { return -1, nil @@ -234,7 +234,7 @@ func (a *ApplyJoin) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Exp } func (a *ApplyJoin) AddColumn(ctx *plancontext.PlanningContext, expr *sqlparser.AliasedExpr, _, addToGroupBy bool) (ops.Operator, int, error) { - if offset, err := a.FindCol(ctx, expr.Expr); err != nil || offset != -1 { + if offset, err := a.FindCol(ctx, expr.Expr, false); err != nil || offset != -1 { return a, offset, err } @@ -258,7 +258,7 @@ func (a *ApplyJoin) AddColumns( offsets = make([]int, len(exprs)) for i, expr := range exprs { if reuse { - offset, err := a.FindCol(ctx, expr.Expr) + offset, err := a.FindCol(ctx, expr.Expr, false) if err != nil { return nil, err } diff --git a/go/vt/vtgate/planbuilder/operators/distinct.go b/go/vt/vtgate/planbuilder/operators/distinct.go index e91ab370b84..31eb925bd82 100644 --- a/go/vt/vtgate/planbuilder/operators/distinct.go +++ b/go/vt/vtgate/planbuilder/operators/distinct.go @@ -112,8 +112,8 @@ func (d *Distinct) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addT return d.Source.AddColumns(ctx, reuse, addToGroupBy, exprs) } -func (d *Distinct) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { - return d.Source.FindCol(ctx, expr) +func (d *Distinct) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr, underRoute bool) (int, error) { + return d.Source.FindCol(ctx, expr, underRoute) } func (d *Distinct) GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { diff --git a/go/vt/vtgate/planbuilder/operators/filter.go b/go/vt/vtgate/planbuilder/operators/filter.go index 2ffc3e1da32..378475c21ab 100644 --- a/go/vt/vtgate/planbuilder/operators/filter.go +++ b/go/vt/vtgate/planbuilder/operators/filter.go @@ -91,8 +91,8 @@ func (f *Filter) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addToG return f.Source.AddColumns(ctx, reuse, addToGroupBy, exprs) } -func (f *Filter) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { - return f.Source.FindCol(ctx, expr) +func (f *Filter) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr, underRoute bool) (int, error) { + return f.Source.FindCol(ctx, expr, underRoute) } func (f *Filter) GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { diff --git a/go/vt/vtgate/planbuilder/operators/horizon.go b/go/vt/vtgate/planbuilder/operators/horizon.go index a3c833f2b31..6718a241342 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon.go +++ b/go/vt/vtgate/planbuilder/operators/horizon.go @@ -159,7 +159,7 @@ func (h *Horizon) AddColumns(ctx *plancontext.PlanningContext, reuse bool, _ []b if !ok { return nil, vterrors.VT13001("cannot push non-ColName expression to horizon") } - offset, err := h.FindCol(ctx, col) + offset, err := h.FindCol(ctx, col, false) if err != nil { return nil, err } @@ -192,7 +192,7 @@ func canReuseColumn[T any]( return } -func (h *Horizon) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { +func (h *Horizon) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr, _ bool) (int, error) { for idx, se := range sqlparser.GetFirstSelect(h.Query).SelectExprs { ae, ok := se.(*sqlparser.AliasedExpr) if !ok { diff --git a/go/vt/vtgate/planbuilder/operators/limit.go b/go/vt/vtgate/planbuilder/operators/limit.go index 844cd7135a5..ff4b46ad78c 100644 --- a/go/vt/vtgate/planbuilder/operators/limit.go +++ b/go/vt/vtgate/planbuilder/operators/limit.go @@ -60,8 +60,8 @@ func (l *Limit) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addToGr return l.Source.AddColumns(ctx, reuse, addToGroupBy, exprs) } -func (l *Limit) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { - return l.Source.FindCol(ctx, expr) +func (l *Limit) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr, underRoute bool) (int, error) { + return l.Source.FindCol(ctx, expr, underRoute) } func (l *Limit) GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { diff --git a/go/vt/vtgate/planbuilder/operators/offset_planning.go b/go/vt/vtgate/planbuilder/operators/offset_planning.go index e39e1e8d36a..8a8095a58e6 100644 --- a/go/vt/vtgate/planbuilder/operators/offset_planning.go +++ b/go/vt/vtgate/planbuilder/operators/offset_planning.go @@ -162,7 +162,7 @@ func pullDistinctFromUNION(root ops.Operator) (ops.Operator, error) { func getVisitor( ctx *plancontext.PlanningContext, - findCol func(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error), + findCol func(ctx *plancontext.PlanningContext, expr sqlparser.Expr, underRoute bool) (int, error), found func(sqlparser.Expr, int), notFound func(sqlparser.Expr) error, ) func(node, parent sqlparser.SQLNode) bool { @@ -176,7 +176,7 @@ func getVisitor( return true } var offset int - offset, err = findCol(ctx, e) + offset, err = findCol(ctx, e, false) if err != nil { return false } diff --git a/go/vt/vtgate/planbuilder/operators/operator.go b/go/vt/vtgate/planbuilder/operators/operator.go index bcbfb76996e..23f5bd99b70 100644 --- a/go/vt/vtgate/planbuilder/operators/operator.go +++ b/go/vt/vtgate/planbuilder/operators/operator.go @@ -116,7 +116,7 @@ func (noColumns) AddColumns(*plancontext.PlanningContext, bool, []bool, []*sqlpa func (noColumns) GetColumns(*plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { return nil, vterrors.VT13001("noColumns operators have no column") } -func (noColumns) FindCol(*plancontext.PlanningContext, sqlparser.Expr) (int, error) { +func (noColumns) FindCol(*plancontext.PlanningContext, sqlparser.Expr, bool) (int, error) { return 0, vterrors.VT13001("noColumns operators have no column") } diff --git a/go/vt/vtgate/planbuilder/operators/ops/op.go b/go/vt/vtgate/planbuilder/operators/ops/op.go index 4ca3c74ee08..f8c48fcd719 100644 --- a/go/vt/vtgate/planbuilder/operators/ops/op.go +++ b/go/vt/vtgate/planbuilder/operators/ops/op.go @@ -46,7 +46,7 @@ type ( AddColumns(ctx *plancontext.PlanningContext, reuseExisting bool, addToGroupBy []bool, exprs []*sqlparser.AliasedExpr) ([]int, error) - FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) + FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr, underRoute bool) (int, error) GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) GetSelectExprs(ctx *plancontext.PlanningContext) (sqlparser.SelectExprs, error) diff --git a/go/vt/vtgate/planbuilder/operators/ordering.go b/go/vt/vtgate/planbuilder/operators/ordering.go index a1b074301d2..0a8d62f2aac 100644 --- a/go/vt/vtgate/planbuilder/operators/ordering.go +++ b/go/vt/vtgate/planbuilder/operators/ordering.go @@ -67,8 +67,8 @@ func (o *Ordering) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addT return o.Source.AddColumns(ctx, reuse, addToGroupBy, exprs) } -func (o *Ordering) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { - return o.Source.FindCol(ctx, expr) +func (o *Ordering) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr, underRoute bool) (int, error) { + return o.Source.FindCol(ctx, expr, underRoute) } func (o *Ordering) GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { diff --git a/go/vt/vtgate/planbuilder/operators/projection.go b/go/vt/vtgate/planbuilder/operators/projection.go index 9734ac7913b..a7c88a30200 100644 --- a/go/vt/vtgate/planbuilder/operators/projection.go +++ b/go/vt/vtgate/planbuilder/operators/projection.go @@ -128,13 +128,13 @@ func (p *Projection) isDerived() bool { return p.TableID != nil } -func (p *Projection) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { - if p.isDerived() { - return -1, nil - } - if offset, found := canReuseColumn(ctx, p.Columns, expr, extractExpr); found { - return offset, nil +func (p *Projection) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr, underRoute bool) (int, error) { + if !(underRoute && p.isDerived()) { + if offset, found := canReuseColumn(ctx, p.Columns, expr, extractExpr); found { + return offset, nil + } } + return -1, nil } @@ -154,23 +154,23 @@ func (p *Projection) AddColumns(ctx *plancontext.PlanningContext, reuse bool, ad colIdx := i + startOffset expr := ae.Expr - if reuse { - offset, err := p.FindCol(ctx, expr) + if p.TableID != nil { + vt, err := ctx.SemTable.TableInfoFor(*p.TableID) if err != nil { return nil, err } - if offset >= 0 { - offsets[i] = offset - continue - } + expr = semantics.RewriteDerivedTableExpression(expr, vt) } - if p.TableID != nil { - vt, err := ctx.SemTable.TableInfoFor(*p.TableID) + if reuse { + offset, err := p.FindCol(ctx, expr, false) if err != nil { return nil, err } - expr = semantics.RewriteDerivedTableExpression(expr, vt) + if offset >= 0 { + offsets[i] = offset + continue + } } // we add the column here, so we can find the expression in the next iteration of this loop, @@ -297,6 +297,21 @@ func (p *Projection) ShortDescription() string { } func (p *Projection) Compact(ctx *plancontext.PlanningContext) (ops.Operator, *rewrite.ApplyResult, error) { + if !p.isDerived() { + // for projections that are not derived tables, we can check if it is safe to remove or not + needed := false + for i, projection := range p.Projections { + e, ok := projection.(Offset) + if !ok || e.Offset != i { + needed = true + break + } + } + if !needed { + return p.Source, rewrite.NewTree("removed projection only passing through the input", p), nil + } + } + switch src := p.Source.(type) { case *Route: return p.compactWithRoute(ctx, src) diff --git a/go/vt/vtgate/planbuilder/operators/route.go b/go/vt/vtgate/planbuilder/operators/route.go index e8ff537e22b..8fb951e4df1 100644 --- a/go/vt/vtgate/planbuilder/operators/route.go +++ b/go/vt/vtgate/planbuilder/operators/route.go @@ -550,7 +550,7 @@ func (r *Route) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addToGr removeKeyspaceFromSelectExpr(expr) if reuse { - offset, err := r.FindCol(ctx, expr.Expr) + offset, err := r.FindCol(ctx, expr.Expr, true) if err != nil { return nil, err } @@ -643,8 +643,8 @@ func addMultipleColumnsToInput(ctx *plancontext.PlanningContext, operator ops.Op } } -func (r *Route) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { - return r.Source.FindCol(ctx, expr) +func (r *Route) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr, _ bool) (int, error) { + return r.Source.FindCol(ctx, expr, true) } func (r *Route) GetColumns(ctx *plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { diff --git a/go/vt/vtgate/planbuilder/operators/table.go b/go/vt/vtgate/planbuilder/operators/table.go index 8f50c4cc386..94ae634a0bf 100644 --- a/go/vt/vtgate/planbuilder/operators/table.go +++ b/go/vt/vtgate/planbuilder/operators/table.go @@ -69,7 +69,7 @@ func (to *Table) AddColumns(*plancontext.PlanningContext, bool, []bool, []*sqlpa return nil, vterrors.VT13001("did not expect this method to be called") } -func (to *Table) FindCol(_ *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { +func (to *Table) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr, underRoute bool) (int, error) { colToFind, ok := expr.(*sqlparser.ColName) if !ok { return -1, nil diff --git a/go/vt/vtgate/planbuilder/operators/union.go b/go/vt/vtgate/planbuilder/operators/union.go index f5dea3e6fb3..bc2f2ade36d 100644 --- a/go/vt/vtgate/planbuilder/operators/union.go +++ b/go/vt/vtgate/planbuilder/operators/union.go @@ -234,7 +234,7 @@ func (u *Union) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addToGr } for i, ae := range exprs { if reuse { - offset, err := u.FindCol(ctx, ae.Expr) + offset, err := u.FindCol(ctx, ae.Expr, false) if err != nil { return nil, err } @@ -280,7 +280,7 @@ func (u *Union) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addToGr } func (u *Union) AddColumn(ctx *plancontext.PlanningContext, ae *sqlparser.AliasedExpr, _, addToGroupBy bool) (ops.Operator, int, error) { - col, err := u.FindCol(ctx, ae.Expr) + col, err := u.FindCol(ctx, ae.Expr, false) if err != nil { return nil, 0, err } @@ -350,7 +350,7 @@ func (u *Union) addWeightStringToOffset(ctx *plancontext.PlanningContext, argIdx return } -func (u *Union) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { +func (u *Union) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr, underRoute bool) (int, error) { columns, err := u.GetColumns(ctx) if err != nil { return 0, err diff --git a/go/vt/vtgate/planbuilder/operators/vindex.go b/go/vt/vtgate/planbuilder/operators/vindex.go index 64e0d366e26..eeb57561afb 100644 --- a/go/vt/vtgate/planbuilder/operators/vindex.go +++ b/go/vt/vtgate/planbuilder/operators/vindex.go @@ -70,7 +70,7 @@ func (v *Vindex) AddColumns(ctx *plancontext.PlanningContext, reuse bool, groupB } if reuse { - offset, err := v.FindCol(ctx, ae.Expr) + offset, err := v.FindCol(ctx, ae.Expr, true) if err != nil { return nil, err } @@ -98,7 +98,7 @@ func colNameToExpr(c *sqlparser.ColName) *sqlparser.AliasedExpr { } } -func (v *Vindex) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (int, error) { +func (v *Vindex) FindCol(ctx *plancontext.PlanningContext, expr sqlparser.Expr, underRoute bool) (int, error) { for idx, col := range v.Columns { if ctx.SemTable.EqualsExprWithDeps(expr, col) { return idx, nil diff --git a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json index 775ecf500be..aa9df5594e8 100644 --- a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json @@ -2054,35 +2054,26 @@ "QueryType": "SELECT", "Original": "select count(*) as a, val1 from user group by val1 having a = 1.00", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0, - 1 - ], + "OperatorType": "Filter", + "Predicate": "count(*) = 1.00", "Inputs": [ { - "OperatorType": "Filter", - "Predicate": "count(*) = 1.00", + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "sum_count_star(0) AS a", + "GroupBy": "(1|2)", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "Aggregates": "sum_count_star(0) AS a", - "GroupBy": "(1|2)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select count(*) as a, val1, weight_string(val1) from `user` where 1 != 1 group by val1, weight_string(val1)", - "OrderBy": "(1|2) ASC", - "Query": "select count(*) as a, val1, weight_string(val1) from `user` group by val1, weight_string(val1) order by val1 asc", - "Table": "`user`" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select count(*) as a, val1, weight_string(val1) from `user` where 1 != 1 group by val1, weight_string(val1)", + "OrderBy": "(1|2) ASC", + "Query": "select count(*) as a, val1, weight_string(val1) from `user` group by val1, weight_string(val1) order by val1 asc", + "Table": "`user`" } ] } @@ -2131,59 +2122,51 @@ "QueryType": "SELECT", "Original": "select 1 from user having count(id) = 10 and name = 'a'", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Filter", + "Predicate": "count(id) = 10", "Inputs": [ { - "OperatorType": "Filter", - "Predicate": "count(id) = 10", + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "any_value(0) AS 1, sum_count(1) AS count(id)", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Scalar", - "Aggregates": "any_value(0) AS 1, sum_count(1) AS count(id)", + "OperatorType": "VindexLookup", + "Variant": "Equal", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "Values": [ + "VARCHAR(\"a\")" + ], + "Vindex": "name_user_map", "Inputs": [ { - "OperatorType": "VindexLookup", - "Variant": "Equal", + "OperatorType": "Route", + "Variant": "IN", "Keyspace": { "Name": "user", "Sharded": true }, + "FieldQuery": "select `name`, keyspace_id from name_user_vdx where 1 != 1", + "Query": "select `name`, keyspace_id from name_user_vdx where `name` in ::__vals", + "Table": "name_user_vdx", "Values": [ - "VARCHAR(\"a\")" + "::name" ], - "Vindex": "name_user_map", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "IN", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select `name`, keyspace_id from name_user_vdx where 1 != 1", - "Query": "select `name`, keyspace_id from name_user_vdx where `name` in ::__vals", - "Table": "name_user_vdx", - "Values": [ - "::name" - ], - "Vindex": "user_index" - }, - { - "OperatorType": "Route", - "Variant": "ByDestination", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select 1, count(id) from `user` where 1 != 1", - "Query": "select 1, count(id) from `user` where `name` = 'a'", - "Table": "`user`" - } - ] + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "ByDestination", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 1, count(id) from `user` where 1 != 1", + "Query": "select 1, count(id) from `user` where `name` = 'a'", + "Table": "`user`" } ] } @@ -2260,32 +2243,24 @@ "QueryType": "SELECT", "Original": "select 1 from user having count(id) = 10", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Filter", + "Predicate": "count(id) = 10", "Inputs": [ { - "OperatorType": "Filter", - "Predicate": "count(id) = 10", + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "any_value(0) AS 1, sum_count(1) AS count(id)", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Scalar", - "Aggregates": "any_value(0) AS 1, sum_count(1) AS count(id)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select 1, count(id) from `user` where 1 != 1", - "Query": "select 1, count(id) from `user`", - "Table": "`user`" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 1, count(id) from `user` where 1 != 1", + "Query": "select 1, count(id) from `user`", + "Table": "`user`" } ] } @@ -2942,35 +2917,26 @@ "QueryType": "SELECT", "Original": "select foo, count(*) from user group by foo having count(*) = 3", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0, - 1 - ], + "OperatorType": "Filter", + "Predicate": "count(*) = 3", "Inputs": [ { - "OperatorType": "Filter", - "Predicate": "count(*) = 3", + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "sum_count_star(1) AS count(*)", + "GroupBy": "(0|2)", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "Aggregates": "sum_count_star(1) AS count(*)", - "GroupBy": "(0|2)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select foo, count(*), weight_string(foo) from `user` where 1 != 1 group by foo, weight_string(foo)", - "OrderBy": "(0|2) ASC", - "Query": "select foo, count(*), weight_string(foo) from `user` group by foo, weight_string(foo) order by foo asc", - "Table": "`user`" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select foo, count(*), weight_string(foo) from `user` where 1 != 1 group by foo, weight_string(foo)", + "OrderBy": "(0|2) ASC", + "Query": "select foo, count(*), weight_string(foo) from `user` group by foo, weight_string(foo) order by foo asc", + "Table": "`user`" } ] } @@ -2988,36 +2954,26 @@ "QueryType": "SELECT", "Original": "select foo, sum(foo), sum(bar) from user group by foo having sum(foo)+sum(bar) = 42", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0, - 1, - 2 - ], + "OperatorType": "Filter", + "Predicate": "sum(foo) + sum(bar) = 42", "Inputs": [ { - "OperatorType": "Filter", - "Predicate": "sum(foo) + sum(bar) = 42", + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "sum(1) AS sum(foo), sum(2) AS sum(bar)", + "GroupBy": "(0|3)", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "Aggregates": "sum(1) AS sum(foo), sum(2) AS sum(bar)", - "GroupBy": "(0|3)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select foo, sum(foo), sum(bar), weight_string(foo) from `user` where 1 != 1 group by foo, weight_string(foo)", - "OrderBy": "(0|3) ASC", - "Query": "select foo, sum(foo), sum(bar), weight_string(foo) from `user` group by foo, weight_string(foo) order by foo asc", - "Table": "`user`" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select foo, sum(foo), sum(bar), weight_string(foo) from `user` where 1 != 1 group by foo, weight_string(foo)", + "OrderBy": "(0|3) ASC", + "Query": "select foo, sum(foo), sum(bar), weight_string(foo) from `user` group by foo, weight_string(foo) order by foo asc", + "Table": "`user`" } ] } @@ -3035,36 +2991,26 @@ "QueryType": "SELECT", "Original": "select foo, sum(foo) as fooSum, sum(bar) as barSum from user group by foo having fooSum+sum(bar) = 42", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0, - 1, - 2 - ], + "OperatorType": "Filter", + "Predicate": "sum(foo) + sum(bar) = 42", "Inputs": [ { - "OperatorType": "Filter", - "Predicate": "sum(foo) + sum(bar) = 42", + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "sum(1) AS fooSum, sum(2) AS barSum", + "GroupBy": "(0|3)", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "Aggregates": "sum(1) AS fooSum, sum(2) AS barSum", - "GroupBy": "(0|3)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select foo, sum(foo) as fooSum, sum(bar) as barSum, weight_string(foo) from `user` where 1 != 1 group by foo, weight_string(foo)", - "OrderBy": "(0|3) ASC", - "Query": "select foo, sum(foo) as fooSum, sum(bar) as barSum, weight_string(foo) from `user` group by foo, weight_string(foo) order by foo asc", - "Table": "`user`" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select foo, sum(foo) as fooSum, sum(bar) as barSum, weight_string(foo) from `user` where 1 != 1 group by foo, weight_string(foo)", + "OrderBy": "(0|3) ASC", + "Query": "select foo, sum(foo) as fooSum, sum(bar) as barSum, weight_string(foo) from `user` group by foo, weight_string(foo) order by foo asc", + "Table": "`user`" } ] } @@ -3082,34 +3028,26 @@ "QueryType": "SELECT", "Original": "select foo from user group by foo having count(*) = 3", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Filter", + "Predicate": "count(*) = 3", "Inputs": [ { - "OperatorType": "Filter", - "Predicate": "count(*) = 3", + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "sum_count_star(1) AS count(*)", + "GroupBy": "(0|2)", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "Aggregates": "sum_count_star(1) AS count(*)", - "GroupBy": "(0|2)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select foo, count(*), weight_string(foo) from `user` where 1 != 1 group by foo, weight_string(foo)", - "OrderBy": "(0|2) ASC", - "Query": "select foo, count(*), weight_string(foo) from `user` group by foo, weight_string(foo) order by foo asc", - "Table": "`user`" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select foo, count(*), weight_string(foo) from `user` where 1 != 1 group by foo, weight_string(foo)", + "OrderBy": "(0|2) ASC", + "Query": "select foo, count(*), weight_string(foo) from `user` group by foo, weight_string(foo) order by foo asc", + "Table": "`user`" } ] } @@ -3127,70 +3065,62 @@ "QueryType": "SELECT", "Original": "select u.id from user u join user_extra ue on ue.id = u.id group by u.id having count(u.name) = 3", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Filter", + "Predicate": "count(u.`name`) = 3", "Inputs": [ { - "OperatorType": "Filter", - "Predicate": "count(u.`name`) = 3", + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "sum_count(1) AS count(u.`name`)", + "GroupBy": "(0|2)", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "Aggregates": "sum_count(1) AS count(u.`name`)", - "GroupBy": "(0|2)", + "OperatorType": "Projection", + "Expressions": [ + "[COLUMN 2] as id", + "[COLUMN 1] * [COLUMN 0] as count(u.`name`)", + "[COLUMN 3] as weight_string(u.id)" + ], "Inputs": [ { - "OperatorType": "Projection", - "Expressions": [ - "[COLUMN 2] as id", - "[COLUMN 1] * [COLUMN 0] as count(u.`name`)", - "[COLUMN 3] as weight_string(u.id)" - ], + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(2|3) ASC", "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(2|3) ASC", + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "R:0,L:0,R:1,R:2", + "JoinVars": { + "ue_id": 1 + }, + "TableName": "user_extra_`user`", "Inputs": [ { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "R:0,L:0,R:1,R:2", - "JoinVars": { - "ue_id": 1 + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true }, - "TableName": "user_extra_`user`", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select count(*), ue.id from user_extra as ue where 1 != 1 group by ue.id", - "Query": "select count(*), ue.id from user_extra as ue group by ue.id", - "Table": "user_extra" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select count(u.`name`), u.id, weight_string(u.id) from `user` as u where 1 != 1 group by u.id, weight_string(u.id)", - "Query": "select count(u.`name`), u.id, weight_string(u.id) from `user` as u where u.id = :ue_id group by u.id, weight_string(u.id)", - "Table": "`user`", - "Values": [ - ":ue_id" - ], - "Vindex": "user_index" - } - ] + "FieldQuery": "select count(*), ue.id from user_extra as ue where 1 != 1 group by ue.id", + "Query": "select count(*), ue.id from user_extra as ue group by ue.id", + "Table": "user_extra" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select count(u.`name`), u.id, weight_string(u.id) from `user` as u where 1 != 1 group by u.id, weight_string(u.id)", + "Query": "select count(u.`name`), u.id, weight_string(u.id) from `user` as u where u.id = :ue_id group by u.id, weight_string(u.id)", + "Table": "`user`", + "Values": [ + ":ue_id" + ], + "Vindex": "user_index" } ] } @@ -3238,70 +3168,62 @@ "QueryType": "SELECT", "Original": "select u.id from user u join user_extra ue on ue.id = u.id group by u.id having count(*) < 3 and count(*) > 5", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Filter", + "Predicate": "count(*) < 3 and count(*) > 5", "Inputs": [ { - "OperatorType": "Filter", - "Predicate": "count(*) < 3 and count(*) > 5", + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "sum_count_star(1) AS count(*)", + "GroupBy": "(0|2)", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "Aggregates": "sum_count_star(1) AS count(*)", - "GroupBy": "(0|2)", + "OperatorType": "Projection", + "Expressions": [ + "[COLUMN 2] as id", + "[COLUMN 0] * [COLUMN 1] as count(*)", + "[COLUMN 3] as weight_string(u.id)" + ], "Inputs": [ { - "OperatorType": "Projection", - "Expressions": [ - "[COLUMN 2] as id", - "[COLUMN 0] * [COLUMN 1] as count(*)", - "[COLUMN 3] as weight_string(u.id)" - ], + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(2|3) ASC", "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(2|3) ASC", + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,R:0,R:1,R:2", + "JoinVars": { + "ue_id": 1 + }, + "TableName": "user_extra_`user`", "Inputs": [ { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "L:0,R:0,R:1,R:2", - "JoinVars": { - "ue_id": 1 + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true }, - "TableName": "user_extra_`user`", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select count(*), ue.id from user_extra as ue where 1 != 1 group by ue.id", - "Query": "select count(*), ue.id from user_extra as ue group by ue.id", - "Table": "user_extra" - }, - { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select count(*), u.id, weight_string(u.id) from `user` as u where 1 != 1 group by u.id, weight_string(u.id)", - "Query": "select count(*), u.id, weight_string(u.id) from `user` as u where u.id = :ue_id group by u.id, weight_string(u.id)", - "Table": "`user`", - "Values": [ - ":ue_id" - ], - "Vindex": "user_index" - } - ] + "FieldQuery": "select count(*), ue.id from user_extra as ue where 1 != 1 group by ue.id", + "Query": "select count(*), ue.id from user_extra as ue group by ue.id", + "Table": "user_extra" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select count(*), u.id, weight_string(u.id) from `user` as u where 1 != 1 group by u.id, weight_string(u.id)", + "Query": "select count(*), u.id, weight_string(u.id) from `user` as u where u.id = :ue_id group by u.id, weight_string(u.id)", + "Table": "`user`", + "Values": [ + ":ue_id" + ], + "Vindex": "user_index" } ] } @@ -3728,32 +3650,24 @@ "QueryType": "SELECT", "Original": "select * from (select id from user having count(*) = 1) s", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Filter", + "Predicate": "count(*) = 1", "Inputs": [ { - "OperatorType": "Filter", - "Predicate": "count(*) = 1", + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "any_value(0) AS id, sum_count_star(1) AS count(*)", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Scalar", - "Aggregates": "any_value(0) AS id, sum_count_star(1) AS count(*)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, count(*) from `user` where 1 != 1", - "Query": "select id, count(*) from `user`", - "Table": "`user`" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, count(*) from `user` where 1 != 1", + "Query": "select id, count(*) from `user`", + "Table": "`user`" } ] } @@ -4067,34 +3981,26 @@ "QueryType": "SELECT", "Original": "SELECT foo FROM (SELECT foo, max(baz) as bazo FROM (SELECT foo, baz FROM user) f GROUP BY foo) tt WHERE bazo BETWEEN 100 AND 200", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Filter", + "Predicate": "bazo between 100 and 200", "Inputs": [ { - "OperatorType": "Filter", - "Predicate": "bazo between 100 and 200", + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "max(1|3) AS bazo", + "GroupBy": "(0|2)", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "Aggregates": "max(1|3) AS bazo", - "GroupBy": "(0|2)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select foo, max(baz) as bazo, weight_string(foo), weight_string(baz) from (select foo, baz from `user` where 1 != 1) as f where 1 != 1 group by foo, weight_string(foo), weight_string(baz)", - "OrderBy": "(0|2) ASC", - "Query": "select foo, max(baz) as bazo, weight_string(foo), weight_string(baz) from (select foo, baz from `user`) as f group by foo, weight_string(foo), weight_string(baz) order by foo asc", - "Table": "`user`" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select foo, max(baz) as bazo, weight_string(foo), weight_string(baz) from (select foo, baz from `user` where 1 != 1) as f where 1 != 1 group by foo, weight_string(foo), weight_string(baz)", + "OrderBy": "(0|2) ASC", + "Query": "select foo, max(baz) as bazo, weight_string(foo), weight_string(baz) from (select foo, baz from `user`) as f group by foo, weight_string(foo), weight_string(baz) order by foo asc", + "Table": "`user`" } ] } @@ -4112,34 +4018,26 @@ "QueryType": "SELECT", "Original": "SELECT foo FROM (SELECT foo, count(baz) as bazo FROM (SELECT foo, baz FROM user) f GROUP BY foo) tt WHERE bazo BETWEEN 100 AND 200", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Filter", + "Predicate": "bazo between 100 and 200", "Inputs": [ { - "OperatorType": "Filter", - "Predicate": "bazo between 100 and 200", + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "sum_count(1) AS bazo", + "GroupBy": "(0|2)", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "Aggregates": "sum_count(1) AS bazo", - "GroupBy": "(0|2)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select foo, count(baz) as bazo, weight_string(foo) from (select foo, baz from `user` where 1 != 1) as f where 1 != 1 group by foo, weight_string(foo)", - "OrderBy": "(0|2) ASC", - "Query": "select foo, count(baz) as bazo, weight_string(foo) from (select foo, baz from `user`) as f group by foo, weight_string(foo) order by foo asc", - "Table": "`user`" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select foo, count(baz) as bazo, weight_string(foo) from (select foo, baz from `user` where 1 != 1) as f where 1 != 1 group by foo, weight_string(foo)", + "OrderBy": "(0|2) ASC", + "Query": "select foo, count(baz) as bazo, weight_string(foo) from (select foo, baz from `user`) as f group by foo, weight_string(foo) order by foo asc", + "Table": "`user`" } ] } @@ -5931,19 +5829,110 @@ "Aggregates": "count(0) AS count(val2), sum(1) AS sum(val2)", "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(2)", + "OperatorType": "SimpleProjection", + "Columns": [ + 0, + 0 + ], "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select val2, val2 from (select id, val2 from `user` where 1 != 1) as x where 1 != 1", - "Query": "select val2, val2 from (select id, val2 from `user` where val2 is null) as x limit :__upper_limit", - "Table": "`user`" + "OperatorType": "Limit", + "Count": "INT64(2)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select val2 from (select id, val2 from `user` where 1 != 1) as x where 1 != 1", + "Query": "select val2 from (select id, val2 from `user` where val2 is null) as x limit :__upper_limit", + "Table": "`user`" + } + ] + } + ] + } + ] + }, + "TablesUsed": [ + "user.user" + ] + } + }, + { + "comment": "aggregation on top of aggregation works fine", + "query": "select distinct count(*) from user, (select distinct count(*) from user) X", + "plan": { + "QueryType": "SELECT", + "Original": "select distinct count(*) from user, (select distinct count(*) from user) X", + "Instructions": { + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "sum_count_star(0) AS count(*)", + "Inputs": [ + { + "OperatorType": "Projection", + "Expressions": [ + "[COLUMN 0] * [COLUMN 1] as count(*)" + ], + "Inputs": [ + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,R:0", + "TableName": "`user`_`user`", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select count(*) from `user` where 1 != 1", + "Query": "select count(*) from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "count_star(0)", + "GroupBy": "(1|2)", + "Inputs": [ + { + "OperatorType": "SimpleProjection", + "Columns": [ + 3, + 1, + 2 + ], + "Inputs": [ + { + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "sum_count_star(0) AS count(*), any_value(3)", + "GroupBy": "(1|2)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select count(*), .0, weight_string(.0), 1 from `user` where 1 != 1 group by .0, weight_string(.0)", + "Query": "select count(*), .0, weight_string(.0), 1 from `user` group by .0, weight_string(.0)", + "Table": "`user`" + } + ] + } + ] + } + ] + } + ] } ] } @@ -5954,4 +5943,5 @@ ] } } + ] diff --git a/go/vt/vtgate/planbuilder/testdata/filter_cases.json b/go/vt/vtgate/planbuilder/testdata/filter_cases.json index d388fb1fbe3..244cfdd1c8e 100644 --- a/go/vt/vtgate/planbuilder/testdata/filter_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/filter_cases.json @@ -3153,47 +3153,39 @@ "QueryType": "SELECT", "Original": "select user.id from user left join user_extra on user.col = user_extra.col where user_extra.id is null", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Filter", + "Predicate": "user_extra.id is null", "Inputs": [ { - "OperatorType": "Filter", - "Predicate": "user_extra.id is null", + "OperatorType": "Join", + "Variant": "LeftJoin", + "JoinColumnIndexes": "L:0,R:0", + "JoinVars": { + "user_col": 1 + }, + "TableName": "`user`_user_extra", "Inputs": [ { - "OperatorType": "Join", - "Variant": "LeftJoin", - "JoinColumnIndexes": "L:0,R:0", - "JoinVars": { - "user_col": 1 + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true }, - "TableName": "`user`_user_extra", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select `user`.id, `user`.col from `user` where 1 != 1", - "Query": "select `user`.id, `user`.col from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select user_extra.id from user_extra where 1 != 1", - "Query": "select user_extra.id from user_extra where user_extra.col = :user_col", - "Table": "user_extra" - } - ] + "FieldQuery": "select `user`.id, `user`.col from `user` where 1 != 1", + "Query": "select `user`.id, `user`.col from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select user_extra.id from user_extra where 1 != 1", + "Query": "select user_extra.id from user_extra where user_extra.col = :user_col", + "Table": "user_extra" } ] } @@ -4121,61 +4113,53 @@ "QueryType": "SELECT", "Original": "select a.textcol1 from user a join user b where a.textcol1 = b.textcol2 group by a.textcol1 having repeat(a.textcol1,sum(a.id)) like \"And%res\"", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Filter", + "Predicate": "repeat(a.textcol1, sum(a.id)) like 'And%res'", "Inputs": [ { - "OperatorType": "Filter", - "Predicate": "repeat(a.textcol1, sum(a.id)) like 'And%res'", + "OperatorType": "Aggregate", + "Variant": "Ordered", + "Aggregates": "sum(1) AS sum(a.id)", + "GroupBy": "0 COLLATE latin1_swedish_ci", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Ordered", - "Aggregates": "sum(1) AS sum(a.id)", - "GroupBy": "0 COLLATE latin1_swedish_ci", + "OperatorType": "Projection", + "Expressions": [ + "[COLUMN 2] as textcol1", + "[COLUMN 0] * [COLUMN 1] as sum(a.id)" + ], "Inputs": [ { - "OperatorType": "Projection", - "Expressions": [ - "[COLUMN 2] as textcol1", - "[COLUMN 0] * [COLUMN 1] as sum(a.id)" - ], + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,R:0,L:1", + "JoinVars": { + "a_textcol1": 1 + }, + "TableName": "`user`_`user`", "Inputs": [ { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "L:0,R:0,L:1", - "JoinVars": { - "a_textcol1": 1 + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select sum(a.id), a.textcol1 from `user` as a where 1 != 1 group by a.textcol1", + "OrderBy": "1 ASC COLLATE latin1_swedish_ci", + "Query": "select sum(a.id), a.textcol1 from `user` as a group by a.textcol1 order by a.textcol1 asc", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true }, - "TableName": "`user`_`user`", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select sum(a.id), a.textcol1 from `user` as a where 1 != 1 group by a.textcol1", - "OrderBy": "1 ASC COLLATE latin1_swedish_ci", - "Query": "select sum(a.id), a.textcol1 from `user` as a group by a.textcol1 order by a.textcol1 asc", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select count(*) from `user` as b where 1 != 1 group by .0", - "Query": "select count(*) from `user` as b where b.textcol2 = :a_textcol1 group by .0", - "Table": "`user`" - } - ] + "FieldQuery": "select count(*) from `user` as b where 1 != 1 group by .0", + "Query": "select count(*) from `user` as b where b.textcol2 = :a_textcol1 group by .0", + "Table": "`user`" } ] } diff --git a/go/vt/vtgate/planbuilder/testdata/from_cases.json b/go/vt/vtgate/planbuilder/testdata/from_cases.json index 533521881be..e014b0c0b67 100644 --- a/go/vt/vtgate/planbuilder/testdata/from_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/from_cases.json @@ -3321,47 +3321,39 @@ "QueryType": "SELECT", "Original": "select user.id from user left join user_extra on user.col = user_extra.col where coalesce(user_extra.col, 4) = 5", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Filter", + "Predicate": "coalesce(user_extra.col, 4) = 5", "Inputs": [ { - "OperatorType": "Filter", - "Predicate": "coalesce(user_extra.col, 4) = 5", + "OperatorType": "Join", + "Variant": "LeftJoin", + "JoinColumnIndexes": "L:0,R:0", + "JoinVars": { + "user_col": 1 + }, + "TableName": "`user`_user_extra", "Inputs": [ { - "OperatorType": "Join", - "Variant": "LeftJoin", - "JoinColumnIndexes": "L:0,R:0", - "JoinVars": { - "user_col": 1 + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true }, - "TableName": "`user`_user_extra", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select `user`.id, `user`.col from `user` where 1 != 1", - "Query": "select `user`.id, `user`.col from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select user_extra.col from user_extra where 1 != 1", - "Query": "select user_extra.col from user_extra where user_extra.col = :user_col", - "Table": "user_extra" - } - ] + "FieldQuery": "select `user`.id, `user`.col from `user` where 1 != 1", + "Query": "select `user`.id, `user`.col from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select user_extra.col from user_extra where 1 != 1", + "Query": "select user_extra.col from user_extra where user_extra.col = :user_col", + "Table": "user_extra" } ] } @@ -3886,47 +3878,39 @@ "QueryType": "SELECT", "Original": "select user.id from user left join user_extra on user.col = user_extra.col where user_extra.col between 10 and 20", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Filter", + "Predicate": "user_extra.col between 10 and 20", "Inputs": [ { - "OperatorType": "Filter", - "Predicate": "user_extra.col between 10 and 20", + "OperatorType": "Join", + "Variant": "LeftJoin", + "JoinColumnIndexes": "L:0,R:0", + "JoinVars": { + "user_col": 1 + }, + "TableName": "`user`_user_extra", "Inputs": [ { - "OperatorType": "Join", - "Variant": "LeftJoin", - "JoinColumnIndexes": "L:0,R:0", - "JoinVars": { - "user_col": 1 + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true }, - "TableName": "`user`_user_extra", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select `user`.id, `user`.col from `user` where 1 != 1", - "Query": "select `user`.id, `user`.col from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select user_extra.col from user_extra where 1 != 1", - "Query": "select user_extra.col from user_extra where user_extra.col = :user_col", - "Table": "user_extra" - } - ] + "FieldQuery": "select `user`.id, `user`.col from `user` where 1 != 1", + "Query": "select `user`.id, `user`.col from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select user_extra.col from user_extra where 1 != 1", + "Query": "select user_extra.col from user_extra where user_extra.col = :user_col", + "Table": "user_extra" } ] } diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json index c0beebde7aa..51b467ade6e 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema57_cases.json @@ -827,39 +827,31 @@ "QueryType": "SELECT", "Original": "select found from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", - "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", - "SysTableTableSchema": "[VARCHAR(\"music\")]", - "Table": "information_schema.`tables`" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 as found from information_schema.views where 1 != 1", - "Query": "select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1", - "SysTableTableSchema": "[VARCHAR(\"music\")]", - "Table": "information_schema.views" - } - ] + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", + "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"music\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.views where 1 != 1", + "Query": "select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1", + "SysTableTableSchema": "[VARCHAR(\"music\")]", + "Table": "information_schema.views" } ] } @@ -1004,44 +996,36 @@ "QueryType": "SELECT", "Original": "select * from (select TABLE_NAME from information_schema.tables t where t.TABLE_SCHEMA = 'a' union select TABLE_NAME from information_schema.columns) dt", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 + "OperatorType": "Distinct", + "Collations": [ + "0: utf8mb4_0900_ai_ci" ], "Inputs": [ { - "OperatorType": "Distinct", - "Collations": [ - "0: utf8mb4_0900_ai_ci" - ], + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_NAME from information_schema.`tables` as t where 1 != 1", - "Query": "select distinct TABLE_NAME from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */", - "SysTableTableSchema": "[VARCHAR(\"a\")]", - "Table": "information_schema.`tables`" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_NAME from information_schema.`columns` where 1 != 1", - "Query": "select distinct TABLE_NAME from information_schema.`columns`", - "Table": "information_schema.`columns`" - } - ] + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_NAME from information_schema.`tables` as t where 1 != 1", + "Query": "select distinct TABLE_NAME from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"a\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_NAME from information_schema.`columns` where 1 != 1", + "Query": "select distinct TABLE_NAME from information_schema.`columns`", + "Table": "information_schema.`columns`" } ] } diff --git a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json index 648c434e396..9313b1f15f1 100644 --- a/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/info_schema80_cases.json @@ -892,39 +892,31 @@ "QueryType": "SELECT", "Original": "select found from (select 1 as found from information_schema.`tables` where table_schema = 'music' union all (select 1 as found from information_schema.views where table_schema = 'music' limit 1)) as t", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", - "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", - "SysTableTableSchema": "[VARCHAR(\"music\")]", - "Table": "information_schema.`tables`" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 as found from information_schema.views where 1 != 1", - "Query": "select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1", - "SysTableTableSchema": "[VARCHAR(\"music\")]", - "Table": "information_schema.views" - } - ] + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.`tables` where 1 != 1", + "Query": "select 1 as found from information_schema.`tables` where table_schema = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"music\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 as found from information_schema.views where 1 != 1", + "Query": "select 1 as found from information_schema.views where table_schema = :__vtschemaname /* VARCHAR */ limit 1", + "SysTableTableSchema": "[VARCHAR(\"music\")]", + "Table": "information_schema.views" } ] } @@ -1069,44 +1061,36 @@ "QueryType": "SELECT", "Original": "select * from (select TABLE_NAME from information_schema.tables t where t.TABLE_SCHEMA = 'a' union select TABLE_NAME from information_schema.columns) dt", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 + "OperatorType": "Distinct", + "Collations": [ + "0: utf8mb4_0900_ai_ci" ], "Inputs": [ { - "OperatorType": "Distinct", - "Collations": [ - "0: utf8mb4_0900_ai_ci" - ], + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_NAME from information_schema.`tables` as t where 1 != 1", - "Query": "select distinct TABLE_NAME from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */", - "SysTableTableSchema": "[VARCHAR(\"a\")]", - "Table": "information_schema.`tables`" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select TABLE_NAME from information_schema.`columns` where 1 != 1", - "Query": "select distinct TABLE_NAME from information_schema.`columns`", - "Table": "information_schema.`columns`" - } - ] + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_NAME from information_schema.`tables` as t where 1 != 1", + "Query": "select distinct TABLE_NAME from information_schema.`tables` as t where t.TABLE_SCHEMA = :__vtschemaname /* VARCHAR */", + "SysTableTableSchema": "[VARCHAR(\"a\")]", + "Table": "information_schema.`tables`" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select TABLE_NAME from information_schema.`columns` where 1 != 1", + "Query": "select distinct TABLE_NAME from information_schema.`columns`", + "Table": "information_schema.`columns`" } ] } diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.json b/go/vt/vtgate/planbuilder/testdata/select_cases.json index 8542400102f..12f3ee7f112 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.json @@ -2477,37 +2477,29 @@ "QueryType": "SELECT", "Original": "select found from (select id as found from user union all (select id from unsharded)) as t", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id as found from `user` where 1 != 1", - "Query": "select id as found from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select id from unsharded where 1 != 1", - "Query": "select id from unsharded", - "Table": "unsharded" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id as found from `user` where 1 != 1", + "Query": "select id as found from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select id from unsharded where 1 != 1", + "Query": "select id from unsharded", + "Table": "unsharded" } ] }, diff --git a/go/vt/vtgate/planbuilder/testdata/tpch_cases.json b/go/vt/vtgate/planbuilder/testdata/tpch_cases.json index 14482b7f78a..561cc437956 100644 --- a/go/vt/vtgate/planbuilder/testdata/tpch_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/tpch_cases.json @@ -746,12 +746,12 @@ { "comment": "TPC-H query 8", "query": "select o_year, sum(case when nation = 'BRAZIL' then volume else 0 end) / sum(volume) as mkt_share from ( select extract(year from o_orderdate) as o_year, l_extendedprice * (1 - l_discount) as volume, n2.n_name as nation from part, supplier, lineitem, orders, customer, nation n1, nation n2, region where p_partkey = l_partkey and s_suppkey = l_suppkey and l_orderkey = o_orderkey and o_custkey = c_custkey and c_nationkey = n1.n_nationkey and n1.n_regionkey = r_regionkey and r_name = 'AMERICA' and s_nationkey = n2.n_nationkey and o_orderdate between date '1995-01-01' and date('1996-12-31') and p_type = 'ECONOMY ANODIZED STEEL' ) as all_nations group by o_year order by o_year", - "plan": "VT12001: unsupported: failed to plan aggregation on: sum(case when nation = 'BRAZIL' then volume else 0 end)" + "plan": "VT13002: unexpected AST struct for query: o_year" }, { "comment": "TPC-H query 9", "query": "select nation, o_year, sum(amount) as sum_profit from ( select n_name as nation, extract(year from o_orderdate) as o_year, l_extendedprice * (1 - l_discount) - ps_supplycost * l_quantity as amount from part, supplier, lineitem, partsupp, orders, nation where s_suppkey = l_suppkey and ps_suppkey = l_suppkey and ps_partkey = l_partkey and p_partkey = l_partkey and o_orderkey = l_orderkey and s_nationkey = n_nationkey and p_name like '%green%' ) as profit group by nation, o_year order by nation, o_year desc", - "plan": "VT12001: unsupported: failed to plan aggregation on: sum(amount) as sum_profit" + "plan": "VT13002: unexpected AST struct for query: nation" }, { "comment": "TPC-H query 10", diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 6239693fde9..18218b63077 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -87,49 +87,41 @@ "QueryType": "SELECT", "Original": "(SELECT id FROM user ORDER BY id DESC LIMIT 1) UNION ALL (SELECT id FROM music ORDER BY id DESC LIMIT 1)", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Limit", + "Count": "INT64(1)", "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(1)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", - "Table": "`user`" - } - ] - }, + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", + "Table": "`user`" + } + ] + }, + { + "OperatorType": "Limit", + "Count": "INT64(1)", + "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(1)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from music where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", - "Table": "music" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from music where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", + "Table": "music" } ] } @@ -217,49 +209,41 @@ "QueryType": "SELECT", "Original": "(select id from user order by id limit 5) union all (select id from music order by id desc limit 5)", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Limit", + "Count": "INT64(5)", "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(5)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) ASC", - "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", - "Table": "`user`" - } - ] - }, + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) ASC", + "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", + "Table": "`user`" + } + ] + }, + { + "OperatorType": "Limit", + "Count": "INT64(5)", + "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(5)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from music where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", - "Table": "music" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from music where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", + "Table": "music" } ] } @@ -1144,51 +1128,43 @@ "QueryType": "SELECT", "Original": "select * from (select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select kcu.`COLUMN_NAME` from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `COLUMN_NAME` = 'primary'", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Filter", + "Predicate": "COLUMN_NAME = 'primary'", "Inputs": [ { - "OperatorType": "Filter", - "Predicate": "COLUMN_NAME = 'primary'", + "OperatorType": "Distinct", + "Collations": [ + "0: utf8mb4_0900_ai_ci" + ], "Inputs": [ { - "OperatorType": "Distinct", - "Collations": [ - "0: utf8mb4_0900_ai_ci" - ], + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select kcu.COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", - "Query": "select distinct kcu.COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name /* VARCHAR */", - "SysTableTableName": "[kcu_table_name:VARCHAR(\"user_extra\")]", - "SysTableTableSchema": "[VARCHAR(\"user\")]", - "Table": "information_schema.key_column_usage" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select kcu.COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", - "Query": "select distinct kcu.COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name1 /* VARCHAR */", - "SysTableTableName": "[kcu_table_name1:VARCHAR(\"music\")]", - "SysTableTableSchema": "[VARCHAR(\"user\")]", - "Table": "information_schema.key_column_usage" - } - ] + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select kcu.COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", + "Query": "select distinct kcu.COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name /* VARCHAR */", + "SysTableTableName": "[kcu_table_name:VARCHAR(\"user_extra\")]", + "SysTableTableSchema": "[VARCHAR(\"user\")]", + "Table": "information_schema.key_column_usage" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select kcu.COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", + "Query": "select distinct kcu.COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name1 /* VARCHAR */", + "SysTableTableName": "[kcu_table_name1:VARCHAR(\"music\")]", + "SysTableTableSchema": "[VARCHAR(\"user\")]", + "Table": "information_schema.key_column_usage" } ] } @@ -1232,73 +1208,54 @@ "QueryType": "SELECT", "Original": "select * from (select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'user_extra' union select * from `information_schema`.`key_column_usage` `kcu` where `kcu`.`table_schema` = 'user' and `kcu`.`table_name` = 'music') `kcu` where `constraint_name` = 'primary'", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11 - ], + "OperatorType": "Filter", + "Predicate": "constraint_name = 'primary'", "Inputs": [ { - "OperatorType": "Filter", - "Predicate": "constraint_name = 'primary'", + "OperatorType": "Distinct", + "Collations": [ + "0: utf8mb4_0900_ai_ci", + "1: utf8mb4_0900_ai_ci", + "2: utf8mb4_0900_ai_ci", + "3: utf8mb4_0900_ai_ci", + "4: utf8mb4_0900_ai_ci", + "5: utf8mb4_0900_ai_ci", + "6: utf8mb4_0900_ai_ci", + "7", + "8", + "9: utf8mb4_0900_ai_ci", + "10: utf8mb4_0900_ai_ci", + "11: utf8mb4_0900_ai_ci" + ], "Inputs": [ { - "OperatorType": "Distinct", - "Collations": [ - "0: utf8mb4_0900_ai_ci", - "1: utf8mb4_0900_ai_ci", - "2: utf8mb4_0900_ai_ci", - "3: utf8mb4_0900_ai_ci", - "4: utf8mb4_0900_ai_ci", - "5: utf8mb4_0900_ai_ci", - "6: utf8mb4_0900_ai_ci", - "7", - "8", - "9: utf8mb4_0900_ai_ci", - "10: utf8mb4_0900_ai_ci", - "11: utf8mb4_0900_ai_ci" - ], + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", - "Query": "select distinct kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name /* VARCHAR */", - "SysTableTableName": "[kcu_table_name:VARCHAR(\"user_extra\")]", - "SysTableTableSchema": "[VARCHAR(\"user\")]", - "Table": "information_schema.key_column_usage" - }, - { - "OperatorType": "Route", - "Variant": "DBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", - "Query": "select distinct kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name1 /* VARCHAR */", - "SysTableTableName": "[kcu_table_name1:VARCHAR(\"music\")]", - "SysTableTableSchema": "[VARCHAR(\"user\")]", - "Table": "information_schema.key_column_usage" - } - ] + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", + "Query": "select distinct kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name /* VARCHAR */", + "SysTableTableName": "[kcu_table_name:VARCHAR(\"user_extra\")]", + "SysTableTableSchema": "[VARCHAR(\"user\")]", + "Table": "information_schema.key_column_usage" + }, + { + "OperatorType": "Route", + "Variant": "DBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where 1 != 1", + "Query": "select distinct kcu.CONSTRAINT_CATALOG, kcu.CONSTRAINT_SCHEMA, kcu.CONSTRAINT_NAME, kcu.TABLE_CATALOG, kcu.TABLE_SCHEMA, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.ORDINAL_POSITION, kcu.POSITION_IN_UNIQUE_CONSTRAINT, kcu.REFERENCED_TABLE_SCHEMA, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME from information_schema.key_column_usage as kcu where kcu.table_schema = :__vtschemaname /* VARCHAR */ and kcu.table_name = :kcu_table_name1 /* VARCHAR */", + "SysTableTableName": "[kcu_table_name1:VARCHAR(\"music\")]", + "SysTableTableSchema": "[VARCHAR(\"user\")]", + "Table": "information_schema.key_column_usage" } ] } diff --git a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json index b500b993041..700cbbe6dd5 100644 --- a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json @@ -469,10 +469,5 @@ "comment": "extremum on input from both sides", "query": "insert into music(user_id, id) select foo, bar from music on duplicate key update id = id+1", "plan": "VT12001: unsupported: DML cannot update vindex column" - }, - { - "comment": "aggregation on top of aggregation not supported", - "query": "select distinct count(*) from user, (select distinct count(*) from user) X", - "plan": "VT12001: unsupported: failed to plan aggregation on: count(*)" } ] From 55c37383d309b646e92ad929d576f9211e27e914 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Wed, 2 Aug 2023 17:08:58 +0530 Subject: [PATCH 24/44] distinct to send columns at once to source for AddColumns, route to add only not available columns below and use reuse bool for adding them Signed-off-by: Harshit Gangal --- .../planbuilder/operators/aggregator.go | 2 +- .../vtgate/planbuilder/operators/distinct.go | 44 ++++++++------ .../planbuilder/operators/projection.go | 17 ++++-- go/vt/vtgate/planbuilder/operators/route.go | 46 +++++++++----- .../testdata/postprocess_cases.json | 58 +----------------- .../planbuilder/testdata/union_cases.json | 60 ++++++------------- 6 files changed, 90 insertions(+), 137 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/aggregator.go b/go/vt/vtgate/planbuilder/operators/aggregator.go index 0507c719e27..40504fb18d6 100644 --- a/go/vt/vtgate/planbuilder/operators/aggregator.go +++ b/go/vt/vtgate/planbuilder/operators/aggregator.go @@ -113,7 +113,7 @@ func (a *Aggregator) addColumnWithoutPushing(expr *sqlparser.AliasedExpr, addToG return offset } -func (a *Aggregator) addColumnsWithoutPushing(expr []*sqlparser.AliasedExpr, groupby []bool) (offsets []int) { +func (a *Aggregator) addColumnsWithoutPushing(ctx *plancontext.PlanningContext, reuse bool, groupby []bool, expr []*sqlparser.AliasedExpr) (offsets []int) { for i, ae := range expr { offsets = append(offsets, a.addColumnWithoutPushing(ae, groupby[i])) } diff --git a/go/vt/vtgate/planbuilder/operators/distinct.go b/go/vt/vtgate/planbuilder/operators/distinct.go index 31eb925bd82..0a0f0293fc0 100644 --- a/go/vt/vtgate/planbuilder/operators/distinct.go +++ b/go/vt/vtgate/planbuilder/operators/distinct.go @@ -19,7 +19,9 @@ package operators import ( "golang.org/x/exp/slices" + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" @@ -51,31 +53,39 @@ func (d *Distinct) planOffsets(ctx *plancontext.PlanningContext) error { if err != nil { return err } - d.Columns = nil - var exprs []sqlparser.Expr - for _, col := range columns { - offsets, err := d.Source.AddColumns(ctx, true, []bool{false}, []*sqlparser.AliasedExpr{col}) - if err != nil { - return err - } + var colExprs []*sqlparser.AliasedExpr + var wsExprs []*sqlparser.AliasedExpr + var wsCol []int + var addToGroupBy []bool + for i, col := range columns { + colExprs = append(colExprs, col) + addToGroupBy = append(addToGroupBy, false) e := d.QP.GetSimplifiedExpr(col.Expr) - exprs = append(exprs, e) - typ, coll, _ := ctx.SemTable.TypeForExpr(e) + typ, coll, found := ctx.SemTable.TypeForExpr(e) + if !found { + wsExprs = append(wsExprs, aeWrap(weightStringFor(e))) + addToGroupBy = append(addToGroupBy, false) + wsCol = append(wsCol, i) + } d.Columns = append(d.Columns, engine.CheckCol{ - Col: offsets[0], + Col: i, Type: typ, Collation: coll, }) } - for i, e := range exprs { - if !ctx.SemTable.NeedsWeightString(e) { - continue + offsets, err := d.Source.AddColumns(ctx, true, addToGroupBy, append(colExprs, wsExprs...)) + if err != nil { + return err + } + n := len(columns) + for i, offset := range offsets { + if i < n && i != offset { + return vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "unable to plan DISTINCT operation") } - offsets, err := d.Source.AddColumns(ctx, true, []bool{false}, []*sqlparser.AliasedExpr{aeWrap(weightStringFor(e))}) - if err != nil { - return err + if i >= n { + var wsOffset = offset + d.Columns[wsCol[i-n]].WsCol = &wsOffset } - d.Columns[i].WsCol = &offsets[0] } return nil } diff --git a/go/vt/vtgate/planbuilder/operators/projection.go b/go/vt/vtgate/planbuilder/operators/projection.go index a7c88a30200..13b822728df 100644 --- a/go/vt/vtgate/planbuilder/operators/projection.go +++ b/go/vt/vtgate/planbuilder/operators/projection.go @@ -118,10 +118,19 @@ func (p *Projection) addColumnWithoutPushing(expr *sqlparser.AliasedExpr, _ bool return p.addUnexploredExpr(expr, expr.Expr) } -func (p *Projection) addColumnsWithoutPushing(expr []*sqlparser.AliasedExpr, _ []bool) []int { - return slice.Map(expr, func(ae *sqlparser.AliasedExpr) int { - return p.addUnexploredExpr(ae, ae.Expr) - }) +func (p *Projection) addColumnsWithoutPushing(ctx *plancontext.PlanningContext, reuse bool, _ []bool, exprs []*sqlparser.AliasedExpr) []int { + offsets := make([]int, len(exprs)) + for idx, expr := range exprs { + if reuse { + offset, _ := p.FindCol(ctx, expr.Expr, true) + if offset != -1 { + offsets[idx] = offset + continue + } + } + offsets[idx] = p.addUnexploredExpr(expr, expr.Expr) + } + return offsets } func (p *Projection) isDerived() bool { diff --git a/go/vt/vtgate/planbuilder/operators/route.go b/go/vt/vtgate/planbuilder/operators/route.go index 8fb951e4df1..b41575794d7 100644 --- a/go/vt/vtgate/planbuilder/operators/route.go +++ b/go/vt/vtgate/planbuilder/operators/route.go @@ -545,7 +545,8 @@ func createProjection(ctx *plancontext.PlanningContext, src ops.Operator) (*Proj func (r *Route) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addToGroupBy []bool, exprs []*sqlparser.AliasedExpr) ([]int, error) { offsets := make([]int, len(exprs)) - notFound := false + var notFoundExprs []*sqlparser.AliasedExpr + var pendingOffsetIdx []int for idx, expr := range exprs { removeKeyspaceFromSelectExpr(expr) @@ -559,19 +560,24 @@ func (r *Route) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addToGr continue } } - notFound = true + notFoundExprs = append(notFoundExprs, expr) + pendingOffsetIdx = append(pendingOffsetIdx, idx) } - if !notFound { + if len(notFoundExprs) == 0 { // we were able to find all columns, so we don't need to fetch anything else return offsets, nil } // if at least one column is not already present, we check if we can easily find a projection // or aggregation in our source that we can add to - if op, ok, offset := addMultipleColumnsToInput(ctx, r.Source, reuse, addToGroupBy, exprs); ok { - r.Source = op - return offset, nil + op, ok, remainingOffsets := addMultipleColumnsToInput(ctx, r.Source, reuse, addToGroupBy, notFoundExprs) + r.Source = op + if ok { + for i, offsetIdx := range pendingOffsetIdx { + offsets[offsetIdx] = remainingOffsets[i] + } + return offsets, nil } // If no-one could be found, we probably don't have one yet, so we add one here @@ -581,36 +587,43 @@ func (r *Route) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addToGr } r.Source = src - return src.addColumnsWithoutPushing(exprs, addToGroupBy), nil + return src.addColumnsWithoutPushing(ctx, reuse, addToGroupBy, exprs), nil } type selectExpressions interface { ops.Operator addColumnWithoutPushing(expr *sqlparser.AliasedExpr, addToGroupBy bool) int - addColumnsWithoutPushing(expr []*sqlparser.AliasedExpr, addToGroupBy []bool) []int + addColumnsWithoutPushing(ctx *plancontext.PlanningContext, reuse bool, addToGroupBy []bool, exprs []*sqlparser.AliasedExpr) []int isDerived() bool } // addColumnToInput adds a column to an operator without pushing it down. // It will return a bool indicating whether the addition was succesful or not, and an offset to where the column can be found -func addMultipleColumnsToInput(ctx *plancontext.PlanningContext, operator ops.Operator, reuse bool, addToGroupBy []bool, expr []*sqlparser.AliasedExpr) (ops.Operator, bool, []int) { +func addMultipleColumnsToInput(ctx *plancontext.PlanningContext, operator ops.Operator, reuse bool, addToGroupBy []bool, exprs []*sqlparser.AliasedExpr) (ops.Operator, bool, []int) { switch op := operator.(type) { case *CorrelatedSubQueryOp: - src, added, offset := addMultipleColumnsToInput(ctx, op.Outer, reuse, addToGroupBy, expr) + src, added, offset := addMultipleColumnsToInput(ctx, op.Outer, reuse, addToGroupBy, exprs) if added { op.Outer = src } return op, added, offset + case *Distinct: + src, added, offset := addMultipleColumnsToInput(ctx, op.Source, reuse, addToGroupBy, exprs) + if added { + op.Source = src + } + return op, added, offset + case *Limit: - src, added, offset := addMultipleColumnsToInput(ctx, op.Source, reuse, addToGroupBy, expr) + src, added, offset := addMultipleColumnsToInput(ctx, op.Source, reuse, addToGroupBy, exprs) if added { op.Source = src } return op, added, offset case *Ordering: - src, added, offset := addMultipleColumnsToInput(ctx, op.Source, reuse, addToGroupBy, expr) + src, added, offset := addMultipleColumnsToInput(ctx, op.Source, reuse, addToGroupBy, exprs) if added { op.Source = src } @@ -622,22 +635,23 @@ func addMultipleColumnsToInput(ctx *plancontext.PlanningContext, operator ops.Op // we have to add a new projection and can't build on this one return op, false, nil } - offset := op.addColumnsWithoutPushing(expr, addToGroupBy) + offset := op.addColumnsWithoutPushing(ctx, reuse, addToGroupBy, exprs) return op, true, offset case *Union: tableID := semantics.SingleTableSet(len(ctx.SemTable.Tables)) ctx.SemTable.Tables = append(ctx.SemTable.Tables, nil) unionColumns, err := op.GetColumns(ctx) if err != nil { - return nil, false, nil + return op, false, nil } - return &Projection{ + proj := &Projection{ Source: op, Columns: unionColumns, Projections: nil, TableID: &tableID, Alias: "dt", - }, true, []int{len(op.unionColumns)} + } + return addMultipleColumnsToInput(ctx, proj, reuse, addToGroupBy, exprs) default: return op, false, nil } diff --git a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json index 8e9270d1f6a..91ef5b755aa 100644 --- a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json @@ -1748,66 +1748,12 @@ { "comment": "Distinct with column alias", "query": "select distinct a as c, a from user", - "plan": { - "QueryType": "SELECT", - "Original": "select distinct a as c, a from user", - "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "(0:2)", - "(0:2)" - ], - "ResultColumns": 2, - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select a as c, a, weight_string(a) from `user` where 1 != 1", - "Query": "select distinct a as c, a, weight_string(a) from `user`", - "Table": "`user`" - } - ] - }, - "TablesUsed": [ - "user.user" - ] - } + "plan": "unable to plan DISTINCT operation" }, { "comment": "Distinct with same column", "query": "select distinct a, a from user", - "plan": { - "QueryType": "SELECT", - "Original": "select distinct a, a from user", - "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "(0:2)", - "(0:2)" - ], - "ResultColumns": 2, - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select a, a, weight_string(a) from `user` where 1 != 1", - "Query": "select distinct a, a, weight_string(a) from `user`", - "Table": "`user`" - } - ] - }, - "TablesUsed": [ - "user.user" - ] - } + "plan": "unable to plan DISTINCT operation" }, { "comment": "Order by has subqueries", diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 18218b63077..1126d080fd8 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -42,8 +42,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id from (select id from `user` where 1 != 1 union select id from music where 1 != 1) as dt where 1 != 1", - "Query": "select id from (select id from `user` union select id from music) as dt", + "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select id from music where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id) from (select id from `user` union select id from music) as dt", "Table": "`user`, music" } ] @@ -444,8 +444,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id from ((select id from `user` where 1 != 1) union (select id from `user` where 1 != 1)) as dt where 1 != 1", - "Query": "select id from ((select id from `user` order by id desc) union (select id from `user` order by id asc)) as dt", + "FieldQuery": "select id, weight_string(id) from ((select id from `user` where 1 != 1) union (select id from `user` where 1 != 1)) as dt where 1 != 1", + "Query": "select id, weight_string(id) from ((select id from `user` order by id desc) union (select id from `user` order by id asc)) as dt", "Table": "`user`" } ] @@ -811,8 +811,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt where 1 != 1", - "Query": "select id from (select id from `user` union select 3 from dual) as dt limit :__upper_limit", + "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id) from (select id from `user` union select 3 from dual limit :__upper_limit) as dt", "Table": "`user`, dual" } ] @@ -1033,11 +1033,14 @@ "Instructions": { "OperatorType": "Sort", "Variant": "Memory", - "OrderBy": "(0|1) ASC", + "OrderBy": "0 ASC", "ResultColumns": 1, "Inputs": [ { "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], "Inputs": [ { "OperatorType": "Route", @@ -1046,8 +1049,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt where 1 != 1", - "Query": "select id from (select id from `user` union select 3 from dual) as dt", + "FieldQuery": "select weight_string(id), weight_string(weight_string(id)) from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt where 1 != 1", + "Query": "select weight_string(id), weight_string(weight_string(id)) from (select id from `user` union select 3 from dual) as dt", "Table": "`user`, dual" } ] @@ -1406,36 +1409,7 @@ { "comment": "UNION with repeating column on the LHS", "query": "select foo, foo, foo from user union select bar, baz, toto from music", - "plan": { - "QueryType": "SELECT", - "Original": "select foo, foo, foo from user union select bar, baz, toto from music", - "Instructions": { - "OperatorType": "Distinct", - "Collations": [ - "(0:3)", - "(0:0)", - "(0:0)" - ], - "ResultColumns": 3, - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select weight_string(foo) from (select foo, foo, foo from `user` where 1 != 1 union select bar, baz, toto from music where 1 != 1) as dt where 1 != 1", - "Query": "select weight_string(foo) from (select foo, foo, foo from `user` union select bar, baz, toto from music) as dt", - "Table": "`user`, music" - } - ] - }, - "TablesUsed": [ - "user.music", - "user.user" - ] - } + "plan": "unable to plan DISTINCT operation" }, { "comment": "UNION with repeating column on the RHS", @@ -1447,8 +1421,8 @@ "OperatorType": "Distinct", "Collations": [ "(0:3)", - "(1:0)", - "(2:1)" + "(1:4)", + "(2:5)" ], "ResultColumns": 3, "Inputs": [ @@ -1459,8 +1433,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select weight_string(baz), weight_string(toto) from (select bar, baz, toto from music where 1 != 1 union select foo, foo, foo from `user` where 1 != 1) as dt where 1 != 1", - "Query": "select weight_string(baz), weight_string(toto) from (select bar, baz, toto from music union select foo, foo, foo from `user`) as dt", + "FieldQuery": "select bar, baz, toto, weight_string(bar), weight_string(baz), weight_string(toto) from (select bar, baz, toto from music where 1 != 1 union select foo, foo, foo from `user` where 1 != 1) as dt where 1 != 1", + "Query": "select bar, baz, toto, weight_string(bar), weight_string(baz), weight_string(toto) from (select bar, baz, toto from music union select foo, foo, foo from `user`) as dt", "Table": "`user`, music" } ] From 054f78f8a371844ac8719251fd3f4eb9b50f4850 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Wed, 2 Aug 2023 17:49:46 +0530 Subject: [PATCH 25/44] add truncation logic to filter Signed-off-by: Harshit Gangal --- go/vt/vtgate/engine/filter.go | 15 ++++++++------- go/vt/vtgate/planbuilder/operator_transformers.go | 1 + go/vt/vtgate/planbuilder/operators/filter.go | 7 +++++++ go/vt/vtgate/planbuilder/testdata/aggr_cases.json | 10 +++++++++- .../vtgate/planbuilder/testdata/filter_cases.json | 1 + 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/go/vt/vtgate/engine/filter.go b/go/vt/vtgate/engine/filter.go index bab94335e67..5db312a9bd3 100644 --- a/go/vt/vtgate/engine/filter.go +++ b/go/vt/vtgate/engine/filter.go @@ -19,12 +19,10 @@ package engine import ( "context" - "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vtgate/evalengine" - "vitess.io/vitess/go/sqltypes" - querypb "vitess.io/vitess/go/vt/proto/query" + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vtgate/evalengine" ) var _ Primitive = (*Filter)(nil) @@ -35,6 +33,8 @@ type Filter struct { ASTPredicate sqlparser.Expr Input Primitive + Truncate int + noTxNeeded } @@ -73,7 +73,7 @@ func (f *Filter) TryExecute(ctx context.Context, vcursor VCursor, bindVars map[s } } result.Rows = rows - return result, nil + return result.Truncate(f.Truncate), nil } // TryStreamExecute satisfies the Primitive interface. @@ -96,7 +96,7 @@ func (f *Filter) TryStreamExecute(ctx context.Context, vcursor VCursor, bindVars } } results.Rows = rows - return callback(results) + return callback(results.Truncate(f.Truncate)) } return vcursor.StreamExecutePrimitive(ctx, f.Input, bindVars, wantfields, filter) @@ -114,7 +114,8 @@ func (f *Filter) Inputs() []Primitive { func (f *Filter) description() PrimitiveDescription { other := map[string]any{ - "Predicate": sqlparser.String(f.ASTPredicate), + "Predicate": sqlparser.String(f.ASTPredicate), + "ResultColumns": f.Truncate, } return PrimitiveDescription{ diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index df40770daf3..72e5967fc70 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -257,6 +257,7 @@ func transformFilter(ctx *plancontext.PlanningContext, op *operators.Filter) (lo efilter: &engine.Filter{ Predicate: predicate, ASTPredicate: ast, + Truncate: op.Truncate, }, }, nil } diff --git a/go/vt/vtgate/planbuilder/operators/filter.go b/go/vt/vtgate/planbuilder/operators/filter.go index 378475c21ab..d48125da991 100644 --- a/go/vt/vtgate/planbuilder/operators/filter.go +++ b/go/vt/vtgate/planbuilder/operators/filter.go @@ -38,6 +38,8 @@ type Filter struct { // FinalPredicate is the evalengine expression that will finally be used. // It contains the ANDed predicates in Predicates, with ColName:s replaced by Offset:s FinalPredicate evalengine.Expr + + Truncate int } func newFilter(op ops.Operator, expr sqlparser.Expr) ops.Operator { @@ -52,6 +54,7 @@ func (f *Filter) Clone(inputs []ops.Operator) ops.Operator { Source: inputs[0], Predicates: slices.Clone(f.Predicates), FinalPredicate: f.FinalPredicate, + Truncate: f.Truncate, } } @@ -147,3 +150,7 @@ func (f *Filter) planOffsets(ctx *plancontext.PlanningContext) error { func (f *Filter) ShortDescription() string { return sqlparser.String(sqlparser.AndExpressions(f.Predicates...)) } + +func (f *Filter) setTruncateColumnCount(offset int) { + f.Truncate = offset +} diff --git a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json index aa9df5594e8..7d1fe92f46d 100644 --- a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json @@ -2056,6 +2056,7 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "count(*) = 1.00", + "ResultColumns": 2, "Inputs": [ { "OperatorType": "Aggregate", @@ -2124,6 +2125,7 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "count(id) = 10", + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Aggregate", @@ -2245,6 +2247,7 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "count(id) = 10", + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Aggregate", @@ -2919,6 +2922,7 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "count(*) = 3", + "ResultColumns": 2, "Inputs": [ { "OperatorType": "Aggregate", @@ -2956,6 +2960,7 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "sum(foo) + sum(bar) = 42", + "ResultColumns": 3, "Inputs": [ { "OperatorType": "Aggregate", @@ -2993,6 +2998,7 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "sum(foo) + sum(bar) = 42", + "ResultColumns": 3, "Inputs": [ { "OperatorType": "Aggregate", @@ -3030,6 +3036,7 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "count(*) = 3", + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Aggregate", @@ -3067,6 +3074,7 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "count(u.`name`) = 3", + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Aggregate", @@ -3170,6 +3178,7 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "count(*) < 3 and count(*) > 5", + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Aggregate", @@ -5943,5 +5952,4 @@ ] } } - ] diff --git a/go/vt/vtgate/planbuilder/testdata/filter_cases.json b/go/vt/vtgate/planbuilder/testdata/filter_cases.json index 244cfdd1c8e..251fb300704 100644 --- a/go/vt/vtgate/planbuilder/testdata/filter_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/filter_cases.json @@ -4115,6 +4115,7 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "repeat(a.textcol1, sum(a.id)) like 'And%res'", + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Aggregate", From b9278d29f576e73c58bf5264890b62412096f26a Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Wed, 2 Aug 2023 17:53:50 +0530 Subject: [PATCH 26/44] fix the test expectation Signed-off-by: Harshit Gangal --- go/vt/vtgate/planbuilder/collations_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/go/vt/vtgate/planbuilder/collations_test.go b/go/vt/vtgate/planbuilder/collations_test.go index 2a7ffebf91c..8919a720744 100644 --- a/go/vt/vtgate/planbuilder/collations_test.go +++ b/go/vt/vtgate/planbuilder/collations_test.go @@ -81,9 +81,9 @@ func TestOrderedAggregateCollations(t *testing.T) { collations: []collationInTable{{ks: "user", table: "user", collationName: "utf8mb4_bin", colName: "textcol1"}}, query: "select distinct textcol1 from user", check: func(t *testing.T, colls []collationInTable, primitive engine.Primitive) { - oa, isOA := primitive.(*engine.OrderedAggregate) - require.True(t, isOA, "should be an OrderedAggregate") - require.Equal(t, collid(colls[0].collationName), oa.GroupByKeys[0].CollationID) + distinct, isDistinct := primitive.(*engine.Distinct) + require.True(t, isDistinct, "should be a distinct") + require.Equal(t, collid(colls[0].collationName), distinct.CheckCols[0].Collation) }, }, { From f5dd14b96708fa65f6a0013619cfc1978bf1d9cc Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Wed, 2 Aug 2023 17:58:03 +0530 Subject: [PATCH 27/44] update sizegen Signed-off-by: Harshit Gangal --- go/vt/vtgate/engine/cached_size.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/vt/vtgate/engine/cached_size.go b/go/vt/vtgate/engine/cached_size.go index 132081aeae5..f863e268632 100644 --- a/go/vt/vtgate/engine/cached_size.go +++ b/go/vt/vtgate/engine/cached_size.go @@ -233,7 +233,7 @@ func (cached *Filter) CachedSize(alloc bool) int64 { } size := int64(0) if alloc { - size += int64(48) + size += int64(64) } // field Predicate vitess.io/vitess/go/vt/vtgate/evalengine.Expr if cc, ok := cached.Predicate.(cachedObject); ok { From b173f8c122ada54ce9557224fe0e87b9ceee3142 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Wed, 2 Aug 2023 18:19:48 +0530 Subject: [PATCH 28/44] improve distinct planning to only reject when columns do not align Signed-off-by: Harshit Gangal --- .../vtgate/planbuilder/operators/distinct.go | 45 +++++++------- .../testdata/postprocess_cases.json | 58 ++++++++++++++++++- .../planbuilder/testdata/union_cases.json | 2 +- 3 files changed, 81 insertions(+), 24 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/distinct.go b/go/vt/vtgate/planbuilder/operators/distinct.go index 0a0f0293fc0..d9caa84b3a7 100644 --- a/go/vt/vtgate/planbuilder/operators/distinct.go +++ b/go/vt/vtgate/planbuilder/operators/distinct.go @@ -19,7 +19,6 @@ package operators import ( "golang.org/x/exp/slices" - vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" @@ -53,39 +52,43 @@ func (d *Distinct) planOffsets(ctx *plancontext.PlanningContext) error { if err != nil { return err } - var colExprs []*sqlparser.AliasedExpr var wsExprs []*sqlparser.AliasedExpr - var wsCol []int var addToGroupBy []bool - for i, col := range columns { - colExprs = append(colExprs, col) + for _, col := range columns { addToGroupBy = append(addToGroupBy, false) e := d.QP.GetSimplifiedExpr(col.Expr) - typ, coll, found := ctx.SemTable.TypeForExpr(e) - if !found { + if ctx.SemTable.NeedsWeightString(e) { wsExprs = append(wsExprs, aeWrap(weightStringFor(e))) addToGroupBy = append(addToGroupBy, false) - wsCol = append(wsCol, i) } - d.Columns = append(d.Columns, engine.CheckCol{ - Col: i, - Type: typ, - Collation: coll, - }) } - offsets, err := d.Source.AddColumns(ctx, true, addToGroupBy, append(colExprs, wsExprs...)) + offsets, err := d.Source.AddColumns(ctx, true, addToGroupBy, append(columns, wsExprs...)) + if err != nil { + return err + } + modifiedCols, err := d.GetColumns(ctx) if err != nil { return err } + if len(modifiedCols) < len(columns) { + return vterrors.VT12001("unable to plan the distinct query as not able to align the columns") + } n := len(columns) - for i, offset := range offsets { - if i < n && i != offset { - return vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "unable to plan DISTINCT operation") - } - if i >= n { - var wsOffset = offset - d.Columns[wsCol[i-n]].WsCol = &wsOffset + wsOffset := 0 + for i, col := range columns { + e := d.QP.GetSimplifiedExpr(col.Expr) + typ, coll, found := ctx.SemTable.TypeForExpr(e) + var wsCol *int + if !found { + wsCol = &offsets[n+wsOffset] + wsOffset++ } + d.Columns = append(d.Columns, engine.CheckCol{ + Col: i, + WsCol: wsCol, + Type: typ, + Collation: coll, + }) } return nil } diff --git a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json index 91ef5b755aa..c40e99910e1 100644 --- a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json @@ -1748,12 +1748,66 @@ { "comment": "Distinct with column alias", "query": "select distinct a as c, a from user", - "plan": "unable to plan DISTINCT operation" + "plan": { + "QueryType": "SELECT", + "Original": "select distinct a as c, a from user", + "Instructions": { + "OperatorType": "Distinct", + "Collations": [ + "(0:2)", + "(1:2)" + ], + "ResultColumns": 2, + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select a as c, a, weight_string(a) from `user` where 1 != 1", + "Query": "select distinct a as c, a, weight_string(a) from `user`", + "Table": "`user`" + } + ] + }, + "TablesUsed": [ + "user.user" + ] + } }, { "comment": "Distinct with same column", "query": "select distinct a, a from user", - "plan": "unable to plan DISTINCT operation" + "plan": { + "QueryType": "SELECT", + "Original": "select distinct a, a from user", + "Instructions": { + "OperatorType": "Distinct", + "Collations": [ + "(0:2)", + "(1:2)" + ], + "ResultColumns": 2, + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select a, a, weight_string(a) from `user` where 1 != 1", + "Query": "select distinct a, a, weight_string(a) from `user`", + "Table": "`user`" + } + ] + }, + "TablesUsed": [ + "user.user" + ] + } }, { "comment": "Order by has subqueries", diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 1126d080fd8..e44f6d66a97 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -1409,7 +1409,7 @@ { "comment": "UNION with repeating column on the LHS", "query": "select foo, foo, foo from user union select bar, baz, toto from music", - "plan": "unable to plan DISTINCT operation" + "plan": "VT12001: unsupported: unable to plan the distinct query as not able to align the columns" }, { "comment": "UNION with repeating column on the RHS", From d37cc719f864eeefabbb7add86564595a8132f3b Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Wed, 2 Aug 2023 18:23:06 +0530 Subject: [PATCH 29/44] update executor union query test expectation Signed-off-by: Harshit Gangal --- go/vt/vtgate/executor_select_test.go | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index 39dc1d5105c..e2977f723de 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -2835,14 +2835,7 @@ func TestSelectWithUnionAll(t *testing.T) { bv1, _ := sqltypes.BuildBindVariable([]int64{1, 2}) bv2, _ := sqltypes.BuildBindVariable([]int64{3}) sbc1WantQueries := []*querypb.BoundQuery{{ - Sql: "select id from `user` where id in ::__vals", - BindVariables: map[string]*querypb.BindVariable{ - "__vals": bv1, - "vtg1": bv, - "vtg2": bv, - }, - }, { - Sql: "select id from `user` where id in ::__vals", + Sql: "select id from `user` where id in ::vtg1 union all select id from `user` where id in ::__vals", BindVariables: map[string]*querypb.BindVariable{ "__vals": bv1, "vtg1": bv, @@ -2850,14 +2843,7 @@ func TestSelectWithUnionAll(t *testing.T) { }, }} sbc2WantQueries := []*querypb.BoundQuery{{ - Sql: "select id from `user` where id in ::__vals", - BindVariables: map[string]*querypb.BindVariable{ - "__vals": bv2, - "vtg1": bv, - "vtg2": bv, - }, - }, { - Sql: "select id from `user` where id in ::__vals", + Sql: "select id from `user` where id in ::vtg1 union all select id from `user` where id in ::__vals", BindVariables: map[string]*querypb.BindVariable{ "__vals": bv2, "vtg1": bv, From edcbc4f7a6be714e424847bda9af180ce7dbd883 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Wed, 2 Aug 2023 20:43:58 +0530 Subject: [PATCH 30/44] fix compact and truncation order by reversing it and adding one more compact call Signed-off-by: Harshit Gangal --- go/test/endtoend/vtgate/gen4/gen4_test.go | 2 +- go/vt/vtgate/planbuilder/operators/horizon_planning.go | 10 +++++----- go/vt/vtgate/planbuilder/testdata/aggr_cases.json | 3 +++ go/vt/vtgate/planbuilder/testdata/filter_cases.json | 1 + go/vt/vtgate/planbuilder/testdata/from_cases.json | 2 ++ 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/go/test/endtoend/vtgate/gen4/gen4_test.go b/go/test/endtoend/vtgate/gen4/gen4_test.go index b84c5309726..fe26ef32829 100644 --- a/go/test/endtoend/vtgate/gen4/gen4_test.go +++ b/go/test/endtoend/vtgate/gen4/gen4_test.go @@ -164,7 +164,7 @@ func TestDistinct(t *testing.T) { utils.Exec(t, mcmp.VtConn, `insert into t2(id, tcol1, tcol2) values (1, 'A', 'A'),(2, 'B', 'C'),(3, 'A', 'C'),(4, 'C', 'A'),(5, 'A', 'A'),(6, 'B', 'C'),(7, 'B', 'A'),(8, 'C', 'A')`) // multi distinct - utils.AssertMatches(t, mcmp.VtConn, `select distinct tcol1, tcol2 from t2`, + utils.AssertMatchesNoOrder(t, mcmp.VtConn, `select distinct tcol1, tcol2 from t2`, `[[VARCHAR("A") VARCHAR("A")] [VARCHAR("A") VARCHAR("C")] [VARCHAR("B") VARCHAR("A")] [VARCHAR("B") VARCHAR("C")] [VARCHAR("C") VARCHAR("A")]]`) } diff --git a/go/vt/vtgate/planbuilder/operators/horizon_planning.go b/go/vt/vtgate/planbuilder/operators/horizon_planning.go index 494c17f7e67..62a46a29439 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_planning.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_planning.go @@ -82,17 +82,17 @@ func tryHorizonPlanning(ctx *plancontext.PlanningContext, root ops.Operator) (ou fmt.Println(ops.ToTree(output)) } - output, err = makeSureOutputIsCorrect(ctx, root, output) + output, err = compact(ctx, output) if err != nil { return nil, err } - output, err = compact(ctx, output) + output, err = addTruncationOrProjectionToReturnOutput(ctx, root, output) if err != nil { return nil, err } - return + return compact(ctx, output) } // planHorizons is the process of figuring out how to perform the operations in the Horizon @@ -703,8 +703,8 @@ func tryPushDownUnion(ctx *plancontext.PlanningContext, op *Union) (ops.Operator return newUnion(sources, selects, columns, op.distinct), rewrite.NewTree("merged union inputs", op), nil } -// makeSureOutputIsCorrect uses the original Horizon to make sure that the output columns line up with what the user asked for -func makeSureOutputIsCorrect(ctx *plancontext.PlanningContext, oldHorizon ops.Operator, output ops.Operator) (ops.Operator, error) { +// addTruncationOrProjectionToReturnOutput uses the original Horizon to make sure that the output columns line up with what the user asked for +func addTruncationOrProjectionToReturnOutput(ctx *plancontext.PlanningContext, oldHorizon ops.Operator, output ops.Operator) (ops.Operator, error) { cols, err := output.GetSelectExprs(ctx) if err != nil { return nil, err diff --git a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json index 7d1fe92f46d..f16039f56c4 100644 --- a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json @@ -3661,6 +3661,7 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "count(*) = 1", + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Aggregate", @@ -3992,6 +3993,7 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "bazo between 100 and 200", + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Aggregate", @@ -4029,6 +4031,7 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "bazo between 100 and 200", + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Aggregate", diff --git a/go/vt/vtgate/planbuilder/testdata/filter_cases.json b/go/vt/vtgate/planbuilder/testdata/filter_cases.json index 251fb300704..ba13e9f45ef 100644 --- a/go/vt/vtgate/planbuilder/testdata/filter_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/filter_cases.json @@ -3155,6 +3155,7 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "user_extra.id is null", + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Join", diff --git a/go/vt/vtgate/planbuilder/testdata/from_cases.json b/go/vt/vtgate/planbuilder/testdata/from_cases.json index e014b0c0b67..794dfb5543a 100644 --- a/go/vt/vtgate/planbuilder/testdata/from_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/from_cases.json @@ -3323,6 +3323,7 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "coalesce(user_extra.col, 4) = 5", + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Join", @@ -3880,6 +3881,7 @@ "Instructions": { "OperatorType": "Filter", "Predicate": "user_extra.col between 10 and 20", + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Join", From ddc049eb9078b84c8004f982fd731a44641d85c0 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Thu, 3 Aug 2023 11:08:23 +0530 Subject: [PATCH 31/44] merge sharded route on union only when both are scatter or both are equal unique with same vindex and value Signed-off-by: Harshit Gangal --- .../planbuilder/operators/union_merging.go | 49 +- .../testdata/large_union_cases.json | 999 +++++++++++++++++- .../planbuilder/testdata/union_cases.json | 147 ++- 3 files changed, 1141 insertions(+), 54 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/union_merging.go b/go/vt/vtgate/planbuilder/operators/union_merging.go index 83740ecff88..171c77e7298 100644 --- a/go/vt/vtgate/planbuilder/operators/union_merging.go +++ b/go/vt/vtgate/planbuilder/operators/union_merging.go @@ -18,6 +18,7 @@ package operators import ( "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vtgate/engine" "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" ) @@ -119,17 +120,29 @@ func mergeUnionInputs(ctx *plancontext.PlanningContext, lhs, rhs ops.Operator, l return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingA) case a == dual: return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB) - case a == anyShard && sameKeyspace: return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB) case b == anyShard && sameKeyspace: return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingA) - case a == sharded && b == sharded && sameKeyspace: - return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB) - default: - return nil, nil, nil + // If the two routes fully match, they can be merged together. + tblA := routingA.(*ShardedRouting) + tblB := routingB.(*ShardedRouting) + if tblA.RouteOpCode == engine.Scatter && tblB.RouteOpCode == engine.Scatter { + return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB) + } + if tblA.RouteOpCode != engine.EqualUnique || tblB.RouteOpCode != engine.EqualUnique { + break + } + aVdx := tblA.SelectedVindex() + bVdx := tblB.SelectedVindex() + aExpr := tblA.VindexExpressions() + bExpr := tblB.VindexExpressions() + if aVdx == bVdx && gen4ValuesEqual(ctx, aExpr, bExpr) { + return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB) + } } + return nil, nil, nil } func createMergedUnion( @@ -145,3 +158,29 @@ func createMergedUnion( Routing: routing, }, selectExprs, nil } + +/* + +func canMergeUnionPlans(ctx *plancontext.PlanningContext, a, b *route) bool { + // this method should be close to tryMerge below. it does the same thing, but on logicalPlans instead of queryTrees + if a.eroute.Keyspace.Name != b.eroute.Keyspace.Name { + return false + } + switch a.eroute.Opcode { + case engine.EqualUnique: + // Check if they target the same shard. + if b.eroute.Opcode == engine.EqualUnique && + a.eroute.Vindex == b.eroute.Vindex && + a.condition != nil && + b.condition != nil && + gen4ValuesEqual(ctx, []sqlparser.Expr{a.condition}, []sqlparser.Expr{b.condition}) { + return true + } + case engine.Scatter: + return b.eroute.Opcode == engine.Scatter + case engine.Next: + return false + } + return false +} +*/ diff --git a/go/vt/vtgate/planbuilder/testdata/large_union_cases.json b/go/vt/vtgate/planbuilder/testdata/large_union_cases.json index cc648220d27..bed4a521b82 100644 --- a/go/vt/vtgate/planbuilder/testdata/large_union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/large_union_cases.json @@ -6,19 +6,994 @@ "QueryType": "SELECT", "Original": "(SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270698330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270699497 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270703806 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270707364 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270714657 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270721330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270812079 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271011532 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271034164 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271034177 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271066849 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271098740 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271355000 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271924504 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272086055 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272127855 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272191137 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272468271 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270644941 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270650576 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270652906 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270660650 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270670201 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270698330 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270699497 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270707364 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271799956 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271799956 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270637436 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270644941 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270649256 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270653671 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270670201 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270717223 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270720898 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271346411 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271352121 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271354908 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271367516 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271472522 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271639345 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271821733 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271914117 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272068709 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272127855 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272191137 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272244005 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272468271 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1270982590 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271365691 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1271607757 ORDER BY created_at ASC, id ASC LIMIT 11) UNION (SELECT `content`, `user_id` FROM `music` WHERE `user_id` = 1272244005 ORDER BY created_at ASC, id ASC LIMIT 11)", "Instructions": { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "(select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1) union (select content, user_id from music where 1 != 1)", - "Query": "(select content, user_id from music where user_id = 1270698330 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270699497 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270703806 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270707364 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270714657 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270721330 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270812079 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271011532 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271034164 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271034177 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271066849 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271098740 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271355000 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271639345 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271914117 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271924504 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272086055 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272127855 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272191137 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272468271 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270637436 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270644941 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270650576 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270652906 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270660650 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270670201 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270698330 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270699497 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270707364 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271365691 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271799956 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271914117 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270637436 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271799956 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270637436 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271639345 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270644941 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270649256 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270653671 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270670201 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270717223 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270720898 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270982590 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271346411 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271352121 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271354908 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271365691 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271367516 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271472522 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271607757 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271639345 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271821733 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271914117 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272068709 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272127855 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272191137 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272244005 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272468271 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270982590 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271365691 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271607757 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1270982590 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271365691 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1271607757 order by created_at asc, id asc limit 11) union (select content, user_id from music where user_id = 1272244005 order by created_at asc, id asc limit 11)", - "Table": "music", - "Values": [ - "INT64(1272244005)" + "OperatorType": "Distinct", + "Collations": [ + "(0:2)", + "(1:3)" ], - "Vindex": "user_index" + "ResultColumns": 2, + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270698330 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270698330)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270699497 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270699497)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270703806 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270703806)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270707364 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270707364)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270714657 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270714657)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270721330 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270721330)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270812079 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270812079)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271011532 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271011532)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271034164 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271034164)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271034177 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271034177)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271066849 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271066849)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271098740 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271098740)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271355000 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271355000)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271639345 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271639345)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271914117 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271914117)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271924504 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271924504)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272086055 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272086055)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272127855 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272127855)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272191137 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272191137)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272468271 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272468271)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270637436 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270637436)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270644941 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270644941)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270650576 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270650576)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270652906 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270652906)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270660650 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270660650)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270670201 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270670201)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270698330 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270698330)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270699497 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270699497)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270707364 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270707364)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271365691)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271799956 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271799956)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271914117 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271914117)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270637436 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270637436)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271799956 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271799956)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270637436 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270637436)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271639345 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271639345)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270644941 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270644941)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270649256 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270649256)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270653671 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270653671)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270670201 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270670201)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270717223 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270717223)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270720898 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270720898)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270982590 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270982590)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271346411 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271346411)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271352121 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271352121)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271354908 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271354908)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271365691)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271367516 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271367516)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271472522 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271472522)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271607757 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271607757)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271639345 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271639345)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271821733 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271821733)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271914117 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271914117)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272068709 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272068709)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272127855 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272127855)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272191137 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272191137)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272244005 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272244005)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272468271 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272468271)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270982590 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270982590)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271365691)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271607757 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271607757)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1270982590 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1270982590)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271365691 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271365691)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1271607757 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1271607757)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select content, user_id, weight_string(content), weight_string(user_id) from music where 1 != 1", + "Query": "select distinct content, user_id, weight_string(content), weight_string(user_id) from music where user_id = 1272244005 order by created_at asc, id asc limit 11", + "Table": "music", + "Values": [ + "INT64(1272244005)" + ], + "Vindex": "user_index" + } + ] + } + ] }, "TablesUsed": [ "user.music" diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index e44f6d66a97..f98924eedca 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -61,19 +61,39 @@ "QueryType": "SELECT", "Original": "select id from user where id = 1 union all select id from user where id = 5", "Instructions": { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id from `user` where 1 != 1 union all select id from `user` where 1 != 1", - "Query": "select id from `user` where id = 1 union all select id from `user` where id = 5", - "Table": "`user`", - "Values": [ - "INT64(5)" - ], - "Vindex": "user_index" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from `user` where 1 != 1", + "Query": "select id from `user` where id = 1", + "Table": "`user`", + "Values": [ + "INT64(1)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from `user` where 1 != 1", + "Query": "select id from `user` where id = 5", + "Table": "`user`", + "Values": [ + "INT64(5)" + ], + "Vindex": "user_index" + } + ] }, "TablesUsed": [ "user.user" @@ -262,15 +282,35 @@ "QueryType": "SELECT", "Original": "select id from user where id = 1 union select id from user where id = 1 union all select id from user", "Instructions": { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id from `user` where 1 != 1 union select id from `user` where 1 != 1 union all select id from `user` where 1 != 1", - "Query": "select id from `user` where id = 1 union select id from `user` where id = 1 union all select id from `user`", - "Table": "`user`" + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from `user` where 1 != 1 union select id from `user` where 1 != 1", + "Query": "select id from `user` where id = 1 union select id from `user` where id = 1", + "Table": "`user`", + "Values": [ + "INT64(1)" + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from `user` where 1 != 1", + "Query": "select id from `user`", + "Table": "`user`" + } + ] }, "TablesUsed": [ "user.user" @@ -373,10 +413,10 @@ }, { "comment": "union with the same target shard because of vindex", - "query": "select * from music where id = 1 union select * from user where id = 1", + "query": "select * from music where user_id = 1 union select * from user where id = 1", "plan": { "QueryType": "SELECT", - "Original": "select * from music where id = 1 union select * from user where id = 1", + "Original": "select * from music where user_id = 1 union select * from user where id = 1", "Instructions": { "OperatorType": "Route", "Variant": "EqualUnique", @@ -385,7 +425,7 @@ "Sharded": true }, "FieldQuery": "select * from music where 1 != 1 union select * from `user` where 1 != 1", - "Query": "select * from music where id = 1 union select * from `user` where id = 1", + "Query": "select * from music where user_id = 1 union select * from `user` where id = 1", "Table": "`user`, music", "Values": [ "INT64(1)" @@ -398,6 +438,11 @@ ] } }, + { + "comment": "union with the different target shard because of vindex (music -> lookup vindex, user -> hash vindex)", + "query": "select * from music where id = 1 union select * from user where id = 1", + "plan": "VT09015: schema tracking required" + }, { "comment": "union with different target shards", "query": "select 1 from music where id = 1 union select 1 from music where id = 2", @@ -405,19 +450,47 @@ "QueryType": "SELECT", "Original": "select 1 from music where id = 1 union select 1 from music where id = 2", "Instructions": { - "OperatorType": "Route", - "Variant": "EqualUnique", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select 1 from music where 1 != 1 union select 1 from music where 1 != 1", - "Query": "select 1 from music where id = 1 union select 1 from music where id = 2", - "Table": "music", - "Values": [ - "INT64(2)" + "OperatorType": "Distinct", + "Collations": [ + "0" ], - "Vindex": "music_user_map" + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 1 from music where 1 != 1", + "Query": "select distinct 1 from music where id = 1", + "Table": "music", + "Values": [ + "INT64(1)" + ], + "Vindex": "music_user_map" + }, + { + "OperatorType": "Route", + "Variant": "EqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 1 from music where 1 != 1", + "Query": "select distinct 1 from music where id = 2", + "Table": "music", + "Values": [ + "INT64(2)" + ], + "Vindex": "music_user_map" + } + ] + } + ] }, "TablesUsed": [ "user.music" From 364d3ad93fee725a9295cb0699bfe9da0d5754ea Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Thu, 3 Aug 2023 14:38:26 +0530 Subject: [PATCH 32/44] fix unit test Signed-off-by: Harshit Gangal --- go/vt/vtgate/executor_select_test.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index e2977f723de..39dc1d5105c 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -2835,7 +2835,14 @@ func TestSelectWithUnionAll(t *testing.T) { bv1, _ := sqltypes.BuildBindVariable([]int64{1, 2}) bv2, _ := sqltypes.BuildBindVariable([]int64{3}) sbc1WantQueries := []*querypb.BoundQuery{{ - Sql: "select id from `user` where id in ::vtg1 union all select id from `user` where id in ::__vals", + Sql: "select id from `user` where id in ::__vals", + BindVariables: map[string]*querypb.BindVariable{ + "__vals": bv1, + "vtg1": bv, + "vtg2": bv, + }, + }, { + Sql: "select id from `user` where id in ::__vals", BindVariables: map[string]*querypb.BindVariable{ "__vals": bv1, "vtg1": bv, @@ -2843,7 +2850,14 @@ func TestSelectWithUnionAll(t *testing.T) { }, }} sbc2WantQueries := []*querypb.BoundQuery{{ - Sql: "select id from `user` where id in ::vtg1 union all select id from `user` where id in ::__vals", + Sql: "select id from `user` where id in ::__vals", + BindVariables: map[string]*querypb.BindVariable{ + "__vals": bv2, + "vtg1": bv, + "vtg2": bv, + }, + }, { + Sql: "select id from `user` where id in ::__vals", BindVariables: map[string]*querypb.BindVariable{ "__vals": bv2, "vtg1": bv, From 357d34918c70bf57c0fb26e111d36185480d5e28 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Fri, 4 Aug 2023 15:44:07 +0530 Subject: [PATCH 33/44] addressed review comments Signed-off-by: Harshit Gangal --- .../vtgate/queries/random/query_gen.go | 3 +- .../vtgate/queries/random/random_expr_test.go | 1 - go/vt/vtgate/engine/aggregations.go | 6 +- go/vt/vtgate/evalengine/compiler_asm.go | 9 +-- go/vt/vtgate/planbuilder/distinct.go | 8 --- .../planbuilder/operators/SQL_builder.go | 8 +-- go/vt/vtgate/planbuilder/operators/horizon.go | 10 --- .../operators/horizon_expanding.go | 7 +- .../planbuilder/operators/horizon_planning.go | 15 +--- go/vt/vtgate/planbuilder/operators/join.go | 5 +- .../planbuilder/operators/querygraph.go | 13 +--- go/vt/vtgate/planbuilder/operators/union.go | 69 +++---------------- .../planbuilder/operators/union_merging.go | 26 ------- go/vt/vtgate/semantics/binder.go | 1 + go/vt/vtgate/semantics/derived_table.go | 3 - go/vt/vtgate/semantics/semantic_state.go | 7 +- go/vt/vtgate/semantics/table_collector.go | 2 +- 17 files changed, 34 insertions(+), 159 deletions(-) diff --git a/go/test/endtoend/vtgate/queries/random/query_gen.go b/go/test/endtoend/vtgate/queries/random/query_gen.go index f8d9350bf5a..9415560b132 100644 --- a/go/test/endtoend/vtgate/queries/random/query_gen.go +++ b/go/test/endtoend/vtgate/queries/random/query_gen.go @@ -21,10 +21,9 @@ import ( "math/rand" "time" - "vitess.io/vitess/go/slice" - "golang.org/x/exp/slices" + "vitess.io/vitess/go/slice" "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/sqlparser" ) diff --git a/go/test/endtoend/vtgate/queries/random/random_expr_test.go b/go/test/endtoend/vtgate/queries/random/random_expr_test.go index daa7ce851a9..1bf4fb7025c 100644 --- a/go/test/endtoend/vtgate/queries/random/random_expr_test.go +++ b/go/test/endtoend/vtgate/queries/random/random_expr_test.go @@ -21,7 +21,6 @@ import ( "time" "vitess.io/vitess/go/slice" - "vitess.io/vitess/go/vt/sqlparser" ) diff --git a/go/vt/vtgate/engine/aggregations.go b/go/vt/vtgate/engine/aggregations.go index d8656d09d08..8d258393292 100644 --- a/go/vt/vtgate/engine/aggregations.go +++ b/go/vt/vtgate/engine/aggregations.go @@ -20,17 +20,15 @@ import ( "fmt" "strconv" - "vitess.io/vitess/go/slice" - - "vitess.io/vitess/go/vt/vterrors" - "google.golang.org/protobuf/proto" "vitess.io/vitess/go/mysql/collations" + "vitess.io/vitess/go/slice" "vitess.io/vitess/go/sqltypes" binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" querypb "vitess.io/vitess/go/vt/proto/query" "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vterrors" . "vitess.io/vitess/go/vt/vtgate/engine/opcode" "vitess.io/vitess/go/vt/vtgate/evalengine" ) diff --git a/go/vt/vtgate/evalengine/compiler_asm.go b/go/vt/vtgate/evalengine/compiler_asm.go index b60f1150490..7b3f4571656 100644 --- a/go/vt/vtgate/evalengine/compiler_asm.go +++ b/go/vt/vtgate/evalengine/compiler_asm.go @@ -33,21 +33,18 @@ import ( "strconv" "time" - "vitess.io/vitess/go/slice" - "github.com/google/uuid" - "vitess.io/vitess/go/mysql/hex" - - "vitess.io/vitess/go/mysql/icuregex" - "vitess.io/vitess/go/hack" "vitess.io/vitess/go/mysql/collations" "vitess.io/vitess/go/mysql/collations/charset" "vitess.io/vitess/go/mysql/datetime" "vitess.io/vitess/go/mysql/decimal" "vitess.io/vitess/go/mysql/fastparse" + "vitess.io/vitess/go/mysql/hex" + "vitess.io/vitess/go/mysql/icuregex" "vitess.io/vitess/go/mysql/json" + "vitess.io/vitess/go/slice" "vitess.io/vitess/go/sqltypes" querypb "vitess.io/vitess/go/vt/proto/query" "vitess.io/vitess/go/vt/proto/vtrpc" diff --git a/go/vt/vtgate/planbuilder/distinct.go b/go/vt/vtgate/planbuilder/distinct.go index d9d8d4176dd..8b81fa4a8ce 100644 --- a/go/vt/vtgate/planbuilder/distinct.go +++ b/go/vt/vtgate/planbuilder/distinct.go @@ -41,14 +41,6 @@ func newDistinct(source logicalPlan, checkCols []engine.CheckCol, truncateColumn } } -func newDistinctGen4Legacy(source logicalPlan, checkCols []engine.CheckCol, needToTruncate bool) logicalPlan { - return &distinct{ - logicalPlanCommon: newBuilderCommon(source), - checkCols: checkCols, - needToTruncate: needToTruncate, - } -} - func (d *distinct) Primitive() engine.Primitive { truncate := d.truncateColumn if d.needToTruncate { diff --git a/go/vt/vtgate/planbuilder/operators/SQL_builder.go b/go/vt/vtgate/planbuilder/operators/SQL_builder.go index e7a84839cbc..e7538f65860 100644 --- a/go/vt/vtgate/planbuilder/operators/SQL_builder.go +++ b/go/vt/vtgate/planbuilder/operators/SQL_builder.go @@ -123,7 +123,7 @@ func (qb *queryBuilder) addProjection(projection *sqlparser.AliasedExpr) error { } } - return vterrors.VT13001("switch should be exhaustive") + return vterrors.VT13001(fmt.Sprintf("unknown select statement type: %T", qb.sel)) } func (qb *queryBuilder) pushUnionInsideDerived() { @@ -414,7 +414,7 @@ func buildQuery(op ops.Operator, qb *queryBuilder) error { qb.sel.MakeDistinct() return nil default: - return vterrors.VT13001(fmt.Sprintf("do not know how to turn %T into SQL", op)) + return vterrors.VT13001(fmt.Sprintf("unknown operator to convert to SQL: %T", op)) } return nil } @@ -601,10 +601,8 @@ func buildDerived(op *Horizon, qb *queryBuilder) error { return buildDerivedSelect(op, qb, sel) case *sqlparser.Union: return buildDerivedUnion(op, qb, sel) - - default: - panic(fmt.Sprintf("what is this? %v", stmt)) } + panic(fmt.Sprintf("unknown select statement type: %T", stmt)) } func buildDerivedUnion(op *Horizon, qb *queryBuilder, union *sqlparser.Union) error { diff --git a/go/vt/vtgate/planbuilder/operators/horizon.go b/go/vt/vtgate/planbuilder/operators/horizon.go index 6718a241342..3e9dc90fb4f 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon.go +++ b/go/vt/vtgate/planbuilder/operators/horizon.go @@ -229,16 +229,6 @@ func (h *Horizon) GetOrdering() ([]ops.OrderBy, error) { return h.QP.OrderExprs, nil } -func addToIntSlice(columnOffset []int, valToAdd int) ([]int, int) { - for idx, val := range columnOffset { - if val == valToAdd { - return columnOffset, idx - } - } - columnOffset = append(columnOffset, valToAdd) - return columnOffset, len(columnOffset) - 1 -} - // TODO: REMOVE func (h *Horizon) selectStatement() sqlparser.SelectStatement { return h.Query diff --git a/go/vt/vtgate/planbuilder/operators/horizon_expanding.go b/go/vt/vtgate/planbuilder/operators/horizon_expanding.go index 5a7ae961862..42c91958a61 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_expanding.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_expanding.go @@ -27,15 +27,14 @@ import ( ) func expandHorizon(ctx *plancontext.PlanningContext, horizon *Horizon) (ops.Operator, *rewrite.ApplyResult, error) { - - switch sel := horizon.selectStatement().(type) { + statement := horizon.selectStatement() + switch sel := statement.(type) { case *sqlparser.Select: return expandSelectHorizon(ctx, horizon, sel) case *sqlparser.Union: return expandUnionHorizon(ctx, horizon, sel) } - - panic("the switch should be exhaustive") + return nil, nil, vterrors.VT13001(fmt.Sprintf("unexpected statement type %T", statement)) } func expandUnionHorizon(ctx *plancontext.PlanningContext, horizon *Horizon, union *sqlparser.Union) (ops.Operator, *rewrite.ApplyResult, error) { diff --git a/go/vt/vtgate/planbuilder/operators/horizon_planning.go b/go/vt/vtgate/planbuilder/operators/horizon_planning.go index 62a46a29439..f22a0989276 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_planning.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_planning.go @@ -109,9 +109,6 @@ func planHorizons(ctx *plancontext.PlanningContext, root ops.Operator) (op ops.O if err != nil { return nil, err } - if op == nil { - panic("got nil op back") - } } if rewrite.DebugOperatorTree { fmt.Printf("PHASE: %s\n", phase.Name) @@ -120,17 +117,11 @@ func planHorizons(ctx *plancontext.PlanningContext, root ops.Operator) (op ops.O if err != nil { return nil, err } - if op == nil { - panic("got nil op back") - } op, err = compact(ctx, op) if err != nil { return nil, err } - if op == nil { - panic("got nil op back") - } } return addGroupByOnRHSOfJoin(op) @@ -696,11 +687,7 @@ func tryPushDownUnion(ctx *plancontext.PlanningContext, op *Union) (ops.Operator if len(sources) == len(op.Sources) { return op, rewrite.SameTree, nil } - - // TODO: this is a hack - columns := op.unionColumns - - return newUnion(sources, selects, columns, op.distinct), rewrite.NewTree("merged union inputs", op), nil + return newUnion(sources, selects, op.unionColumns, op.distinct), rewrite.NewTree("merged union inputs", op), nil } // addTruncationOrProjectionToReturnOutput uses the original Horizon to make sure that the output columns line up with what the user asked for diff --git a/go/vt/vtgate/planbuilder/operators/join.go b/go/vt/vtgate/planbuilder/operators/join.go index 1998454a4e2..dd119625902 100644 --- a/go/vt/vtgate/planbuilder/operators/join.go +++ b/go/vt/vtgate/planbuilder/operators/join.go @@ -79,10 +79,7 @@ func (j *Join) Compact(ctx *plancontext.PlanningContext) (ops.Operator, *rewrite NoDeps: ctx.SemTable.AndExpressions(lqg.NoDeps, rqg.NoDeps), } if j.Predicate != nil { - err := newOp.collectPredicate(ctx, j.Predicate) - if err != nil { - return nil, rewrite.SameTree, err - } + newOp.collectPredicate(ctx, j.Predicate) } return newOp, rewrite.NewTree("merge querygraphs into a single one", newOp), nil } diff --git a/go/vt/vtgate/planbuilder/operators/querygraph.go b/go/vt/vtgate/planbuilder/operators/querygraph.go index 5d06da0e9b5..0d0d3f4e28a 100644 --- a/go/vt/vtgate/planbuilder/operators/querygraph.go +++ b/go/vt/vtgate/planbuilder/operators/querygraph.go @@ -96,10 +96,7 @@ func (qg *QueryGraph) collectPredicates(ctx *plancontext.PlanningContext, sel *s predicates := sqlparser.SplitAndExpression(nil, sel.Where.Expr) for _, predicate := range predicates { - err := qg.collectPredicate(ctx, predicate) - if err != nil { - return err - } + qg.collectPredicate(ctx, predicate) } return nil } @@ -130,7 +127,7 @@ func (qg *QueryGraph) addJoinPredicates(ctx *plancontext.PlanningContext, ts sem }) } -func (qg *QueryGraph) collectPredicate(ctx *plancontext.PlanningContext, predicate sqlparser.Expr) error { +func (qg *QueryGraph) collectPredicate(ctx *plancontext.PlanningContext, predicate sqlparser.Expr) { deps := ctx.SemTable.RecursiveDeps(predicate) switch deps.NumberOfTables() { case 0: @@ -144,7 +141,6 @@ func (qg *QueryGraph) collectPredicate(ctx *plancontext.PlanningContext, predica default: qg.addJoinPredicates(ctx, deps, predicate) } - return nil } func (qg *QueryGraph) addToSingleTable(ctx *plancontext.PlanningContext, table semantics.TableSet, predicate sqlparser.Expr) bool { @@ -203,10 +199,7 @@ func (qg *QueryGraph) GetOrdering() ([]ops.OrderBy, error) { func (qg *QueryGraph) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (ops.Operator, error) { for _, e := range sqlparser.SplitAndExpression(nil, expr) { - err := qg.collectPredicate(ctx, e) - if err != nil { - return nil, err - } + qg.collectPredicate(ctx, e) } return qg, nil } diff --git a/go/vt/vtgate/planbuilder/operators/union.go b/go/vt/vtgate/planbuilder/operators/union.go index bc2f2ade36d..72a9985cdca 100644 --- a/go/vt/vtgate/planbuilder/operators/union.go +++ b/go/vt/vtgate/planbuilder/operators/union.go @@ -110,16 +110,16 @@ func (u *Union) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Ex offsets[ae.ColumnName()] = i } - exprPerSource, err := u.predicatePerSource(expr, offsets) - if err == errUseFilter { + needsFilter, exprPerSource, err := u.predicatePerSource(expr, offsets) + if err != nil { + return nil, err + } + if needsFilter { return &Filter{ Source: u, Predicates: []sqlparser.Expr{expr}, }, nil } - if err != nil { - return nil, err - } for i, src := range u.Sources { u.Sources[i], err = src.AddPredicate(ctx, exprPerSource[i]) @@ -131,9 +131,8 @@ func (u *Union) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Ex return u, nil } -var errUseFilter = fmt.Errorf("use filter") - -func (u *Union) predicatePerSource(expr sqlparser.Expr, offsets map[string]int) ([]sqlparser.Expr, error) { +func (u *Union) predicatePerSource(expr sqlparser.Expr, offsets map[string]int) (bool, []sqlparser.Expr, error) { + needsFilter := false exprPerSource := make([]sqlparser.Expr, len(u.Sources)) for i := range u.Sources { var err error @@ -145,7 +144,7 @@ func (u *Union) predicatePerSource(expr sqlparser.Expr, offsets map[string]int) idx, ok := offsets[col.Name.Lowered()] if !ok { - err = errUseFilter + needsFilter = true cursor.StopTreeWalk() return } @@ -165,12 +164,12 @@ func (u *Union) predicatePerSource(expr sqlparser.Expr, offsets map[string]int) } cursor.Replace(ae.Expr) }, nil).(sqlparser.Expr) - if err != nil { - return nil, err + if err != nil || needsFilter { + return needsFilter, nil, err } exprPerSource[i] = predicate } - return exprPerSource, nil + return needsFilter, exprPerSource, nil } func (u *Union) GetSelectFor(source int) (*sqlparser.Select, error) { @@ -279,52 +278,6 @@ func (u *Union) AddColumns(ctx *plancontext.PlanningContext, reuse bool, addToGr return offsets, nil } -func (u *Union) AddColumn(ctx *plancontext.PlanningContext, ae *sqlparser.AliasedExpr, _, addToGroupBy bool) (ops.Operator, int, error) { - col, err := u.FindCol(ctx, ae.Expr, false) - if err != nil { - return nil, 0, err - } - if col >= 0 { - return u, col, nil - } - - cols, err := u.GetColumns(ctx) - if err != nil { - return nil, 0, err - } - - switch e := ae.Expr.(type) { - case *sqlparser.ColName: - // here we deal with pure column access on top of the union - offset := slices.IndexFunc(cols, func(expr *sqlparser.AliasedExpr) bool { - return e.Name.EqualString(expr.ColumnName()) - }) - if offset == -1 { - return nil, 0, vterrors.VT13001(fmt.Sprintf("could not find the column '%s' on the UNION", sqlparser.String(e))) - } - return u, offset, nil - case *sqlparser.WeightStringFuncExpr: - wsArg := e.Expr - argIdx := slices.IndexFunc(cols, func(expr *sqlparser.AliasedExpr) bool { - return ctx.SemTable.EqualsExprWithDeps(wsArg, expr.Expr) - }) - - if argIdx == -1 { - return nil, 0, vterrors.VT13001(fmt.Sprintf("could not find the argument to the weight_string function: %s", sqlparser.String(wsArg))) - } - - outputOffset, err := u.addWeightStringToOffset(ctx, argIdx, addToGroupBy) - if err != nil { - return nil, 0, err - } - - return u, outputOffset, nil - default: - return nil, 0, vterrors.VT13001(fmt.Sprintf("only weight_string function is expected - got %s", sqlparser.String(ae))) - } - -} - func (u *Union) addWeightStringToOffset(ctx *plancontext.PlanningContext, argIdx int, addToGroupBy bool) (outputOffset int, err error) { for i, src := range u.Sources { exprs := u.Selects[i] diff --git a/go/vt/vtgate/planbuilder/operators/union_merging.go b/go/vt/vtgate/planbuilder/operators/union_merging.go index 171c77e7298..297bfaec452 100644 --- a/go/vt/vtgate/planbuilder/operators/union_merging.go +++ b/go/vt/vtgate/planbuilder/operators/union_merging.go @@ -158,29 +158,3 @@ func createMergedUnion( Routing: routing, }, selectExprs, nil } - -/* - -func canMergeUnionPlans(ctx *plancontext.PlanningContext, a, b *route) bool { - // this method should be close to tryMerge below. it does the same thing, but on logicalPlans instead of queryTrees - if a.eroute.Keyspace.Name != b.eroute.Keyspace.Name { - return false - } - switch a.eroute.Opcode { - case engine.EqualUnique: - // Check if they target the same shard. - if b.eroute.Opcode == engine.EqualUnique && - a.eroute.Vindex == b.eroute.Vindex && - a.condition != nil && - b.condition != nil && - gen4ValuesEqual(ctx, []sqlparser.Expr{a.condition}, []sqlparser.Expr{b.condition}) { - return true - } - case engine.Scatter: - return b.eroute.Opcode == engine.Scatter - case engine.Next: - return false - } - return false -} -*/ diff --git a/go/vt/vtgate/semantics/binder.go b/go/vt/vtgate/semantics/binder.go index dd65bc712c4..c43180d1efa 100644 --- a/go/vt/vtgate/semantics/binder.go +++ b/go/vt/vtgate/semantics/binder.go @@ -118,6 +118,7 @@ func (b *binder) up(cursor *sqlparser.Cursor) error { b.bindCountStar(node) case *sqlparser.Union: info := b.tc.unionInfo[node] + // TODO: this check can be removed and available type information should be used. if !info.isAuthoritative { return nil } diff --git a/go/vt/vtgate/semantics/derived_table.go b/go/vt/vtgate/semantics/derived_table.go index 584665a1f7f..a88f39cf8af 100644 --- a/go/vt/vtgate/semantics/derived_table.go +++ b/go/vt/vtgate/semantics/derived_table.go @@ -171,9 +171,6 @@ func (dt *DerivedTable) getExprFor(s string) (sqlparser.Expr, error) { } for i, colName := range dt.columnNames { if colName == s { - if i >= len(dt.cols) { - panic("oops") - } return dt.cols[i], nil } } diff --git a/go/vt/vtgate/semantics/semantic_state.go b/go/vt/vtgate/semantics/semantic_state.go index 9163ef910a3..4f68a4e9702 100644 --- a/go/vt/vtgate/semantics/semantic_state.go +++ b/go/vt/vtgate/semantics/semantic_state.go @@ -17,6 +17,8 @@ limitations under the License. package semantics import ( + "fmt" + "vitess.io/vitess/go/mysql/collations" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/key" @@ -148,10 +150,9 @@ func (st *SemTable) SelectExprs(sel sqlparser.SelectStatement) sqlparser.SelectE if found { return exprs } - panic("what the what") + panic("BUG: union not found in semantic table for select expressions") } - - return nil + panic(fmt.Sprintf("BUG: unexpected select statement type %T", sel)) } func getColumnNames(exprs sqlparser.SelectExprs) (expanded bool, selectExprs sqlparser.SelectExprs) { diff --git a/go/vt/vtgate/semantics/table_collector.go b/go/vt/vtgate/semantics/table_collector.go index 92795cee880..d6fd4c6efd6 100644 --- a/go/vt/vtgate/semantics/table_collector.go +++ b/go/vt/vtgate/semantics/table_collector.go @@ -155,7 +155,7 @@ func (tc *tableCollector) addUnionDerivedTable(union *sqlparser.Union, node *sql tables := tc.scoper.wScope[firstSelect] info, found := tc.unionInfo[union] if !found { - panic("what the what") + return vterrors.VT13001("information about union is not available") } tableInfo := createDerivedTableForExpressions(info.exprs, node.Columns, tables.tables, tc.org, info.isAuthoritative, info.recursive, info.types) From e5ee6bb030ec865156ba90c544b3705fb2c0899e Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Sun, 6 Aug 2023 15:19:31 +0530 Subject: [PATCH 34/44] moved unsupported cases to unsupported_cases file Signed-off-by: Harshit Gangal --- .../planbuilder/testdata/aggr_cases.json | 5 - .../ddl_cases_no_default_keyspace.json | 15 --- .../planbuilder/testdata/filter_cases.json | 5 - .../testdata/postprocess_cases.json | 20 --- .../planbuilder/testdata/select_cases.json | 20 --- .../planbuilder/testdata/union_cases.json | 15 --- .../testdata/unsupported_cases.json | 126 +++++++++++------- 7 files changed, 80 insertions(+), 126 deletions(-) diff --git a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json index f16039f56c4..49df0ab91c5 100644 --- a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json @@ -1406,11 +1406,6 @@ ] } }, - { - "comment": "Cannot have more than one aggr(distinct...", - "query": "select count(distinct a), count(distinct b) from user", - "plan": "VT12001: unsupported: only one DISTINCT aggregation is allowed in a SELECT: count(distinct b)" - }, { "comment": "multiple distinct functions with grouping.", "query": "select col1, count(distinct col2), sum(distinct col2) from user group by col1", diff --git a/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json b/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json index 9df66921fd5..d05631cbff5 100644 --- a/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json +++ b/go/vt/vtgate/planbuilder/testdata/ddl_cases_no_default_keyspace.json @@ -637,11 +637,6 @@ ] } }, - { - "comment": "drop table with incompatible tables", - "query": "drop table user, unsharded_a", - "plan": "VT12001: unsupported: Tables or Views specified in the query do not belong to the same destination" - }, { "comment": "drop table with unknown table", "query": "drop table unknown", @@ -667,11 +662,6 @@ ] } }, - { - "comment": "drop view with incompatible views", - "query": "drop view user, unsharded_a", - "plan": "VT12001: unsupported: Tables or Views specified in the query do not belong to the same destination" - }, { "comment": "drop view with unknown view", "query": "drop view unknown", @@ -716,11 +706,6 @@ ] } }, - { - "comment": "Rename table with different keyspace tables", - "query": "rename table user_extra to b, main.a to b", - "plan": "VT12001: unsupported: Tables or Views specified in the query do not belong to the same destination" - }, { "comment": "Rename table with change in keyspace name", "query": "rename table user_extra to main.b", diff --git a/go/vt/vtgate/planbuilder/testdata/filter_cases.json b/go/vt/vtgate/planbuilder/testdata/filter_cases.json index ba13e9f45ef..842602f2e99 100644 --- a/go/vt/vtgate/planbuilder/testdata/filter_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/filter_cases.json @@ -2656,11 +2656,6 @@ ] } }, - { - "comment": "correlated subquery with different keyspace tables involved", - "query": "select id from user where id in (select col from unsharded where col = user.id)", - "plan": "VT12001: unsupported: cross-shard correlated subquery" - }, { "comment": "correlated subquery with same keyspace", "query": "select u.id from user as u where u.col in (select ue.user_id from user_extra as ue where ue.user_id = u.id)", diff --git a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json index c40e99910e1..ab717491421 100644 --- a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json @@ -232,26 +232,6 @@ ] } }, - { - "comment": "ORDER BY on select t.*", - "query": "select t.*, t.col from user t order by t.col", - "plan": "VT12001: unsupported: '*' expression in cross-shard query" - }, - { - "comment": "ORDER BY on select *", - "query": "select *, col from user order by col", - "plan": "VT12001: unsupported: '*' expression in cross-shard query" - }, - { - "comment": "ORDER BY on select multi t.*", - "query": "select t.*, t.name, t.*, t.col from user t order by t.col", - "plan": "VT12001: unsupported: '*' expression in cross-shard query" - }, - { - "comment": "ORDER BY on select multi *", - "query": "select *, name, *, col from user order by col", - "plan": "VT12001: unsupported: '*' expression in cross-shard query" - }, { "comment": "ORDER BY works for select * from authoritative table", "query": "select * from authoritative order by user_id", diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.json b/go/vt/vtgate/planbuilder/testdata/select_cases.json index 12f3ee7f112..a2f5fe778c6 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.json @@ -2161,11 +2161,6 @@ ] } }, - { - "comment": "select (select col from user where user_extra.id = 4 limit 1) as a from user join user_extra", - "query": "select (select col from user where user_extra.id = 4 limit 1) as a from user join user_extra", - "plan": "VT12001: unsupported: cross-shard correlated subquery" - }, { "comment": "plan test for a natural character set string", "query": "select N'string' from dual", @@ -2438,11 +2433,6 @@ ] } }, - { - "comment": "correlated subquery part of an OR clause", - "query": "select 1 from user u where u.col = 6 or exists (select 1 from user_extra ue where ue.col = u.col and u.col = ue.col2)", - "plan": "VT12001: unsupported: EXISTS sub-queries are only supported with AND clause" - }, { "comment": "correlated subquery that is dependent on one side of a join, fully mergeable", "query": "SELECT music.id FROM music INNER JOIN user ON music.user_id = user.id WHERE music.user_id = 5 AND music.id = (SELECT MAX(m2.id) FROM music m2 WHERE m2.user_id = user.id)", @@ -4277,16 +4267,6 @@ ] } }, - { - "comment": "cant switch sides for outer joins", - "query": "select id from user left join (select user_id from user_extra limit 10) ue on user.id = ue.user_id", - "plan": "VT12001: unsupported: LEFT JOIN with derived tables" - }, - { - "comment": "limit on both sides means that we can't evaluate this at all", - "query": "select id from (select id from user limit 10) u join (select user_id from user_extra limit 10) ue on u.id = ue.user_id", - "plan": "VT12001: unsupported: JOIN between derived tables" - }, { "comment": "SELECT music.id FROM (SELECT MAX(id) as maxt FROM music WHERE music.user_id = 5) other JOIN music ON other.maxt = music.id", "query": "SELECT music.id FROM (SELECT MAX(id) as maxt FROM music WHERE music.user_id = 5) other JOIN music ON other.maxt = music.id", diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index f98924eedca..edd43a14251 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -401,16 +401,6 @@ ] } }, - { - "comment": "multi-shard union", - "query": "select 1 from music union (select id from user union all select name from unsharded)", - "plan": "VT12001: unsupported: nesting of UNIONs on the right-hand side" - }, - { - "comment": "multi-shard union", - "query": "select 1 from music union (select id from user union select name from unsharded)", - "plan": "VT12001: unsupported: nesting of UNIONs on the right-hand side" - }, { "comment": "union with the same target shard because of vindex", "query": "select * from music where user_id = 1 union select * from user where id = 1", @@ -1479,11 +1469,6 @@ ] } }, - { - "comment": "UNION with repeating column on the LHS", - "query": "select foo, foo, foo from user union select bar, baz, toto from music", - "plan": "VT12001: unsupported: unable to plan the distinct query as not able to align the columns" - }, { "comment": "UNION with repeating column on the RHS", "query": "select bar, baz, toto from music union select foo, foo, foo from user", diff --git a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json index 700cbbe6dd5..36d93cb6a8e 100644 --- a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json @@ -374,52 +374,6 @@ "query": "with x as (select * from user) select * from x union select * from x", "plan": "VT12001: unsupported: WITH expression in UNION statement" }, - { - "comment": "aggregation on union", - "query": "select sum(col) from (select col from user union all select col from unsharded) t", - "plan": { - "QueryType": "SELECT", - "Original": "select sum(col) from (select col from user union all select col from unsharded) t", - "Instructions": { - "OperatorType": "Aggregate", - "Variant": "Scalar", - "Aggregates": "sum(0) AS sum(col)", - "Inputs": [ - { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select col from `user` where 1 != 1", - "Query": "select col from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select col from unsharded where 1 != 1", - "Query": "select col from unsharded", - "Table": "unsharded" - } - ] - } - ] - }, - "TablesUsed": [ - "main.unsharded", - "user.user" - ] - } - }, { "comment": "insert having subquery in row values", "query": "insert into user(id, name) values ((select 1 from user where id = 1), 'A')", @@ -469,5 +423,85 @@ "comment": "extremum on input from both sides", "query": "insert into music(user_id, id) select foo, bar from music on duplicate key update id = id+1", "plan": "VT12001: unsupported: DML cannot update vindex column" + }, + { + "comment": "drop table with incompatible tables", + "query": "drop table user, unsharded_a", + "plan": "VT12001: unsupported: Tables or Views specified in the query do not belong to the same destination" + }, + { + "comment": "drop view with incompatible views", + "query": "drop view user, unsharded_a", + "plan": "VT12001: unsupported: Tables or Views specified in the query do not belong to the same destination" + }, + { + "comment": "Rename table with different keyspace tables", + "query": "rename table user_extra to b, main.a to b", + "plan": "VT12001: unsupported: Tables or Views specified in the query do not belong to the same destination" + }, + { + "comment": "correlated subquery with different keyspace tables involved", + "query": "select id from user where id in (select col from unsharded where col = user.id)", + "plan": "VT12001: unsupported: cross-shard correlated subquery" + }, + { + "comment": "ORDER BY on select t.*", + "query": "select t.*, t.col from user t order by t.col", + "plan": "VT12001: unsupported: '*' expression in cross-shard query" + }, + { + "comment": "ORDER BY on select *", + "query": "select *, col from user order by col", + "plan": "VT12001: unsupported: '*' expression in cross-shard query" + }, + { + "comment": "ORDER BY on select multi t.*", + "query": "select t.*, t.name, t.*, t.col from user t order by t.col", + "plan": "VT12001: unsupported: '*' expression in cross-shard query" + }, + { + "comment": "ORDER BY on select multi *", + "query": "select *, name, *, col from user order by col", + "plan": "VT12001: unsupported: '*' expression in cross-shard query" + }, + { + "comment": "select (select col from user where user_extra.id = 4 limit 1) as a from user join user_extra", + "query": "select (select col from user where user_extra.id = 4 limit 1) as a from user join user_extra", + "plan": "VT12001: unsupported: cross-shard correlated subquery" + }, + { + "comment": "correlated subquery part of an OR clause", + "query": "select 1 from user u where u.col = 6 or exists (select 1 from user_extra ue where ue.col = u.col and u.col = ue.col2)", + "plan": "VT12001: unsupported: EXISTS sub-queries are only supported with AND clause" + }, + { + "comment": "cant switch sides for outer joins", + "query": "select id from user left join (select user_id from user_extra limit 10) ue on user.id = ue.user_id", + "plan": "VT12001: unsupported: LEFT JOIN with derived tables" + }, + { + "comment": "limit on both sides means that we can't evaluate this at all", + "query": "select id from (select id from user limit 10) u join (select user_id from user_extra limit 10) ue on u.id = ue.user_id", + "plan": "VT12001: unsupported: JOIN between derived tables" + }, + { + "comment": "multi-shard union", + "query": "select 1 from music union (select id from user union all select name from unsharded)", + "plan": "VT12001: unsupported: nesting of UNIONs on the right-hand side" + }, + { + "comment": "multi-shard union", + "query": "select 1 from music union (select id from user union select name from unsharded)", + "plan": "VT12001: unsupported: nesting of UNIONs on the right-hand side" + }, + { + "comment": "UNION with repeating column on the LHS", + "query": "select foo, foo, foo from user union select bar, baz, toto from music", + "plan": "VT12001: unsupported: unable to plan the distinct query as not able to align the columns" + }, + { + "comment": "Cannot have more than one aggr(distinct...", + "query": "select count(distinct a), count(distinct b) from user", + "plan": "VT12001: unsupported: only one DISTINCT aggregation is allowed in a SELECT: count(distinct b)" } ] From 52299b3e7bbbf107ef56931a6f3e67b694578eaf Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Mon, 7 Aug 2023 11:09:49 +0200 Subject: [PATCH 35/44] remove optimization that lead to issues Signed-off-by: Andres Taylor --- .../planbuilder/operators/projection.go | 3 - .../planbuilder/testdata/aggr_cases.json | 106 +++++++++++------- .../planbuilder/testdata/select_cases.json | 4 +- .../planbuilder/testdata/union_cases.json | 43 ++++++- .../testdata/unsupported_cases.json | 5 - 5 files changed, 107 insertions(+), 54 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/projection.go b/go/vt/vtgate/planbuilder/operators/projection.go index 13b822728df..50857791209 100644 --- a/go/vt/vtgate/planbuilder/operators/projection.go +++ b/go/vt/vtgate/planbuilder/operators/projection.go @@ -261,9 +261,6 @@ func (p *Projection) AddPredicate(ctx *plancontext.PlanningContext, expr sqlpars } func (p *Projection) GetColumns(*plancontext.PlanningContext) ([]*sqlparser.AliasedExpr, error) { - if p.TableID != nil { - return nil, nil - } return p.Columns, nil } diff --git a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json index 49df0ab91c5..709dada2dec 100644 --- a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json @@ -2881,8 +2881,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select sum(col) from (select `user`.col as col, 32 from `user` where 1 != 1) as t where 1 != 1", - "Query": "select sum(col) from (select `user`.col as col, 32 from `user`) as t", + "FieldQuery": "select sum(col), 32 from (select `user`.col as col, 32 from `user` where 1 != 1) as t where 1 != 1", + "Query": "select sum(col), 32 from (select `user`.col as col, 32 from `user`) as t", "Table": "`user`" }, { @@ -3493,19 +3493,27 @@ "Aggregates": "count(0) AS count(city)", "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(10)", + "OperatorType": "SimpleProjection", + "Columns": [ + 2 + ], "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select city from (select phone, id, city from `user` where 1 != 1) as x where 1 != 1", - "Query": "select city from (select phone, id, city from `user` where id > 12) as x limit :__upper_limit", - "Table": "`user`" + "OperatorType": "Limit", + "Count": "INT64(10)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select phone, id, city from (select phone, id, city from `user` where 1 != 1) as x where 1 != 1", + "Query": "select phone, id, city from (select phone, id, city from `user` where id > 12) as x limit :__upper_limit", + "Table": "`user`" + } + ] } ] } @@ -3528,19 +3536,27 @@ "Aggregates": "count_star(0) AS count(*)", "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(10)", + "OperatorType": "SimpleProjection", + "Columns": [ + 3 + ], "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select 1 from (select phone, id, city from `user` where 1 != 1) as x where 1 != 1", - "Query": "select 1 from (select phone, id, city from `user` where id > 12) as x limit :__upper_limit", - "Table": "`user`" + "OperatorType": "Limit", + "Count": "INT64(10)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select phone, id, city, 1 from (select phone, id, city from `user` where 1 != 1) as x where 1 != 1", + "Query": "select phone, id, city, 1 from (select phone, id, city from `user` where id > 12) as x limit :__upper_limit", + "Table": "`user`" + } + ] } ] } @@ -3623,20 +3639,30 @@ "ResultColumns": 2, "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(2)", + "OperatorType": "SimpleProjection", + "Columns": [ + 1, + 2, + 3 + ], "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select val1, 1, weight_string(val1) from (select id, val1 from `user` where 1 != 1) as x where 1 != 1", - "OrderBy": "(0|2) ASC", - "Query": "select val1, 1, weight_string(val1) from (select id, val1 from `user` where val2 < 4) as x order by val1 asc limit :__upper_limit", - "Table": "`user`" + "OperatorType": "Limit", + "Count": "INT64(2)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, val1, 1, weight_string(val1) from (select id, val1 from `user` where 1 != 1) as x where 1 != 1", + "OrderBy": "(1|3) ASC", + "Query": "select id, val1, 1, weight_string(val1) from (select id, val1 from `user` where val2 < 4) as x order by val1 asc limit :__upper_limit", + "Table": "`user`" + } + ] } ] } @@ -5838,8 +5864,8 @@ { "OperatorType": "SimpleProjection", "Columns": [ - 0, - 0 + 1, + 1 ], "Inputs": [ { @@ -5853,8 +5879,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select val2 from (select id, val2 from `user` where 1 != 1) as x where 1 != 1", - "Query": "select val2 from (select id, val2 from `user` where val2 is null) as x limit :__upper_limit", + "FieldQuery": "select id, val2 from (select id, val2 from `user` where 1 != 1) as x where 1 != 1", + "Query": "select id, val2 from (select id, val2 from `user` where val2 is null) as x limit :__upper_limit", "Table": "`user`" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.json b/go/vt/vtgate/planbuilder/testdata/select_cases.json index a2f5fe778c6..53084d8a5a2 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.json @@ -4171,8 +4171,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select ue.user_id from (select user_id from user_extra where 1 != 1) as ue where 1 != 1", - "Query": "select ue.user_id from (select user_id from user_extra) as ue limit :__upper_limit", + "FieldQuery": "select user_id from (select user_id from user_extra where 1 != 1) as ue where 1 != 1", + "Query": "select user_id from (select user_id from user_extra) as ue limit :__upper_limit", "Table": "user_extra" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index edd43a14251..a686a7807b7 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -1096,13 +1096,14 @@ "Instructions": { "OperatorType": "Sort", "Variant": "Memory", - "OrderBy": "0 ASC", + "OrderBy": "(0|1) ASC", "ResultColumns": 1, "Inputs": [ { "OperatorType": "Distinct", "Collations": [ - "(0:1)" + "(0:1)", + "(1:2)" ], "Inputs": [ { @@ -1112,8 +1113,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select weight_string(id), weight_string(weight_string(id)) from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt where 1 != 1", - "Query": "select weight_string(id), weight_string(weight_string(id)) from (select id from `user` union select 3 from dual) as dt", + "FieldQuery": "select id, weight_string(id), weight_string(weight_string(id)) from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id), weight_string(weight_string(id)) from (select id from `user` union select 3 from dual) as dt", "Table": "`user`, dual" } ] @@ -1502,5 +1503,39 @@ "user.user" ] } + }, + { + "comment": "UNION with repeating column on the LHS", + "query": "select foo, foo, foo from user union select bar, baz, toto from music", + "plan": { + "QueryType": "SELECT", + "Original": "select foo, foo, foo from user union select bar, baz, toto from music", + "Instructions": { + "OperatorType": "Distinct", + "Collations": [ + "(0:3)", + "(1:3)", + "(2:3)" + ], + "ResultColumns": 3, + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select foo, foo, foo, weight_string(foo) from (select foo, foo, foo from `user` where 1 != 1 union select bar, baz, toto from music where 1 != 1) as dt where 1 != 1", + "Query": "select foo, foo, foo, weight_string(foo) from (select foo, foo, foo from `user` union select bar, baz, toto from music) as dt", + "Table": "`user`, music" + } + ] + }, + "TablesUsed": [ + "user.music", + "user.user" + ] + } } ] diff --git a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json index 36d93cb6a8e..e1d07bc58e3 100644 --- a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.json @@ -494,11 +494,6 @@ "query": "select 1 from music union (select id from user union select name from unsharded)", "plan": "VT12001: unsupported: nesting of UNIONs on the right-hand side" }, - { - "comment": "UNION with repeating column on the LHS", - "query": "select foo, foo, foo from user union select bar, baz, toto from music", - "plan": "VT12001: unsupported: unable to plan the distinct query as not able to align the columns" - }, { "comment": "Cannot have more than one aggr(distinct...", "query": "select count(distinct a), count(distinct b) from user", From 885a94eb14c7d550b9b69e2cd8b66913b1752c5c Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Mon, 7 Aug 2023 11:15:33 +0200 Subject: [PATCH 36/44] clean up distinct ws handling Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/operators/distinct.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/distinct.go b/go/vt/vtgate/planbuilder/operators/distinct.go index d9caa84b3a7..f31b4e6ea88 100644 --- a/go/vt/vtgate/planbuilder/operators/distinct.go +++ b/go/vt/vtgate/planbuilder/operators/distinct.go @@ -54,12 +54,14 @@ func (d *Distinct) planOffsets(ctx *plancontext.PlanningContext) error { } var wsExprs []*sqlparser.AliasedExpr var addToGroupBy []bool - for _, col := range columns { + wsNeeded := make([]bool, len(columns)) + for idx, col := range columns { addToGroupBy = append(addToGroupBy, false) e := d.QP.GetSimplifiedExpr(col.Expr) if ctx.SemTable.NeedsWeightString(e) { wsExprs = append(wsExprs, aeWrap(weightStringFor(e))) addToGroupBy = append(addToGroupBy, false) + wsNeeded[idx] = true } } offsets, err := d.Source.AddColumns(ctx, true, addToGroupBy, append(columns, wsExprs...)) @@ -76,13 +78,13 @@ func (d *Distinct) planOffsets(ctx *plancontext.PlanningContext) error { n := len(columns) wsOffset := 0 for i, col := range columns { - e := d.QP.GetSimplifiedExpr(col.Expr) - typ, coll, found := ctx.SemTable.TypeForExpr(e) var wsCol *int - if !found { + if wsNeeded[i] { wsCol = &offsets[n+wsOffset] wsOffset++ } + e := d.QP.GetSimplifiedExpr(col.Expr) + typ, coll, _ := ctx.SemTable.TypeForExpr(e) d.Columns = append(d.Columns, engine.CheckCol{ Col: i, WsCol: wsCol, From 687810134182eb716bbf29b2530b6189d693a08d Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Mon, 7 Aug 2023 11:16:02 +0200 Subject: [PATCH 37/44] no need to ask for the weightstring of a weightstring Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/testdata/union_cases.json | 6 +++--- go/vt/vtgate/semantics/semantic_state.go | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index a686a7807b7..4bd646741c2 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -1103,7 +1103,7 @@ "OperatorType": "Distinct", "Collations": [ "(0:1)", - "(1:2)" + "1" ], "Inputs": [ { @@ -1113,8 +1113,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id, weight_string(id), weight_string(weight_string(id)) from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt where 1 != 1", - "Query": "select id, weight_string(id), weight_string(weight_string(id)) from (select id from `user` union select 3 from dual) as dt", + "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select 3 from dual where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id) from (select id from `user` union select 3 from dual) as dt", "Table": "`user`, dual" } ] diff --git a/go/vt/vtgate/semantics/semantic_state.go b/go/vt/vtgate/semantics/semantic_state.go index 4f68a4e9702..fd248a8ed15 100644 --- a/go/vt/vtgate/semantics/semantic_state.go +++ b/go/vt/vtgate/semantics/semantic_state.go @@ -299,6 +299,10 @@ func (st *SemTable) TypeForExpr(e sqlparser.Expr) (sqltypes.Type, collations.ID, // NeedsWeightString returns true if the given expression needs weight_string to do safe comparisons func (st *SemTable) NeedsWeightString(e sqlparser.Expr) bool { + _, isWs := e.(*sqlparser.WeightStringFuncExpr) + if isWs { + return false + } typ, found := st.ExprTypes[e] if !found { return true From 41bdbf03db1a753fdd881e4d8e627d15b1dcddbb Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Mon, 7 Aug 2023 17:10:30 +0530 Subject: [PATCH 38/44] fix test in executor Signed-off-by: Harshit Gangal --- go/vt/vtgate/executor_select_test.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index 39dc1d5105c..2241944cd37 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -3642,15 +3642,15 @@ func TestSelectAggregationNoData(t *testing.T) { }, { sql: `select count(*) from (select col1, col2 from user limit 2) x`, - sandboxRes: sqltypes.MakeTestResult(sqltypes.MakeTestFields("col1", "int64")), - expSandboxQ: "select 1 from (select col1, col2 from `user`) as x limit :__upper_limit", + sandboxRes: sqltypes.MakeTestResult(sqltypes.MakeTestFields("col1|col2|1", "int64|int64|int64")), + expSandboxQ: "select col1, col2, 1 from (select col1, col2 from `user`) as x limit :__upper_limit", expField: `[name:"count(*)" type:INT64]`, expRow: `[[INT64(0)]]`, }, { sql: `select col2, count(*) from (select col1, col2 from user limit 2) x group by col2`, - sandboxRes: sqltypes.MakeTestResult(sqltypes.MakeTestFields("col2|1|weight_string(col2)", "int64|int64|varbinary")), - expSandboxQ: "select col2, 1, weight_string(col2) from (select col1, col2 from `user`) as x limit :__upper_limit", + sandboxRes: sqltypes.MakeTestResult(sqltypes.MakeTestFields("col1|col2|1|weight_string(col2)", "int64|int64|int64|varbinary")), + expSandboxQ: "select col1, col2, 1, weight_string(col2) from (select col1, col2 from `user`) as x limit :__upper_limit", expField: `[name:"col2" type:INT64 name:"count(*)" type:INT64]`, expRow: `[]`, }, @@ -3726,29 +3726,29 @@ func TestSelectAggregationData(t *testing.T) { }, { sql: `select count(*) from (select col1, col2 from user limit 2) x`, - sandboxRes: sqltypes.MakeTestResult(sqltypes.MakeTestFields("1", "int64"), "1", "1"), - expSandboxQ: "select 1 from (select col1, col2 from `user`) as x limit :__upper_limit", + sandboxRes: sqltypes.MakeTestResult(sqltypes.MakeTestFields("col1|col2|1", "int64|int64|int64"), "100|200|1", "200|300|1"), + expSandboxQ: "select col1, col2, 1 from (select col1, col2 from `user`) as x limit :__upper_limit", expField: `[name:"count(*)" type:INT64]`, expRow: `[[INT64(2)]]`, }, { sql: `select col2, count(*) from (select col1, col2 from user limit 9) x group by col2`, - sandboxRes: sqltypes.MakeTestResult(sqltypes.MakeTestFields("col2|1|weight_string(col2)", "int64|int64|varbinary"), "3|1|NULL", "2|1|NULL"), - expSandboxQ: "select col2, 1, weight_string(col2) from (select col1, col2 from `user`) as x limit :__upper_limit", + sandboxRes: sqltypes.MakeTestResult(sqltypes.MakeTestFields("col1|col2|1|weight_string(col2)", "int64|int64|int64|varbinary"), "100|3|1|NULL", "200|2|1|NULL"), + expSandboxQ: "select col1, col2, 1, weight_string(col2) from (select col1, col2 from `user`) as x limit :__upper_limit", expField: `[name:"col2" type:INT64 name:"count(*)" type:INT64]`, expRow: `[[INT64(2) INT64(4)] [INT64(3) INT64(5)]]`, }, { sql: `select count(col1) from (select id, col1 from user limit 2) x`, - sandboxRes: sqltypes.MakeTestResult(sqltypes.MakeTestFields("col1", "varchar"), "a", "b"), - expSandboxQ: "select col1 from (select id, col1 from `user`) as x limit :__upper_limit", + sandboxRes: sqltypes.MakeTestResult(sqltypes.MakeTestFields("id|col1", "int64|varchar"), "1|a", "2|b"), + expSandboxQ: "select id, col1 from (select id, col1 from `user`) as x limit :__upper_limit", expField: `[name:"count(col1)" type:INT64]`, expRow: `[[INT64(2)]]`, }, { sql: `select count(col1), col2 from (select col2, col1 from user limit 9) x group by col2`, - sandboxRes: sqltypes.MakeTestResult(sqltypes.MakeTestFields("col1|col2|weight_string(col2)", "varchar|int64|varbinary"), "a|3|NULL", "b|2|NULL"), - expSandboxQ: "select col1, col2, weight_string(col2) from (select col2, col1 from `user`) as x limit :__upper_limit", + sandboxRes: sqltypes.MakeTestResult(sqltypes.MakeTestFields("col2|col1|weight_string(col2)", "int64|varchar|varbinary"), "3|a|NULL", "2|b|NULL"), + expSandboxQ: "select col2, col1, weight_string(col2) from (select col2, col1 from `user`) as x limit :__upper_limit", expField: `[name:"count(col1)" type:INT64 name:"col2" type:INT64]`, expRow: `[[INT64(4) INT64(2)] [INT64(5) INT64(3)]]`, }, From c10e4f544fe1f43fb52e5e35ff2338e8db54c707 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Mon, 7 Aug 2023 17:39:59 +0530 Subject: [PATCH 39/44] no compact after truncation call Signed-off-by: Harshit Gangal --- .../planbuilder/operators/horizon_planning.go | 7 +- .../planbuilder/testdata/from_cases.json | 57 ++++---- .../testdata/postprocess_cases.json | 59 ++++---- .../planbuilder/testdata/union_cases.json | 136 ++++++++++-------- 4 files changed, 144 insertions(+), 115 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/horizon_planning.go b/go/vt/vtgate/planbuilder/operators/horizon_planning.go index f22a0989276..0fcd501c377 100644 --- a/go/vt/vtgate/planbuilder/operators/horizon_planning.go +++ b/go/vt/vtgate/planbuilder/operators/horizon_planning.go @@ -87,12 +87,7 @@ func tryHorizonPlanning(ctx *plancontext.PlanningContext, root ops.Operator) (ou return nil, err } - output, err = addTruncationOrProjectionToReturnOutput(ctx, root, output) - if err != nil { - return nil, err - } - - return compact(ctx, output) + return addTruncationOrProjectionToReturnOutput(ctx, root, output) } // planHorizons is the process of figuring out how to perform the operations in the Horizon diff --git a/go/vt/vtgate/planbuilder/testdata/from_cases.json b/go/vt/vtgate/planbuilder/testdata/from_cases.json index 794dfb5543a..bf48056623e 100644 --- a/go/vt/vtgate/planbuilder/testdata/from_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/from_cases.json @@ -2464,32 +2464,41 @@ "QueryType": "SELECT", "Original": "select id, t.id from (select user.id from user join user_extra) as t", "Instructions": { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "L:0,L:0", - "TableName": "`user`_user_extra", + "OperatorType": "SimpleProjection", + "Columns": [ + 0, + 0 + ], "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id from (select `user`.id from `user` where 1 != 1) as t where 1 != 1", - "Query": "select id from (select `user`.id from `user`) as t", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select 1 from user_extra where 1 != 1", - "Query": "select 1 from user_extra", - "Table": "user_extra" + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0", + "TableName": "`user`_user_extra", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from (select `user`.id from `user` where 1 != 1) as t where 1 != 1", + "Query": "select id from (select `user`.id from `user`) as t", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 1 from user_extra where 1 != 1", + "Query": "select 1 from user_extra", + "Table": "user_extra" + } + ] } ] }, diff --git a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json index ab717491421..dd2ab2fc2d1 100644 --- a/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/postprocess_cases.json @@ -1575,33 +1575,42 @@ "QueryType": "SELECT", "Original": "select name, name from user, music order by name", "Instructions": { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "L:0,L:0", - "TableName": "`user`_music", + "OperatorType": "SimpleProjection", + "Columns": [ + 0, + 0 + ], "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select `name`, weight_string(`name`) from `user` where 1 != 1", - "OrderBy": "(0|1) ASC", - "Query": "select `name`, weight_string(`name`) from `user` order by `name` asc", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select 1 from music where 1 != 1", - "Query": "select 1 from music", - "Table": "music" + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0", + "TableName": "`user`_music", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select `name`, weight_string(`name`) from `user` where 1 != 1", + "OrderBy": "(0|1) ASC", + "Query": "select `name`, weight_string(`name`) from `user` order by `name` asc", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 1 from music where 1 != 1", + "Query": "select 1 from music", + "Table": "music" + } + ] } ] }, diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 4bd646741c2..6445906b6af 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -107,41 +107,49 @@ "QueryType": "SELECT", "Original": "(SELECT id FROM user ORDER BY id DESC LIMIT 1) UNION ALL (SELECT id FROM music ORDER BY id DESC LIMIT 1)", "Instructions": { - "OperatorType": "Concatenate", + "OperatorType": "SimpleProjection", + "Columns": [ + 0 + ], "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(1)", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", - "Table": "`user`" - } - ] - }, - { - "OperatorType": "Limit", - "Count": "INT64(1)", - "Inputs": [ + "OperatorType": "Limit", + "Count": "INT64(1)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", + "Table": "`user`" + } + ] + }, { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from music where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", - "Table": "music" + "OperatorType": "Limit", + "Count": "INT64(1)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from music where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", + "Table": "music" + } + ] } ] } @@ -229,41 +237,49 @@ "QueryType": "SELECT", "Original": "(select id from user order by id limit 5) union all (select id from music order by id desc limit 5)", "Instructions": { - "OperatorType": "Concatenate", + "OperatorType": "SimpleProjection", + "Columns": [ + 0 + ], "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(5)", + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) ASC", - "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", - "Table": "`user`" - } - ] - }, - { - "OperatorType": "Limit", - "Count": "INT64(5)", - "Inputs": [ + "OperatorType": "Limit", + "Count": "INT64(5)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) ASC", + "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", + "Table": "`user`" + } + ] + }, { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from music where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", - "Table": "music" + "OperatorType": "Limit", + "Count": "INT64(5)", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from music where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from music order by id desc limit :__upper_limit", + "Table": "music" + } + ] } ] } From 9b19a249d32eb7b97ab3a0d47981a7a79308ffe5 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Mon, 7 Aug 2023 17:55:04 +0200 Subject: [PATCH 40/44] calculate the dependencies more fine grained Signed-off-by: Andres Taylor --- .../planbuilder/operators/union_merging.go | 43 ++++++++++++++++--- .../planbuilder/testdata/union_cases.json | 16 +++---- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/union_merging.go b/go/vt/vtgate/planbuilder/operators/union_merging.go index 297bfaec452..78cc77b03e5 100644 --- a/go/vt/vtgate/planbuilder/operators/union_merging.go +++ b/go/vt/vtgate/planbuilder/operators/union_merging.go @@ -117,19 +117,19 @@ func mergeUnionInputs(ctx *plancontext.PlanningContext, lhs, rhs ops.Operator, l switch { // if either side is a dual query, we can always merge them together case b == dual: - return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingA) + return createMergedUnion(ctx, lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingA) case a == dual: - return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB) + return createMergedUnion(ctx, lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB) case a == anyShard && sameKeyspace: - return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB) + return createMergedUnion(ctx, lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB) case b == anyShard && sameKeyspace: - return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingA) + return createMergedUnion(ctx, lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingA) case a == sharded && b == sharded && sameKeyspace: // If the two routes fully match, they can be merged together. tblA := routingA.(*ShardedRouting) tblB := routingB.(*ShardedRouting) if tblA.RouteOpCode == engine.Scatter && tblB.RouteOpCode == engine.Scatter { - return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB) + return createMergedUnion(ctx, lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB) } if tblA.RouteOpCode != engine.EqualUnique || tblB.RouteOpCode != engine.EqualUnique { break @@ -139,18 +139,47 @@ func mergeUnionInputs(ctx *plancontext.PlanningContext, lhs, rhs ops.Operator, l aExpr := tblA.VindexExpressions() bExpr := tblB.VindexExpressions() if aVdx == bVdx && gen4ValuesEqual(ctx, aExpr, bExpr) { - return createMergedUnion(lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB) + return createMergedUnion(ctx, lhsRoute, rhsRoute, lhsExprs, rhsExprs, distinct, routingB) } } return nil, nil, nil } func createMergedUnion( + ctx *plancontext.PlanningContext, lhsRoute, rhsRoute *Route, lhsExprs, rhsExprs sqlparser.SelectExprs, distinct bool, routing Routing) (ops.Operator, sqlparser.SelectExprs, error) { - union := newUnion([]ops.Operator{lhsRoute.Source, rhsRoute.Source}, []sqlparser.SelectExprs{lhsExprs, rhsExprs}, lhsExprs, distinct) + + // if there are `*` on either side, or a different number of SelectExpr items, + // we give up aligning the expressions and trust that we can push everything down + cols := make(sqlparser.SelectExprs, len(lhsExprs)) + noDeps := len(lhsExprs) != len(rhsExprs) + for idx, col := range lhsExprs { + ae, ok := col.(*sqlparser.AliasedExpr) + if !ok { + cols[idx] = col + noDeps = true + continue + } + col := sqlparser.NewColName(ae.ColumnName()) + cols[idx] = aeWrap(col) + if noDeps { + continue + } + + deps := ctx.SemTable.RecursiveDeps(ae.Expr) + ae, ok = rhsExprs[idx].(*sqlparser.AliasedExpr) + if !ok { + noDeps = true + continue + } + deps = deps.Merge(ctx.SemTable.RecursiveDeps(ae.Expr)) + ctx.SemTable.Recursive[col] = deps + } + + union := newUnion([]ops.Operator{lhsRoute.Source, rhsRoute.Source}, []sqlparser.SelectExprs{lhsExprs, rhsExprs}, cols, distinct) selectExprs := unionSelects(lhsExprs) return &Route{ Source: union, diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 6445906b6af..82e7bcd27ba 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -543,8 +543,9 @@ "Instructions": { "OperatorType": "Distinct", "Collations": [ - "0" + "(0:1)" ], + "ResultColumns": 1, "Inputs": [ { "OperatorType": "Route", @@ -553,8 +554,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select 1 from dual where 1 != 1 union select null from dual where 1 != 1 union select 1.0 from dual where 1 != 1 union select '1' from dual where 1 != 1 union select 2 from dual where 1 != 1 union select 2.0 from `user` where 1 != 1", - "Query": "select 1 from dual union select null from dual union select 1.0 from dual union select '1' from dual union select 2 from dual union select 2.0 from `user`", + "FieldQuery": "select `1`, weight_string(`1`) from (select 1 from dual where 1 != 1 union select null from dual where 1 != 1 union select 1.0 from dual where 1 != 1 union select '1' from dual where 1 != 1 union select 2 from dual where 1 != 1 union select 2.0 from `user` where 1 != 1) as dt where 1 != 1", + "Query": "select `1`, weight_string(`1`) from (select 1 from dual union select null from dual union select 1.0 from dual union select '1' from dual union select 2 from dual union select 2.0 from `user`) as dt", "Table": "`user`, dual" } ] @@ -786,14 +787,13 @@ "Instructions": { "OperatorType": "SimpleProjection", "Columns": [ - 1 + 0 ], "Inputs": [ { "OperatorType": "Distinct", "Collations": [ - "(0:2)", - "(1:3)" + "(0:1)" ], "Inputs": [ { @@ -803,8 +803,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select id, weight_string(id), weight_string(id) from (select id from `user` where 1 != 1 union select id + 1 from `user` where 1 != 1 union select user_id from user_extra where 1 != 1) as dt where 1 != 1", - "Query": "select id, weight_string(id), weight_string(id) from (select id from `user` union select id + 1 from `user` union select user_id from user_extra) as dt", + "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select id + 1 from `user` where 1 != 1 union select user_id from user_extra where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id) from (select id from `user` union select id + 1 from `user` union select user_id from user_extra) as dt", "Table": "`user`, user_extra" } ] From 6b4a544b6cbd1f20f7b55a8c6a1310961a16be08 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Mon, 7 Aug 2023 18:05:13 +0200 Subject: [PATCH 41/44] remove unneeded projections Signed-off-by: Andres Taylor --- .../planbuilder/operators/projection.go | 30 ++-- .../planbuilder/testdata/union_cases.json | 157 ++++++++---------- 2 files changed, 86 insertions(+), 101 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/projection.go b/go/vt/vtgate/planbuilder/operators/projection.go index 50857791209..7233d7058e9 100644 --- a/go/vt/vtgate/planbuilder/operators/projection.go +++ b/go/vt/vtgate/planbuilder/operators/projection.go @@ -303,21 +303,24 @@ func (p *Projection) ShortDescription() string { } func (p *Projection) Compact(ctx *plancontext.PlanningContext) (ops.Operator, *rewrite.ApplyResult, error) { - if !p.isDerived() { - // for projections that are not derived tables, we can check if it is safe to remove or not - needed := false - for i, projection := range p.Projections { - e, ok := projection.(Offset) - if !ok || e.Offset != i { - needed = true - break - } - } - if !needed { - return p.Source, rewrite.NewTree("removed projection only passing through the input", p), nil + if p.isDerived() { + return p, rewrite.SameTree, nil + } + + // for projections that are not derived tables, we can check if it is safe to remove or not + needed := false + for i, projection := range p.Projections { + e, ok := projection.(Offset) + if !ok || e.Offset != i { + needed = true + break } } + if !needed { + return p.Source, rewrite.NewTree("removed projection only passing through the input", p), nil + } + switch src := p.Source.(type) { case *Route: return p.compactWithRoute(ctx, src) @@ -428,6 +431,9 @@ func (p *Projection) planOffsets(ctx *plancontext.PlanningContext) error { } } + p.TableID = nil + p.Alias = "" + return nil } diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 82e7bcd27ba..ac115f1318e 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -785,29 +785,22 @@ "QueryType": "SELECT", "Original": "select * from ((select id from user union select id+1 from user) union select user_id from user_extra) as t", "Instructions": { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" ], + "ResultColumns": 1, "Inputs": [ { - "OperatorType": "Distinct", - "Collations": [ - "(0:1)" - ], - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select id + 1 from `user` where 1 != 1 union select user_id from user_extra where 1 != 1) as dt where 1 != 1", - "Query": "select id, weight_string(id) from (select id from `user` union select id + 1 from `user` union select user_id from user_extra) as dt", - "Table": "`user`, user_extra" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from (select id from `user` where 1 != 1 union select id + 1 from `user` where 1 != 1 union select user_id from user_extra where 1 != 1) as dt where 1 != 1", + "Query": "select id, weight_string(id) from (select id from `user` union select id + 1 from `user` union select user_id from user_extra) as dt", + "Table": "`user`, user_extra" } ] }, @@ -1013,49 +1006,41 @@ "TableName": "`user`_`user`", "Inputs": [ { - "OperatorType": "SimpleProjection", - "Columns": [ - 0 - ], + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", + "OperatorType": "Limit", + "Count": "INT64(5)", "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(5)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) ASC", - "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", - "Table": "`user`" - } - ] - }, + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) ASC", + "Query": "select id, weight_string(id) from `user` order by id asc limit :__upper_limit", + "Table": "`user`" + } + ] + }, + { + "OperatorType": "Limit", + "Count": "INT64(5)", + "Inputs": [ { - "OperatorType": "Limit", - "Count": "INT64(5)", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", - "OrderBy": "(0|1) DESC", - "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", - "Table": "`user`" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id, weight_string(id) from `user` where 1 != 1", + "OrderBy": "(0|1) DESC", + "Query": "select id, weight_string(id) from `user` order by id desc limit :__upper_limit", + "Table": "`user`" } ] } @@ -1156,41 +1141,35 @@ ], "Inputs": [ { - "OperatorType": "Projection", - "Expressions": null, + "OperatorType": "Distinct", + "Collations": [ + "(0:1)" + ], "Inputs": [ { - "OperatorType": "Distinct", - "Collations": [ - "(0:1)" - ], + "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Concatenate", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id + 42 as foo, weight_string(id + 42) from `user` where 1 != 1", - "Query": "select distinct id + 42 as foo, weight_string(id + 42) from `user`", - "Table": "`user`" - }, - { - "OperatorType": "Route", - "Variant": "Unsharded", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 + id as foo, weight_string(1 + id) from unsharded where 1 != 1", - "Query": "select distinct 1 + id as foo, weight_string(1 + id) from unsharded", - "Table": "unsharded" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id + 42 as foo, weight_string(id + 42) from `user` where 1 != 1", + "Query": "select distinct id + 42 as foo, weight_string(id + 42) from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select 1 + id as foo, weight_string(1 + id) from unsharded where 1 != 1", + "Query": "select distinct 1 + id as foo, weight_string(1 + id) from unsharded", + "Table": "unsharded" } ] } From 5abffd69e6d113435694c0a59c8304482c55f967 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Mon, 7 Aug 2023 19:18:09 +0200 Subject: [PATCH 42/44] remove weightstring for literal values Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/testdata/aggr_cases.json | 15 +++++++-------- go/vt/vtgate/semantics/semantic_state.go | 15 ++++++++------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json index 709dada2dec..f431acc8b02 100644 --- a/go/vt/vtgate/planbuilder/testdata/aggr_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/aggr_cases.json @@ -5932,21 +5932,20 @@ "OperatorType": "Aggregate", "Variant": "Ordered", "Aggregates": "count_star(0)", - "GroupBy": "(1|2)", + "GroupBy": "1", "Inputs": [ { "OperatorType": "SimpleProjection", "Columns": [ - 3, - 1, - 2 + 2, + 1 ], "Inputs": [ { "OperatorType": "Aggregate", "Variant": "Ordered", - "Aggregates": "sum_count_star(0) AS count(*), any_value(3)", - "GroupBy": "(1|2)", + "Aggregates": "sum_count_star(0) AS count(*), any_value(2)", + "GroupBy": "1", "Inputs": [ { "OperatorType": "Route", @@ -5955,8 +5954,8 @@ "Name": "user", "Sharded": true }, - "FieldQuery": "select count(*), .0, weight_string(.0), 1 from `user` where 1 != 1 group by .0, weight_string(.0)", - "Query": "select count(*), .0, weight_string(.0), 1 from `user` group by .0, weight_string(.0)", + "FieldQuery": "select count(*), .0, 1 from `user` where 1 != 1 group by .0", + "Query": "select count(*), .0, 1 from `user` group by .0", "Table": "`user`" } ] diff --git a/go/vt/vtgate/semantics/semantic_state.go b/go/vt/vtgate/semantics/semantic_state.go index fd248a8ed15..24ca5db5eef 100644 --- a/go/vt/vtgate/semantics/semantic_state.go +++ b/go/vt/vtgate/semantics/semantic_state.go @@ -299,15 +299,16 @@ func (st *SemTable) TypeForExpr(e sqlparser.Expr) (sqltypes.Type, collations.ID, // NeedsWeightString returns true if the given expression needs weight_string to do safe comparisons func (st *SemTable) NeedsWeightString(e sqlparser.Expr) bool { - _, isWs := e.(*sqlparser.WeightStringFuncExpr) - if isWs { + switch e := e.(type) { + case *sqlparser.WeightStringFuncExpr, *sqlparser.Literal: return false + default: + typ, found := st.ExprTypes[e] + if !found { + return true + } + return typ.Collation == collations.Unknown && !sqltypes.IsNumber(typ.Type) } - typ, found := st.ExprTypes[e] - if !found { - return true - } - return typ.Collation == collations.Unknown && !sqltypes.IsNumber(typ.Type) } func (st *SemTable) DefaultCollation() collations.ID { From 20212064d104c5436fb3c63047bc6415859ec939 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Mon, 7 Aug 2023 19:42:10 +0200 Subject: [PATCH 43/44] remove any DISTINCTs we still have not pushed down Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/operators/phases.go | 12 ++++ .../planbuilder/testdata/union_cases.json | 64 +++++++------------ 2 files changed, 36 insertions(+), 40 deletions(-) diff --git a/go/vt/vtgate/planbuilder/operators/phases.go b/go/vt/vtgate/planbuilder/operators/phases.go index e2e4bb85736..44e86be5813 100644 --- a/go/vt/vtgate/planbuilder/operators/phases.go +++ b/go/vt/vtgate/planbuilder/operators/phases.go @@ -60,6 +60,18 @@ func getPhases() []Phase { // add the necessary Ordering operators for them Name: "add ORDER BY to aggregations above the route and add GROUP BY to aggregations on the RHS of join", action: addOrderBysForAggregations, + }, { + Name: "remove Distinct operator that are not required and still above a route", + action: func(ctx *plancontext.PlanningContext, op ops.Operator) (ops.Operator, error) { + return rewrite.BottomUp(op, TableID, func(innerOp ops.Operator, _ semantics.TableSet, _ bool) (ops.Operator, *rewrite.ApplyResult, error) { + d, ok := innerOp.(*Distinct) + if !ok || d.Required { + return innerOp, rewrite.SameTree, nil + } + + return d.Source, rewrite.NewTree("removed distinct not required that was not pushed under route", d), nil + }, stopAtRoute) + }, }} } diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index ac115f1318e..b718065b9b5 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -717,54 +717,38 @@ "OperatorType": "Concatenate", "Inputs": [ { - "OperatorType": "Distinct", - "Collations": [ - "0" - ], + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "sum_count_star(0) AS s", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Scalar", - "Aggregates": "sum_count_star(0) AS s", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select count(*) as s from `user` where 1 != 1", - "Query": "select count(*) as s from `user`", - "Table": "`user`" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select count(*) as s from `user` where 1 != 1", + "Query": "select count(*) as s from `user`", + "Table": "`user`" } ] }, { - "OperatorType": "Distinct", - "Collations": [ - "0" - ], + "OperatorType": "Aggregate", + "Variant": "Scalar", + "Aggregates": "sum_count_star(0) AS s", "Inputs": [ { - "OperatorType": "Aggregate", - "Variant": "Scalar", - "Aggregates": "sum_count_star(0) AS s", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "Scatter", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select count(*) as s from music where 1 != 1", - "Query": "select count(*) as s from music", - "Table": "music" - } - ] + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select count(*) as s from music where 1 != 1", + "Query": "select count(*) as s from music", + "Table": "music" } ] } From ff8d3f1dbc13b2f8689c7a11668245f3259efd1d Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Tue, 8 Aug 2023 11:30:12 +0530 Subject: [PATCH 44/44] fix test query Signed-off-by: Harshit Gangal --- .../vtgate/queries/aggregation/aggregation_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go b/go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go index 5f1211a3bad..91073d43d2e 100644 --- a/go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go +++ b/go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go @@ -78,12 +78,12 @@ func TestGroupBy(t *testing.T) { mcmp.Exec("insert into t3(id5, id6, id7) values(1,1,2), (2,2,4), (3,2,4), (4,1,2), (5,1,2), (6,3,6)") // test ordering and group by int column mcmp.AssertMatches("select id6, id7, count(*) k from t3 group by id6, id7 order by k", `[[INT64(3) INT64(6) INT64(1)] [INT64(2) INT64(4) INT64(2)] [INT64(1) INT64(2) INT64(3)]]`) - mcmp.AssertMatches("select /*vt+ PLANNER=Gen4 */ id6+id7, count(*) k from t3 group by id6+id7 order by k", `[[INT64(9) INT64(1)] [INT64(6) INT64(2)] [INT64(3) INT64(3)]]`) + mcmp.AssertMatches("select id6+id7, count(*) k from t3 group by id6+id7 order by k", `[[INT64(9) INT64(1)] [INT64(6) INT64(2)] [INT64(3) INT64(3)]]`) // Test the same queries in streaming mode utils.Exec(t, mcmp.VtConn, "set workload = olap") mcmp.AssertMatches("select id6, id7, count(*) k from t3 group by id6, id7 order by k", `[[INT64(3) INT64(6) INT64(1)] [INT64(2) INT64(4) INT64(2)] [INT64(1) INT64(2) INT64(3)]]`) - mcmp.AssertMatches("select /*vt+ PLANNER=Gen4 */ id6+id7, count(*) k from t3 group by id6+id7 order by k", `[[INT64(9) INT64(1)] [INT64(6) INT64(2)] [INT64(3) INT64(3)]]`) + mcmp.AssertMatches("select id6+id7, count(*) k from t3 group by id6+id7 order by k", `[[INT64(9) INT64(1)] [INT64(6) INT64(2)] [INT64(3) INT64(3)]]`) } func TestEqualFilterOnScatter(t *testing.T) { @@ -378,7 +378,7 @@ func TestAggregateAnyValue(t *testing.T) { mcmp.AssertMatches("SELECT t1.shardKey, t1.name, count(t2.id) FROM t1 JOIN t2 ON t1.value != t2.shardKey GROUP BY t1.t1_id", `[[INT64(1) VARCHAR("name 1") INT64(2)] [INT64(2) VARCHAR("name 2") INT64(2)]]`) mcmp.Exec("set sql_mode=''") - mcmp.AssertMatches("select /*vt+ PLANNER=Gen4 */ tbl0.comm, count(*) from emp as tbl0, emp as tbl1 where tbl0.empno = tbl1.deptno", `[[NULL INT64(0)]]`) + mcmp.AssertMatches("select tbl0.comm, count(*) from emp as tbl0, emp as tbl1 where tbl0.empno = tbl1.deptno", `[[NULL INT64(0)]]`) } // TestAggregateLeftJoin tests that aggregates work with left joins and does not ignore the count when column value does not match the right side table. @@ -443,16 +443,16 @@ func TestBuggyQueries(t *testing.T) { mcmp.Exec("insert into t10(k, a, b) values (0, 100, 10), (10, 200, 20), (20, null, null)") - mcmp.AssertMatches("select /*vt+ PLANNER=Gen4 */ sum(t1.a) from t10 as t1, t10 as t2", + mcmp.AssertMatches("select sum(t1.a) from t10 as t1, t10 as t2", `[[DECIMAL(900)]]`) - mcmp.AssertMatches("selectt1.a, sum(t1.a), count(*), t1.a, sum(t1.a), count(*) from t10 as t1, t10 as t2 group by t1.a", + mcmp.AssertMatches("select t1.a, sum(t1.a), count(*), t1.a, sum(t1.a), count(*) from t10 as t1, t10 as t2 group by t1.a", "[[NULL NULL INT64(3) NULL NULL INT64(3)] "+ "[INT32(100) DECIMAL(300) INT64(3) INT32(100) DECIMAL(300) INT64(3)] "+ "[INT32(200) DECIMAL(600) INT64(3) INT32(200) DECIMAL(600) INT64(3)]]") - mcmp.Exec("selectsum(tbl1.a), min(tbl0.b) from t10 as tbl0, t10 as tbl1 left join t10 as tbl2 on tbl1.a = tbl2.a and tbl1.b = tbl2.k") - mcmp.Exec("selectcount(*) from t10 left join t10 as t11 on t10.a = t11.b where t11.a") + mcmp.Exec("select sum(tbl1.a), min(tbl0.b) from t10 as tbl0, t10 as tbl1 left join t10 as tbl2 on tbl1.a = tbl2.a and tbl1.b = tbl2.k") + mcmp.Exec("select count(*) from t10 left join t10 as t11 on t10.a = t11.b where t11.a") } func TestMinMaxAcrossJoins(t *testing.T) {