diff --git a/go/vt/vtgate/planbuilder/plan_test.go b/go/vt/vtgate/planbuilder/plan_test.go index ffc014d2648..583a105f6c9 100644 --- a/go/vt/vtgate/planbuilder/plan_test.go +++ b/go/vt/vtgate/planbuilder/plan_test.go @@ -218,6 +218,23 @@ func TestOne(t *testing.T) { testFile(t, "onecase.txt", "", vschema, true) } +func TestRubyOnRailsQueries(t *testing.T) { + vschemaWrapper := &vschemaWrapper{ + v: loadSchema(t, "rails_schema_test.json"), + sysVarEnabled: true, + } + + testOutputTempDir, err := ioutil.TempDir("", "plan_test") + require.NoError(t, err) + defer func() { + if !t.Failed() { + os.RemoveAll(testOutputTempDir) + } + }() + + testFile(t, "rails_cases.txt", testOutputTempDir, vschemaWrapper, true) +} + func TestOLTP(t *testing.T) { vschemaWrapper := &vschemaWrapper{ v: loadSchema(t, "oltp_schema_test.json"), diff --git a/go/vt/vtgate/planbuilder/route_planning.go b/go/vt/vtgate/planbuilder/route_planning.go index ee21bfe4030..427fa64b958 100644 --- a/go/vt/vtgate/planbuilder/route_planning.go +++ b/go/vt/vtgate/planbuilder/route_planning.go @@ -17,7 +17,6 @@ limitations under the License. package planbuilder import ( - "fmt" "io" "sort" @@ -405,82 +404,119 @@ func stripDownQuery(from, to sqlparser.SelectStatement) error { } func pushJoinPredicate(ctx *planningContext, exprs []sqlparser.Expr, tree queryTree) (queryTree, error) { + if len(exprs) == 0 { + return tree, nil + } switch node := tree.(type) { case *routeTree: - plan := node.clone().(*routeTree) - err := plan.addPredicate(ctx, exprs...) + return pushJoinPredicateOnRoute(ctx, exprs, node) + case *joinTree: + return pushJoinPredicateOnJoin(ctx, exprs, node) + case *derivedTree: + return pushJoinPredicateOnDerived(ctx, exprs, node) + case *vindexTree: + // vindexFunc cannot accept predicates from the other side of a join + return node, nil + default: + return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "BUG: unknown type %T", node) + } +} + +func pushJoinPredicateOnRoute(ctx *planningContext, exprs []sqlparser.Expr, node *routeTree) (queryTree, error) { + plan := node.clone().(*routeTree) + err := plan.addPredicate(ctx, exprs...) + if err != nil { + return nil, err + } + return plan, nil +} + +func pushJoinPredicateOnDerived(ctx *planningContext, exprs []sqlparser.Expr, node *derivedTree) (queryTree, error) { + plan := node.clone().(*derivedTree) + + newExpressions := make([]sqlparser.Expr, 0, len(exprs)) + for _, expr := range exprs { + tblInfo, err := ctx.semTable.TableInfoForExpr(expr) if err != nil { return nil, err } - return plan, nil + rewritten, err := semantics.RewriteDerivedExpression(expr, tblInfo) + if err != nil { + return nil, err + } + newExpressions = append(newExpressions, rewritten) + } - case *joinTree: - node = node.clone().(*joinTree) - - // we break up the predicates so that colnames from the LHS are replaced by arguments - var rhsPreds []sqlparser.Expr - var lhsColumns []*sqlparser.ColName - var lhsVarsName []string - lhsSolves := node.lhs.tableID() - for _, expr := range exprs { - bvName, cols, predicate, err := breakPredicateInLHSandRHS(expr, ctx.semTable, lhsSolves) - if err != nil { - return nil, err - } - lhsColumns = append(lhsColumns, cols...) - lhsVarsName = append(lhsVarsName, bvName...) - rhsPreds = append(rhsPreds, predicate) + newInner, err := pushJoinPredicate(ctx, newExpressions, plan.inner) + if err != nil { + return nil, err + } + + plan.inner = newInner + return plan, nil +} + +func pushJoinPredicateOnJoin(ctx *planningContext, exprs []sqlparser.Expr, node *joinTree) (queryTree, error) { + node = node.clone().(*joinTree) + + var rhsPreds []sqlparser.Expr + var lhsPreds []sqlparser.Expr + var lhsColumns []*sqlparser.ColName + var lhsVarsName []string + + for _, expr := range exprs { + // We find the dependencies for the given expression and if they are solved entirely by one + // side of the join tree, then we push the predicate there and do not break it into parts. + // In case a predicate has no dependencies, then it is pushed to both sides so that we can filter + // rows as early as possible making join cheaper on the vtgate level. + depsForExpr := ctx.semTable.RecursiveDeps(expr) + singleSideDeps := false + if depsForExpr.IsSolvedBy(node.lhs.tableID()) { + lhsPreds = append(lhsPreds, expr) + singleSideDeps = true } - if lhsColumns != nil && lhsVarsName != nil { - idxs, err := node.pushOutputColumns(lhsColumns, ctx.semTable) - if err != nil { - return nil, err - } - for i, idx := range idxs { - node.vars[lhsVarsName[i]] = idx - } + if depsForExpr.IsSolvedBy(node.rhs.tableID()) { + rhsPreds = append(rhsPreds, expr) + singleSideDeps = true } - rhsPlan, err := pushJoinPredicate(ctx, rhsPreds, node.rhs) - if err != nil { - return nil, err + if singleSideDeps { + continue } - return &joinTree{ - lhs: node.lhs, - rhs: rhsPlan, - outer: node.outer, - vars: node.vars, - }, nil - case *derivedTree: - plan := node.clone().(*derivedTree) - - newExpressions := make([]sqlparser.Expr, 0, len(exprs)) - for _, expr := range exprs { - tblInfo, err := ctx.semTable.TableInfoForExpr(expr) - if err != nil { - return nil, err - } - rewritten, err := semantics.RewriteDerivedExpression(expr, tblInfo) - if err != nil { - return nil, err - } - newExpressions = append(newExpressions, rewritten) + bvName, cols, predicate, err := breakPredicateInLHSandRHS(expr, ctx.semTable, node.lhs.tableID()) + if err != nil { + return nil, err } + lhsColumns = append(lhsColumns, cols...) + lhsVarsName = append(lhsVarsName, bvName...) + rhsPreds = append(rhsPreds, predicate) + } - newInner, err := pushJoinPredicate(ctx, newExpressions, plan.inner) + if lhsColumns != nil && lhsVarsName != nil { + idxs, err := node.pushOutputColumns(lhsColumns, ctx.semTable) if err != nil { return nil, err } + for i, idx := range idxs { + node.vars[lhsVarsName[i]] = idx + } + } + lhsPlan, err := pushJoinPredicate(ctx, lhsPreds, node.lhs) + if err != nil { + return nil, err + } - plan.inner = newInner - return plan, nil - case *vindexTree: - // vindexFunc cannot accept predicates from the other side of a join - return node, nil - default: - panic(fmt.Sprintf("BUG: unknown type %T", node)) + rhsPlan, err := pushJoinPredicate(ctx, rhsPreds, node.rhs) + if err != nil { + return nil, err } + return &joinTree{ + lhs: lhsPlan, + rhs: rhsPlan, + outer: node.outer, + vars: node.vars, + }, nil } func breakPredicateInLHSandRHS( diff --git a/go/vt/vtgate/planbuilder/testdata/from_cases.txt b/go/vt/vtgate/planbuilder/testdata/from_cases.txt index 4d48dd08447..ee7e268d446 100644 --- a/go/vt/vtgate/planbuilder/testdata/from_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/from_cases.txt @@ -642,7 +642,7 @@ Gen4 plan same as above "Sharded": true }, "FieldQuery": "select e.col from user_extra as e where 1 != 1", - "Query": "select e.col from user_extra as e", + "Query": "select e.col from user_extra as e where e.col = :user_col", "Table": "user_extra" }, { @@ -653,7 +653,7 @@ Gen4 plan same as above "Sharded": false }, "FieldQuery": "select 1 from unsharded as m1 where 1 != 1", - "Query": "select 1 from unsharded as m1 where m1.col = :e_col and :user_col = :e_col", + "Query": "select 1 from unsharded as m1 where m1.col = :e_col", "Table": "unsharded" } ] @@ -2605,21 +2605,22 @@ Gen4 plan same as above "OperatorType": "Join", "Variant": "Join", "JoinColumnIndexes": "-1,-2", - "JoinVars": { - "user_id": 0 - }, "TableName": "`user`_user_extra", "Inputs": [ { "OperatorType": "Route", - "Variant": "SelectScatter", + "Variant": "SelectEqualUnique", "Keyspace": { "Name": "user", "Sharded": true }, "FieldQuery": "select `user`.id, `user`.col1 from `user` where 1 != 1", - "Query": "select `user`.id, `user`.col1 from `user`", - "Table": "`user`" + "Query": "select `user`.id, `user`.col1 from `user` where `user`.id = :ua_id", + "Table": "`user`", + "Values": [ + ":ua_id" + ], + "Vindex": "user_index" }, { "OperatorType": "Route", @@ -2629,7 +2630,7 @@ Gen4 plan same as above "Sharded": true }, "FieldQuery": "select 1 from user_extra where 1 != 1", - "Query": "select 1 from user_extra where :user_id = :ua_id", + "Query": "select 1 from user_extra", "Table": "user_extra" } ] diff --git a/go/vt/vtgate/planbuilder/testdata/rails_cases.txt b/go/vt/vtgate/planbuilder/testdata/rails_cases.txt new file mode 100644 index 00000000000..4dfbf463125 --- /dev/null +++ b/go/vt/vtgate/planbuilder/testdata/rails_cases.txt @@ -0,0 +1,206 @@ +# Author5.joins(books: [{orders: :customer}, :supplier]) +"select author5s.* from author5s join book6s on book6s.author5_id = author5s.id join book6s_order2s on book6s_order2s.book6_id = book6s.id join order2s on order2s.id = book6s_order2s.order2_id join customer2s on customer2s.id = order2s.customer2_id join supplier5s on supplier5s.id = book6s.supplier5_id" +{ + "QueryType": "SELECT", + "Original": "select author5s.* from author5s join book6s on book6s.author5_id = author5s.id join book6s_order2s on book6s_order2s.book6_id = book6s.id join order2s on order2s.id = book6s_order2s.order2_id join customer2s on customer2s.id = order2s.customer2_id join supplier5s on supplier5s.id = book6s.supplier5_id", + "Instructions": { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "-1,-2,-3,-4", + "JoinVars": { + "book6s_supplier5_id": 4 + }, + "TableName": "author5s, book6s_book6s_order2s_order2s_customer2s_supplier5s", + "Inputs": [ + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "-1,-2,-3,-4,-5", + "JoinVars": { + "order2s_customer2_id": 5 + }, + "TableName": "author5s, book6s_book6s_order2s_order2s_customer2s", + "Inputs": [ + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "-1,-2,-3,-4,-5,1", + "JoinVars": { + "book6s_order2s_order2_id": 5 + }, + "TableName": "author5s, book6s_book6s_order2s_order2s", + "Inputs": [ + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "-1,-2,-3,-4,-5,1", + "JoinVars": { + "book6s_id": 5 + }, + "TableName": "author5s, book6s_book6s_order2s", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "SelectScatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select author5s.id, author5s.`name`, author5s.created_at, author5s.updated_at, book6s.supplier5_id, book6s.id from author5s join book6s on book6s.author5_id = author5s.id where 1 != 1", + "Query": "select author5s.id, author5s.`name`, author5s.created_at, author5s.updated_at, book6s.supplier5_id, book6s.id from author5s join book6s on book6s.author5_id = author5s.id", + "Table": "author5s, book6s" + }, + { + "OperatorType": "Route", + "Variant": "SelectEqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select book6s_order2s.order2_id from book6s_order2s where 1 != 1", + "Query": "select book6s_order2s.order2_id from book6s_order2s where book6s_order2s.book6_id = :book6s_id", + "Table": "book6s_order2s", + "Values": [ + ":book6s_id" + ], + "Vindex": "binary_md5" + } + ] + }, + { + "OperatorType": "Route", + "Variant": "SelectScatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select order2s.customer2_id from order2s where 1 != 1", + "Query": "select order2s.customer2_id from order2s where order2s.id = :book6s_order2s_order2_id", + "Table": "order2s" + } + ] + }, + { + "OperatorType": "Route", + "Variant": "SelectEqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 1 from customer2s where 1 != 1", + "Query": "select 1 from customer2s where customer2s.id = :order2s_customer2_id", + "Table": "customer2s", + "Values": [ + ":order2s_customer2_id" + ], + "Vindex": "binary_md5" + } + ] + }, + { + "OperatorType": "Route", + "Variant": "SelectEqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 1 from supplier5s where 1 != 1", + "Query": "select 1 from supplier5s where supplier5s.id = :book6s_supplier5_id", + "Table": "supplier5s", + "Values": [ + ":book6s_supplier5_id" + ], + "Vindex": "binary_md5" + } + ] + } +} +{ + "QueryType": "SELECT", + "Original": "select author5s.* from author5s join book6s on book6s.author5_id = author5s.id join book6s_order2s on book6s_order2s.book6_id = book6s.id join order2s on order2s.id = book6s_order2s.order2_id join customer2s on customer2s.id = order2s.customer2_id join supplier5s on supplier5s.id = book6s.supplier5_id", + "Instructions": { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "1,2,3,4", + "JoinVars": { + "order2s_id": 0 + }, + "TableName": "customer2s, order2s_author5s, book6s_book6s_order2s_supplier5s", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "SelectScatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select order2s.id from order2s, customer2s where 1 != 1", + "Query": "select order2s.id from order2s, customer2s where customer2s.id = order2s.customer2_id", + "Table": "customer2s, order2s" + }, + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "-1,-2,-3,-4", + "JoinVars": { + "book6s_supplier5_id": 0 + }, + "TableName": "author5s, book6s_book6s_order2s_supplier5s", + "Inputs": [ + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "-3,-4,-5,-6", + "JoinVars": { + "book6s_id": 0 + }, + "TableName": "author5s, book6s_book6s_order2s", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "SelectScatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select book6s.id, book6s.supplier5_id, author5s.id as id, author5s.`name` as `name`, author5s.created_at as created_at, author5s.updated_at as updated_at from author5s, book6s where 1 != 1", + "Query": "select book6s.id, book6s.supplier5_id, author5s.id as id, author5s.`name` as `name`, author5s.created_at as created_at, author5s.updated_at as updated_at from author5s, book6s where book6s.author5_id = author5s.id", + "Table": "author5s, book6s" + }, + { + "OperatorType": "Route", + "Variant": "SelectEqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 1 from book6s_order2s where 1 != 1", + "Query": "select 1 from book6s_order2s where book6s_order2s.book6_id = :book6s_id and book6s_order2s.order2_id = :order2s_id", + "Table": "book6s_order2s", + "Values": [ + ":book6s_id" + ], + "Vindex": "binary_md5" + } + ] + }, + { + "OperatorType": "Route", + "Variant": "SelectEqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 1 from supplier5s where 1 != 1", + "Query": "select 1 from supplier5s where supplier5s.id = :book6s_supplier5_id", + "Table": "supplier5s", + "Values": [ + ":book6s_supplier5_id" + ], + "Vindex": "binary_md5" + } + ] + } + ] + } +} diff --git a/go/vt/vtgate/planbuilder/testdata/rails_schema_test.json b/go/vt/vtgate/planbuilder/testdata/rails_schema_test.json new file mode 100644 index 00000000000..26e0ec1dec7 --- /dev/null +++ b/go/vt/vtgate/planbuilder/testdata/rails_schema_test.json @@ -0,0 +1,321 @@ +{ + "keyspaces": { + "user": { + "sharded": true, + "vindexes": { + "binary_md5": { + "type": "hash_test" + } + }, + "tables": { + "order2s": { + "column_vindexes": [ + { + "columns": [ + "customer2_id" + ], + "name": "binary_md5" + } + ], + "auto_increment": { + "column": "id", + "sequence": "order2s_seq" + }, + "columns": [ + { + "name": "id", + "type": "INT64" + }, + { + "name": "customer2_id", + "type": "INT64" + }, + { + "name": "status", + "type": "INT32" + }, + { + "name": "created_at", + "type": "DATETIME" + }, + { + "name": "updated_at", + "type": "DATETIME" + } + ], + "column_list_authoritative": true + }, + "book6s": { + "column_vindexes": [ + { + "columns": [ + "author5_id" + ], + "name": "binary_md5" + } + ], + "auto_increment": { + "column": "id", + "sequence": "book6s_seq" + }, + "columns": [ + { + "name": "id", + "type": "INT64" + }, + { + "name": "author5_id", + "type": "INT64" + }, + { + "name": "supplier5_id", + "type": "INT64" + }, + { + "name": "title", + "type": "VARCHAR" + }, + { + "name": "price", + "type": "INT32" + }, + { + "name": "year_published", + "type": "INT32" + }, + { + "name": "out_of_print", + "type": "INT8" + }, + { + "name": "created_at", + "type": "DATETIME" + }, + { + "name": "updated_at", + "type": "DATETIME" + } + ], + "column_list_authoritative": true + }, + "book6s_order2s": { + "column_vindexes": [ + { + "columns": [ + "book6_id" + ], + "name": "binary_md5" + } + ], + "columns": [ + { + "name": "book6_id", + "type": "INT64" + }, + { + "name": "order2_id", + "type": "INT64" + } + ], + "column_list_authoritative": true + }, + "customer2s": { + "column_vindexes": [ + { + "columns": [ + "id" + ], + "name": "binary_md5" + } + ], + "auto_increment": { + "column": "id", + "sequence": "customer2s_seq" + }, + "columns": [ + { + "name": "id", + "type": "INT64" + }, + { + "name": "first_name", + "type": "VARCHAR" + }, + { + "name": "orders_count", + "type": "INT32" + }, + { + "name": "lock_version", + "type": "INT32" + }, + { + "name": "created_at", + "type": "DATETIME" + }, + { + "name": "updated_at", + "type": "DATETIME" + } + ], + "column_list_authoritative": true + }, + "author5s": { + "column_vindexes": [ + { + "columns": [ + "id" + ], + "name": "binary_md5" + } + ], + "auto_increment": { + "column": "id", + "sequence": "author5s_seq" + }, + "columns": [ + { + "name": "id", + "type": "INT64" + }, + { + "name": "name", + "type": "VARCHAR" + }, + { + "name": "created_at", + "type": "DATETIME" + }, + { + "name": "updated_at", + "type": "DATETIME" + } + ], + "column_list_authoritative": true + }, + "supplier5s": { + "column_vindexes": [ + { + "columns": [ + "id" + ], + "name": "binary_md5" + } + ], + "auto_increment": { + "column": "id", + "sequence": "supplier5s_seq" + }, + "columns": [ + { + "name": "id", + "type": "INT64" + }, + { + "name": "state", + "type": "VARCHAR" + }, + { + "name": "created_at", + "type": "DATETIME" + }, + { + "name": "updated_at", + "type": "DATETIME" + } + ], + "column_list_authoritative": true + } + } + }, + "main": { + "tables": { + "book6s_seq": { + "type": "sequence", + "columns": [ + { + "name": "id", + "type": "INT64" + }, + { + "name": "next_id", + "type": "INT64" + }, + { + "name": "cache", + "type": "INT64" + } + ], + "column_list_authoritative": true + }, + "author5s_seq": { + "type": "sequence", + "columns": [ + { + "name": "id", + "type": "INT64" + }, + { + "name": "next_id", + "type": "INT64" + }, + { + "name": "cache", + "type": "INT64" + } + ], + "column_list_authoritative": true + }, + "supplier5s_seq": { + "type": "sequence", + "columns": [ + { + "name": "id", + "type": "INT64" + }, + { + "name": "next_id", + "type": "INT64" + }, + { + "name": "cache", + "type": "INT64" + } + ], + "column_list_authoritative": true + }, + "customer2s_seq": { + "type": "sequence", + "columns": [ + { + "name": "id", + "type": "INT64" + }, + { + "name": "next_id", + "type": "INT64" + }, + { + "name": "cache", + "type": "INT64" + } + ], + "column_list_authoritative": true + }, + "order2s_seq": { + "type": "sequence", + "columns": [ + { + "name": "predef1" + }, + { + "name": "cache", + "type": "INT64" + } + ], + "column_list_authoritative": true + } + } + } + } +} diff --git a/go/vt/vtgate/planbuilder/testdata/tpch_cases.txt b/go/vt/vtgate/planbuilder/testdata/tpch_cases.txt index b3746a69894..c116fbeaada 100644 --- a/go/vt/vtgate/planbuilder/testdata/tpch_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/tpch_cases.txt @@ -38,32 +38,46 @@ Gen4 error: unsupported: cross-shard correlated subquery { "OperatorType": "Join", "Variant": "Join", - "JoinColumnIndexes": "1,2,-2,-3,3,-4,-5", + "JoinColumnIndexes": "-1,-2,1,2,-3,3,4", "JoinVars": { - "o_orderkey": 0 + "l_orderkey": 0 }, - "TableName": "orders_customer_lineitem", + "TableName": "lineitem_orders_customer", "Inputs": [ + { + "OperatorType": "Route", + "Variant": "SelectScatter", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select l_orderkey, sum(l_extendedprice * (1 - l_discount)) as revenue, weight_string(l_orderkey) from lineitem where 1 != 1", + "Query": "select l_orderkey, sum(l_extendedprice * (1 - l_discount)) as revenue, weight_string(l_orderkey) from lineitem where l_shipdate \u003e date('1995-03-15')", + "Table": "lineitem" + }, { "OperatorType": "Join", "Variant": "Join", - "JoinColumnIndexes": "-2,-3,-4,-5,-6", + "JoinColumnIndexes": "-2,-3,-4,-5", "JoinVars": { - "o_custkey": 0, - "o_orderkey": 0 + "o_custkey": 0 }, "TableName": "orders_customer", "Inputs": [ { "OperatorType": "Route", - "Variant": "SelectScatter", + "Variant": "SelectEqualUnique", "Keyspace": { "Name": "main", "Sharded": true }, - "FieldQuery": "select o_custkey, o_orderkey, o_orderdate, o_shippriority, weight_string(o_orderdate), weight_string(o_shippriority) from orders where 1 != 1", - "Query": "select o_custkey, o_orderkey, o_orderdate, o_shippriority, weight_string(o_orderdate), weight_string(o_shippriority) from orders where o_orderdate \u003c date('1995-03-15')", - "Table": "orders" + "FieldQuery": "select o_custkey, o_orderdate, o_shippriority, weight_string(o_orderdate), weight_string(o_shippriority) from orders where 1 != 1", + "Query": "select o_custkey, o_orderdate, o_shippriority, weight_string(o_orderdate), weight_string(o_shippriority) from orders where o_orderdate \u003c date('1995-03-15') and o_orderkey = :l_orderkey", + "Table": "orders", + "Values": [ + ":l_orderkey" + ], + "Vindex": "hash" }, { "OperatorType": "Route", @@ -81,21 +95,6 @@ Gen4 error: unsupported: cross-shard correlated subquery "Vindex": "hash" } ] - }, - { - "OperatorType": "Route", - "Variant": "SelectEqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select l_orderkey, sum(l_extendedprice * (1 - l_discount)) as revenue, weight_string(l_orderkey) from lineitem where 1 != 1", - "Query": "select l_orderkey, sum(l_extendedprice * (1 - l_discount)) as revenue, weight_string(l_orderkey) from lineitem where l_shipdate \u003e date('1995-03-15') and l_orderkey = :o_orderkey", - "Table": "lineitem", - "Values": [ - ":o_orderkey" - ], - "Vindex": "lineitem_map" } ] } @@ -203,39 +202,79 @@ Gen4 plan same as above "GroupBy": "(0|8), (1|9), (3|10), (6|11), (4|12), (5|13), (7|14)", "Inputs": [ { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "-1,-2,1,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14", - "JoinVars": { - "c_custkey": 0 - }, - "TableName": "customer_nation_orders_lineitem", + "OperatorType": "Sort", + "Variant": "Memory", + "OrderBy": "(0|8) ASC, (1|9) ASC, (3|10) ASC, (6|11) ASC, (4|12) ASC, (5|13) ASC, (7|14) ASC", "Inputs": [ { - "OperatorType": "Sort", - "Variant": "Memory", - "OrderBy": "(0|7) ASC, (1|8) ASC, (2|9) ASC, (5|10) ASC, (3|11) ASC, (4|12) ASC, (6|13) ASC", + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "1,2,-2,3,4,5,6,7,8,9,10,11,12,13,14", + "JoinVars": { + "o_custkey": 0 + }, + "TableName": "orders_lineitem_customer_nation", "Inputs": [ + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "-2,1", + "JoinVars": { + "o_orderkey": 0 + }, + "TableName": "orders_lineitem", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "SelectScatter", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select o_orderkey, o_custkey from orders where 1 != 1", + "Query": "select o_orderkey, o_custkey from orders where o_orderdate \u003e= date('1993-10-01') and o_orderdate \u003c date('1993-10-01') + interval '3' month", + "Table": "orders" + }, + { + "OperatorType": "Route", + "Variant": "SelectEqualUnique", + "Keyspace": { + "Name": "main", + "Sharded": true + }, + "FieldQuery": "select sum(l_extendedprice * (1 - l_discount)) as revenue from lineitem where 1 != 1", + "Query": "select sum(l_extendedprice * (1 - l_discount)) as revenue from lineitem where l_returnflag = 'R' and l_orderkey = :o_orderkey", + "Table": "lineitem", + "Values": [ + ":o_orderkey" + ], + "Vindex": "lineitem_map" + } + ] + }, { "OperatorType": "Join", "Variant": "Join", "JoinColumnIndexes": "-2,-3,-4,1,-5,-6,-7,-8,-9,-10,-11,2,-12,-13", "JoinVars": { - "c_custkey": 0, "c_nationkey": 0 }, "TableName": "customer_nation", "Inputs": [ { "OperatorType": "Route", - "Variant": "SelectScatter", + "Variant": "SelectEqualUnique", "Keyspace": { "Name": "main", "Sharded": true }, "FieldQuery": "select c_nationkey, c_custkey, c_name, c_acctbal, c_address, c_phone, c_comment, weight_string(c_custkey), weight_string(c_name), weight_string(c_acctbal), weight_string(c_phone), weight_string(c_address), weight_string(c_comment) from customer where 1 != 1", - "Query": "select c_nationkey, c_custkey, c_name, c_acctbal, c_address, c_phone, c_comment, weight_string(c_custkey), weight_string(c_name), weight_string(c_acctbal), weight_string(c_phone), weight_string(c_address), weight_string(c_comment) from customer", - "Table": "customer" + "Query": "select c_nationkey, c_custkey, c_name, c_acctbal, c_address, c_phone, c_comment, weight_string(c_custkey), weight_string(c_name), weight_string(c_acctbal), weight_string(c_phone), weight_string(c_address), weight_string(c_comment) from customer where c_custkey = :o_custkey", + "Table": "customer", + "Values": [ + ":o_custkey" + ], + "Vindex": "hash" }, { "OperatorType": "Route", @@ -255,44 +294,6 @@ Gen4 plan same as above ] } ] - }, - { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "1", - "JoinVars": { - "o_custkey": 0, - "o_orderkey": 0 - }, - "TableName": "orders_lineitem", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "SelectScatter", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select o_orderkey, o_custkey from orders where 1 != 1", - "Query": "select o_orderkey, o_custkey from orders where o_orderdate \u003e= date('1993-10-01') and o_orderdate \u003c date('1993-10-01') + interval '3' month", - "Table": "orders" - }, - { - "OperatorType": "Route", - "Variant": "SelectEqualUnique", - "Keyspace": { - "Name": "main", - "Sharded": true - }, - "FieldQuery": "select sum(l_extendedprice * (1 - l_discount)) as revenue from lineitem where 1 != 1", - "Query": "select sum(l_extendedprice * (1 - l_discount)) as revenue from lineitem where l_returnflag = 'R' and l_orderkey = :o_orderkey and :c_custkey = :o_custkey", - "Table": "lineitem", - "Values": [ - ":o_orderkey" - ], - "Vindex": "lineitem_map" - } - ] } ] } diff --git a/go/vt/vtgate/planbuilder/testdata/wireup_cases.txt b/go/vt/vtgate/planbuilder/testdata/wireup_cases.txt index 54cb40259bd..487b1d97583 100644 --- a/go/vt/vtgate/planbuilder/testdata/wireup_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/wireup_cases.txt @@ -491,7 +491,7 @@ "Sharded": true }, "FieldQuery": "select u1.col, u1.id from `user` as u1 where 1 != 1", - "Query": "select u1.col, u1.id from `user` as u1", + "Query": "select u1.col, u1.id from `user` as u1 where u1.col = :u3_col", "Table": "`user`" }, { @@ -502,7 +502,7 @@ "Sharded": true }, "FieldQuery": "select 1 from `user` as u2 where 1 != 1", - "Query": "select 1 from `user` as u2 where u2.col = :u1_col and :u3_col = :u1_col", + "Query": "select 1 from `user` as u2 where u2.col = :u1_col", "Table": "`user`" } ] @@ -655,7 +655,7 @@ "Sharded": true }, "FieldQuery": "select u1.col, u1.id from `user` as u1 where 1 != 1", - "Query": "select u1.col, u1.id from `user` as u1", + "Query": "select u1.col, u1.id from `user` as u1 where u1.col = :u4_col", "Table": "`user`" }, { @@ -666,7 +666,7 @@ "Sharded": true }, "FieldQuery": "select 1 from `user` as u3 where 1 != 1", - "Query": "select 1 from `user` as u3 where u3.id = :u1_col and :u4_col = :u1_col", + "Query": "select 1 from `user` as u3 where u3.id = :u1_col", "Table": "`user`", "Values": [ ":u1_col"