From 68780a78bb5f9dafcc3e72b8f2706b7275a8c408 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Thu, 15 Jul 2021 17:30:17 +0530 Subject: [PATCH 1/9] gen4: extracting routing information from predicates for system table query Signed-off-by: Harshit Gangal --- go/vt/vtgate/planbuilder/jointree.go | 6 ++++++ .../planbuilder/jointree_transformers.go | 12 ++++++----- go/vt/vtgate/planbuilder/route_planning.go | 10 ++++++++-- go/vt/vtgate/planbuilder/system_tables.go | 20 +++++++++++++++++++ .../planbuilder/testdata/filter_cases.txt | 3 +++ .../planbuilder/testdata/from_cases.txt | 6 ++++++ .../planbuilder/testdata/select_cases.txt | 2 ++ .../testdata/unsupported_cases.txt | 20 ------------------- 8 files changed, 52 insertions(+), 27 deletions(-) diff --git a/go/vt/vtgate/planbuilder/jointree.go b/go/vt/vtgate/planbuilder/jointree.go index 8aedd07e00e..ec5420e5320 100644 --- a/go/vt/vtgate/planbuilder/jointree.go +++ b/go/vt/vtgate/planbuilder/jointree.go @@ -19,6 +19,8 @@ package planbuilder import ( "strings" + "vitess.io/vitess/go/vt/vtgate/evalengine" + "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/engine" @@ -95,6 +97,10 @@ type ( // columns needed to feed other plans` columns []*sqlparser.ColName + + // The following two fields are used when routing information_schema queries + SysTableTableSchema []evalengine.Expr + SysTableTableName []evalengine.Expr } joinPlan struct { diff --git a/go/vt/vtgate/planbuilder/jointree_transformers.go b/go/vt/vtgate/planbuilder/jointree_transformers.go index dfa98d649b8..44aae7f5f4a 100644 --- a/go/vt/vtgate/planbuilder/jointree_transformers.go +++ b/go/vt/vtgate/planbuilder/jointree_transformers.go @@ -144,11 +144,13 @@ func transformRoutePlan(n *routePlan) (*route, error) { return &route{ eroute: &engine.Route{ - Opcode: n.routeOpCode, - TableName: strings.Join(tableNames, ", "), - Keyspace: n.keyspace, - Vindex: singleColumn, - Values: n.vindexValues, + Opcode: n.routeOpCode, + TableName: strings.Join(tableNames, ", "), + Keyspace: n.keyspace, + Vindex: singleColumn, + Values: n.vindexValues, + SysTableTableName: n.SysTableTableName, + SysTableTableSchema: n.SysTableTableSchema, }, Select: &sqlparser.Select{ SelectExprs: expressions, diff --git a/go/vt/vtgate/planbuilder/route_planning.go b/go/vt/vtgate/planbuilder/route_planning.go index 91903c2af39..ff345a8835a 100644 --- a/go/vt/vtgate/planbuilder/route_planning.go +++ b/go/vt/vtgate/planbuilder/route_planning.go @@ -568,7 +568,7 @@ func createRoutePlan(table *abstract.QueryTable, solves semantics.TableSet, vsch if err != nil { return nil, err } - return &routePlan{ + rp := &routePlan{ routeOpCode: engine.SelectDBA, solved: solves, // TODO: find keyspace to route using the predicates as in v3 @@ -581,7 +581,13 @@ func createRoutePlan(table *abstract.QueryTable, solves semantics.TableSet, vsch }, }}, predicates: table.Predicates, - }, nil + } + err = rp.findSysInfoRoutingPredicatesGen4() + if err != nil { + return nil, err + } + + return rp, nil } vschemaTable, _, _, _, _, err := vschema.FindTableOrVindex(table.Table) if err != nil { diff --git a/go/vt/vtgate/planbuilder/system_tables.go b/go/vt/vtgate/planbuilder/system_tables.go index 111d86bb41d..c2338d809a4 100644 --- a/go/vt/vtgate/planbuilder/system_tables.go +++ b/go/vt/vtgate/planbuilder/system_tables.go @@ -42,6 +42,26 @@ func (pb *primitiveBuilder) findSysInfoRoutingPredicates(expr sqlparser.Expr, ru return nil } +func (rp *routePlan) findSysInfoRoutingPredicatesGen4() error { + for _, pred := range rp.predicates { + isTableSchema, out, err := extractInfoSchemaRoutingPredicate(pred) + if err != nil { + return err + } + if out == nil { + // we didn't find a predicate to use for routing, continue to look for next predicate + continue + } + + if isTableSchema { + rp.SysTableTableSchema = append(rp.SysTableTableSchema, out) + } else { + rp.SysTableTableName = append(rp.SysTableTableName, out) + } + } + return nil +} + func findOtherComparator(cmp *sqlparser.ComparisonExpr) (bool, sqlparser.Expr, sqlparser.Expr, func(arg sqlparser.Argument)) { if schema, table := isTableSchemaOrName(cmp.Left); schema || table { return schema, cmp.Left, cmp.Right, func(arg sqlparser.Argument) { diff --git a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt index 08422d1fc76..58031deba9d 100644 --- a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt @@ -1969,6 +1969,7 @@ Gen4 plan same as above "Table": "INFORMATION_SCHEMA.`TABLES`" } } +Gen4 plan same as above # table_name predicate against a routed table "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ks' AND TABLE_NAME = 'route1'" @@ -1989,6 +1990,7 @@ Gen4 plan same as above "Table": "INFORMATION_SCHEMA.`TABLES`" } } +Gen4 plan same as above # information_schema query with additional predicates "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ks' and other_column = 42" @@ -2008,6 +2010,7 @@ Gen4 plan same as above "Table": "INFORMATION_SCHEMA.`TABLES`" } } +Gen4 plan same as above # pullout sq after pullout sq "select id from user where not id in (select user_extra.col from user_extra where user_extra.user_id = 42) and id in (select user_extra.col from user_extra where user_extra.user_id = 411)" diff --git a/go/vt/vtgate/planbuilder/testdata/from_cases.txt b/go/vt/vtgate/planbuilder/testdata/from_cases.txt index 83539e37047..247cbca003e 100644 --- a/go/vt/vtgate/planbuilder/testdata/from_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/from_cases.txt @@ -2880,6 +2880,7 @@ Gen4 plan same as above "Table": "information_schema.schemata" } } +Gen4 plan same as above #rails_query 3 "SELECT table_comment FROM information_schema.tables WHERE table_schema = 'schema_name' AND table_name = 'table_name'" @@ -2900,6 +2901,7 @@ Gen4 plan same as above "Table": "information_schema.`tables`" } } +Gen4 plan same as above #rails_query 4 "SELECT fk.referenced_table_name AS 'to_table', fk.referenced_column_name AS 'primary_key',fk.column_name AS 'column',fk.constraint_name AS 'name',rc.update_rule AS 'on_update',rc.delete_rule AS 'on_delete' FROM information_schema.referential_constraints rc JOIN information_schema.key_column_usage fk USING (constraint_schema, constraint_name) WHERE fk.referenced_column_name IS NOT NULL AND fk.table_schema = 'table_schema' AND fk.table_name = 'table_name' AND rc.constraint_schema = 'table_schema' AND rc.table_name = 'table_name'" @@ -2960,6 +2962,7 @@ Gen4 plan same as above "Table": "information_schema.statistics" } } +Gen4 plan same as above #rails_query 7 "SELECT generation_expression FROM information_schema.columns WHERE table_schema = 'table_schema' AND table_name = 'table_name' AND column_name = 'column_name'" @@ -2980,6 +2983,7 @@ Gen4 plan same as above "Table": "information_schema.`columns`" } } +Gen4 plan same as above #rails_query 8 "SELECT id FROM information_schema.processlist WHERE info LIKE '% FOR UPDATE'" @@ -3057,6 +3061,7 @@ Gen4 plan same as above "Table": "information_schema.check_constraints" } } +Gen4 plan same as above # system schema in where clause of information_schema query "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'performance_schema' AND table_name = 'foo'" @@ -3077,6 +3082,7 @@ Gen4 plan same as above "Table": "INFORMATION_SCHEMA.`TABLES`" } } +Gen4 plan same as above # query with parens is planned correctly "select m1.col from (unsharded as m1, unsharded as m2)" diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.txt b/go/vt/vtgate/planbuilder/testdata/select_cases.txt index c4992c4b7ac..a7fe027e933 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.txt @@ -1853,6 +1853,7 @@ Gen4 plan same as above "Table": "information_schema.routines" } } +Gen4 plan same as above #information_schema table sizes "SELECT SUM(data_length + index_length) as size FROM information_schema.TABLES WHERE table_schema = ?" @@ -1872,6 +1873,7 @@ Gen4 plan same as above "Table": "information_schema.`TABLES`" } } +Gen4 plan same as above #information_schema referential contraints "SELECT kcu.constraint_name constraint_name, kcu.column_name column_name, kcu.referenced_table_name referenced_table_name, kcu.referenced_column_name referenced_column_name, kcu.ordinal_position ordinal_position, kcu.table_name table_name, rc.delete_rule delete_rule, rc.update_rule update_rule FROM information_schema.key_column_usage AS kcu INNER JOIN information_schema.referential_constraints AS rc ON kcu.constraint_name = rc.constraint_name WHERE kcu.table_schema = ? AND rc.constraint_schema = ? AND kcu.referenced_column_name IS NOT NULL ORDER BY ordinal_position" diff --git a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt index f8d35069956..5d32673c74b 100644 --- a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt @@ -421,26 +421,6 @@ Gen4 plan same as above "select * from user into outfile s3 'out_file_name'" "INTO is not supported on sharded keyspace" -# unsupported two predicates specifying the database for the same table if they are different -# will fail on run time but will pass on the planbuilder -"SELECT cc.constraint_name AS 'name' FROM information_schema.check_constraints cc WHERE cc.constraint_schema = 'constraint_schema' AND cc.table_schema = 'a'" -{ - "QueryType": "SELECT", - "Original": "SELECT cc.constraint_name AS 'name' FROM information_schema.check_constraints cc WHERE cc.constraint_schema = 'constraint_schema' AND cc.table_schema = 'a'", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select cc.constraint_name as `name` from information_schema.check_constraints as cc where 1 != 1", - "Query": "select cc.constraint_name as `name` from information_schema.check_constraints as cc where cc.constraint_schema = :__vtschemaname and cc.table_schema = :__vtschemaname", - "SysTableTableSchema": "[VARBINARY(\"constraint_schema\"), VARBINARY(\"a\")]", - "Table": "information_schema.check_constraints" - } -} - # create view with Cannot auto-resolve for cross-shard joins "create view user.view_a as select col from user join user_extra" "symbol col not found" From c45cd5ccea3db7d89bf549341c4f5b7c7397faf4 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Thu, 15 Jul 2021 22:51:30 +0530 Subject: [PATCH 2/9] merge system tables routing information when merging join, consolidated all system tables plan tests into its own file Signed-off-by: Harshit Gangal --- go/vt/vtgate/planbuilder/plan_test.go | 1 + go/vt/vtgate/planbuilder/route_planning.go | 8 +- .../planbuilder/testdata/filter_cases.txt | 117 --- .../planbuilder/testdata/from_cases.txt | 369 --------- .../planbuilder/testdata/select_cases.txt | 139 ---- .../testdata/set_sysvar_disabled_cases.txt | 2 + .../testdata/sysschema_default.txt | 1 + .../testdata/systemtables_cases.txt | 723 ++++++++++++++++++ 8 files changed, 732 insertions(+), 628 deletions(-) create mode 100644 go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt diff --git a/go/vt/vtgate/planbuilder/plan_test.go b/go/vt/vtgate/planbuilder/plan_test.go index 4778728ea91..852b0caf4c7 100644 --- a/go/vt/vtgate/planbuilder/plan_test.go +++ b/go/vt/vtgate/planbuilder/plan_test.go @@ -195,6 +195,7 @@ func TestPlan(t *testing.T) { testFile(t, "flush_cases_no_default_keyspace.txt", testOutputTempDir, vschemaWrapper, false) testFile(t, "show_cases_no_default_keyspace.txt", testOutputTempDir, vschemaWrapper, false) testFile(t, "stream_cases.txt", testOutputTempDir, vschemaWrapper, false) + testFile(t, "systemtables_cases.txt", testOutputTempDir, vschemaWrapper, false) } func TestSysVarSetDisabled(t *testing.T) { diff --git a/go/vt/vtgate/planbuilder/route_planning.go b/go/vt/vtgate/planbuilder/route_planning.go index ff345a8835a..c1ddcbb1903 100644 --- a/go/vt/vtgate/planbuilder/route_planning.go +++ b/go/vt/vtgate/planbuilder/route_planning.go @@ -780,9 +780,11 @@ func createRoutePlanForInner(aRoute *routePlan, bRoute *routePlan, newTabletSet predicates: append( append(aRoute.predicates, bRoute.predicates...), joinPredicates...), - keyspace: aRoute.keyspace, - vindexPreds: append(aRoute.vindexPreds, bRoute.vindexPreds...), - leftJoins: append(aRoute.leftJoins, bRoute.leftJoins...), + keyspace: aRoute.keyspace, + vindexPreds: append(aRoute.vindexPreds, bRoute.vindexPreds...), + leftJoins: append(aRoute.leftJoins, bRoute.leftJoins...), + SysTableTableSchema: append(aRoute.SysTableTableSchema, bRoute.SysTableTableSchema...), + SysTableTableName: append(aRoute.SysTableTableName, bRoute.SysTableTableName...), } } diff --git a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt index 58031deba9d..dda43a33e56 100644 --- a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt @@ -1172,24 +1172,6 @@ Gen4 plan same as above } Gen4 plan same as above -# subquery of information_schema with itself -"select * from information_schema.a where id in (select * from information_schema.b)" -{ - "QueryType": "SELECT", - "Original": "select * from information_schema.a where id in (select * from information_schema.b)", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select * from information_schema.a where 1 != 1", - "Query": "select * from information_schema.a where id in (select * from information_schema.b)", - "Table": "information_schema.a" - } -} - # subquery "select u.m from user_extra join user u where u.id in (select m2 from user where user.id = u.id and user_extra.col = user.col) and u.id in (user_extra.col, 1)" { @@ -1913,105 +1895,6 @@ Gen4 plan same as above } Gen4 plan same as above -# query trying to query two different keyspaces at the same time -"SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'user' AND TABLE_SCHEMA = 'main'" -{ - "QueryType": "SELECT", - "Original": "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'user' AND TABLE_SCHEMA = 'main'", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select * from INFORMATION_SCHEMA.`TABLES` where 1 != 1", - "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = :__vtschemaname and TABLE_SCHEMA = :__vtschemaname", - "SysTableTableSchema": "[VARBINARY(\"user\"), VARBINARY(\"main\")]", - "Table": "INFORMATION_SCHEMA.`TABLES`" - } -} - -# information_schema query using database() func -"SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = database()" -{ - "QueryType": "SELECT", - "Original": "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = database()", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select * from INFORMATION_SCHEMA.`TABLES` where 1 != 1", - "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = database()", - "Table": "INFORMATION_SCHEMA.`TABLES`" - } -} -Gen4 plan same as above - -# table_schema predicate the wrong way around -"SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE 'ks' = TABLE_SCHEMA" -{ - "QueryType": "SELECT", - "Original": "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE 'ks' = TABLE_SCHEMA", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select * from INFORMATION_SCHEMA.`TABLES` where 1 != 1", - "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = :__vtschemaname", - "SysTableTableSchema": "[VARBINARY(\"ks\")]", - "Table": "INFORMATION_SCHEMA.`TABLES`" - } -} -Gen4 plan same as above - -# table_name predicate against a routed table -"SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ks' AND TABLE_NAME = 'route1'" -{ - "QueryType": "SELECT", - "Original": "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ks' AND TABLE_NAME = 'route1'", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select * from INFORMATION_SCHEMA.`TABLES` where 1 != 1", - "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = :__vtschemaname and TABLE_NAME = :__vttablename", - "SysTableTableName": "[VARBINARY(\"route1\")]", - "SysTableTableSchema": "[VARBINARY(\"ks\")]", - "Table": "INFORMATION_SCHEMA.`TABLES`" - } -} -Gen4 plan same as above - -# information_schema query with additional predicates -"SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ks' and other_column = 42" -{ - "QueryType": "SELECT", - "Original": "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ks' and other_column = 42", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select * from INFORMATION_SCHEMA.`TABLES` where 1 != 1", - "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = :__vtschemaname and other_column = 42", - "SysTableTableSchema": "[VARBINARY(\"ks\")]", - "Table": "INFORMATION_SCHEMA.`TABLES`" - } -} -Gen4 plan same as above - # pullout sq after pullout sq "select id from user where not id in (select user_extra.col from user_extra where user_extra.user_id = 42) and id in (select user_extra.col from user_extra where user_extra.user_id = 411)" { diff --git a/go/vt/vtgate/planbuilder/testdata/from_cases.txt b/go/vt/vtgate/planbuilder/testdata/from_cases.txt index 247cbca003e..57a2fd9b4d0 100644 --- a/go/vt/vtgate/planbuilder/testdata/from_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/from_cases.txt @@ -74,25 +74,6 @@ Gen4 plan same as above } Gen4 plan same as above -# Single information_schema query -"select col from information_schema.foo" -{ - "QueryType": "SELECT", - "Original": "select col from information_schema.foo", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select col from information_schema.foo where 1 != 1", - "Query": "select col from information_schema.foo", - "Table": "information_schema.foo" - } -} -Gen4 plan same as above - # Multi-table unsharded "select m1.col from unsharded as m1 join unsharded as m2" { @@ -321,25 +302,6 @@ Gen4 plan same as above } Gen4 plan same as above -# ',' join information_schema -"select a.id,b.id from information_schema.a as a, information_schema.b as b" -{ - "QueryType": "SELECT", - "Original": "select a.id,b.id from information_schema.a as a, information_schema.b as b", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select a.id, b.id from information_schema.a as a, information_schema.b as b where 1 != 1", - "Query": "select a.id, b.id from information_schema.a as a, information_schema.b as b", - "Table": "information_schema.a, information_schema.b" - } -} -Gen4 plan same as above - # ',' 3-way join unsharded "select u1.a, u2.a from unsharded u1, unsharded u2, unsharded u3" { @@ -1833,44 +1795,6 @@ Gen4 plan same as above } } -# access to unqualified column names in information_schema -"select * from information_schema.a where b=10" -{ - "QueryType": "SELECT", - "Original": "select * from information_schema.a where b=10", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select * from information_schema.a where 1 != 1", - "Query": "select * from information_schema.a where b = 10", - "Table": "information_schema.a" - } -} -Gen4 plan same as above - -# access to qualified column names in information_schema -"select * from information_schema.a where information_schema.a.b=10" -{ - "QueryType": "SELECT", - "Original": "select * from information_schema.a where information_schema.a.b=10", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select * from information_schema.a where 1 != 1", - "Query": "select * from information_schema.a where information_schema.a.b = 10", - "Table": "information_schema.a" - } -} -Gen4 plan same as above - # join of information_schema with normal table "select unsharded.foo from information_schema.a join unsharded" { @@ -2791,299 +2715,6 @@ Gen4 plan same as above "table t not found" Gen4 plan same as above -# information schema query that uses table_schema -"select column_name from information_schema.columns where table_schema = (select schema())" -{ - "QueryType": "SELECT", - "Original": "select column_name from information_schema.columns where table_schema = (select schema())", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select column_name from information_schema.`columns` where 1 != 1", - "Query": "select column_name from information_schema.`columns` where table_schema = schema()", - "Table": "information_schema.`columns`" - } -} -Gen4 plan same as above - -# information schema join -"select * from information_schema.a join information_schema.b" -{ - "QueryType": "SELECT", - "Original": "select * from information_schema.a join information_schema.b", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select * from information_schema.a join information_schema.b where 1 != 1", - "Query": "select * from information_schema.a join information_schema.b", - "Table": "information_schema.a, information_schema.b" - } -} -{ - "QueryType": "SELECT", - "Original": "select * from information_schema.a join information_schema.b", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select * from information_schema.a, information_schema.b where 1 != 1", - "Query": "select * from information_schema.a, information_schema.b", - "Table": "information_schema.a, information_schema.b" - } -} - -# rails query -"select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as name, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk using (constraint_schema, constraint_name) where fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = ':vtg1' and rc.constraint_schema = database() and rc.table_name = ':vtg1'" -{ - "QueryType": "SELECT", - "Original": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as name, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk using (constraint_schema, constraint_name) where fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = ':vtg1' and rc.constraint_schema = database() and rc.table_name = ':vtg1'", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name where 1 != 1", - "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name where fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = :__vttablename and rc.constraint_schema = database() and rc.table_name = :__vttablename", - "SysTableTableName": "[VARBINARY(\":vtg1\"), VARBINARY(\":vtg1\")]", - "Table": "information_schema.referential_constraints, information_schema.key_column_usage" - } -} - -#rails_query 2 -"SELECT * FROM information_schema.schemata WHERE schema_name = 'user'" -{ - "QueryType": "SELECT", - "Original": "SELECT * FROM information_schema.schemata WHERE schema_name = 'user'", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select * from information_schema.schemata where 1 != 1", - "Query": "select * from information_schema.schemata where schema_name = :__vtschemaname", - "SysTableTableSchema": "[VARBINARY(\"user\")]", - "Table": "information_schema.schemata" - } -} -Gen4 plan same as above - -#rails_query 3 -"SELECT table_comment FROM information_schema.tables WHERE table_schema = 'schema_name' AND table_name = 'table_name'" -{ - "QueryType": "SELECT", - "Original": "SELECT table_comment FROM information_schema.tables WHERE table_schema = 'schema_name' AND table_name = 'table_name'", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select table_comment from information_schema.`tables` where 1 != 1", - "Query": "select table_comment from information_schema.`tables` where table_schema = :__vtschemaname and table_name = :__vttablename", - "SysTableTableName": "[VARBINARY(\"table_name\")]", - "SysTableTableSchema": "[VARBINARY(\"schema_name\")]", - "Table": "information_schema.`tables`" - } -} -Gen4 plan same as above - -#rails_query 4 -"SELECT fk.referenced_table_name AS 'to_table', fk.referenced_column_name AS 'primary_key',fk.column_name AS 'column',fk.constraint_name AS 'name',rc.update_rule AS 'on_update',rc.delete_rule AS 'on_delete' FROM information_schema.referential_constraints rc JOIN information_schema.key_column_usage fk USING (constraint_schema, constraint_name) WHERE fk.referenced_column_name IS NOT NULL AND fk.table_schema = 'table_schema' AND fk.table_name = 'table_name' AND rc.constraint_schema = 'table_schema' AND rc.table_name = 'table_name'" -{ - "QueryType": "SELECT", - "Original": "SELECT fk.referenced_table_name AS 'to_table', fk.referenced_column_name AS 'primary_key',fk.column_name AS 'column',fk.constraint_name AS 'name',rc.update_rule AS 'on_update',rc.delete_rule AS 'on_delete' FROM information_schema.referential_constraints rc JOIN information_schema.key_column_usage fk USING (constraint_schema, constraint_name) WHERE fk.referenced_column_name IS NOT NULL AND fk.table_schema = 'table_schema' AND fk.table_name = 'table_name' AND rc.constraint_schema = 'table_schema' AND rc.table_name = 'table_name'", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name where 1 != 1", - "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name where fk.referenced_column_name is not null and fk.table_schema = :__vtschemaname and fk.table_name = :__vttablename and rc.constraint_schema = :__vtschemaname and rc.table_name = :__vttablename", - "SysTableTableName": "[VARBINARY(\"table_name\"), VARBINARY(\"table_name\")]", - "SysTableTableSchema": "[VARBINARY(\"table_schema\"), VARBINARY(\"table_schema\")]", - "Table": "information_schema.referential_constraints, information_schema.key_column_usage" - } -} - -#rails_query 5 -"SELECT cc.constraint_name AS 'name', cc.check_clause AS 'expression' FROM information_schema.check_constraints cc JOIN information_schema.table_constraints tc USING (constraint_schema, constraint_name) WHERE tc.table_schema = 'table_schema' AND tc.table_name = 'table_name' AND cc.constraint_schema = 'constraint_schema'" -{ - "QueryType": "SELECT", - "Original": "SELECT cc.constraint_name AS 'name', cc.check_clause AS 'expression' FROM information_schema.check_constraints cc JOIN information_schema.table_constraints tc USING (constraint_schema, constraint_name) WHERE tc.table_schema = 'table_schema' AND tc.table_name = 'table_name' AND cc.constraint_schema = 'constraint_schema'", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select cc.constraint_name as `name`, cc.check_clause as expression from information_schema.check_constraints as cc join information_schema.table_constraints as tc on cc.constraint_schema = tc.constraint_schema and cc.constraint_name = tc.constraint_name where 1 != 1", - "Query": "select cc.constraint_name as `name`, cc.check_clause as expression from information_schema.check_constraints as cc join information_schema.table_constraints as tc on cc.constraint_schema = tc.constraint_schema and cc.constraint_name = tc.constraint_name where tc.table_schema = :__vtschemaname and tc.table_name = :__vttablename and cc.constraint_schema = :__vtschemaname", - "SysTableTableName": "[VARBINARY(\"table_name\")]", - "SysTableTableSchema": "[VARBINARY(\"table_schema\"), VARBINARY(\"constraint_schema\")]", - "Table": "information_schema.check_constraints, information_schema.table_constraints" - } -} - -#rails_query 6 -"SELECT column_name FROM information_schema.statistics WHERE index_name = 'PRIMARY' AND table_schema = 'table_schema' AND table_name = 'table_name' ORDER BY seq_in_index" -{ - "QueryType": "SELECT", - "Original": "SELECT column_name FROM information_schema.statistics WHERE index_name = 'PRIMARY' AND table_schema = 'table_schema' AND table_name = 'table_name' ORDER BY seq_in_index", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select column_name from information_schema.statistics where 1 != 1", - "Query": "select column_name from information_schema.statistics where index_name = 'PRIMARY' and table_schema = :__vtschemaname and table_name = :__vttablename order by seq_in_index asc", - "SysTableTableName": "[VARBINARY(\"table_name\")]", - "SysTableTableSchema": "[VARBINARY(\"table_schema\")]", - "Table": "information_schema.statistics" - } -} -Gen4 plan same as above - -#rails_query 7 -"SELECT generation_expression FROM information_schema.columns WHERE table_schema = 'table_schema' AND table_name = 'table_name' AND column_name = 'column_name'" -{ - "QueryType": "SELECT", - "Original": "SELECT generation_expression FROM information_schema.columns WHERE table_schema = 'table_schema' AND table_name = 'table_name' AND column_name = 'column_name'", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select generation_expression from information_schema.`columns` where 1 != 1", - "Query": "select generation_expression from information_schema.`columns` where table_schema = :__vtschemaname and table_name = :__vttablename and column_name = 'column_name'", - "SysTableTableName": "[VARBINARY(\"table_name\")]", - "SysTableTableSchema": "[VARBINARY(\"table_schema\")]", - "Table": "information_schema.`columns`" - } -} -Gen4 plan same as above - -#rails_query 8 -"SELECT id FROM information_schema.processlist WHERE info LIKE '% FOR UPDATE'" -{ - "QueryType": "SELECT", - "Original": "SELECT id FROM information_schema.processlist WHERE info LIKE '% FOR UPDATE'", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select id from information_schema.`processlist` where 1 != 1", - "Query": "select id from information_schema.`processlist` where info like '% FOR UPDATE'", - "Table": "information_schema.`processlist`" - } -} -Gen4 plan same as above - -#rails_query 9 -"SELECT table_name FROM (SELECT * FROM information_schema.tables WHERE table_schema = 'table_schema') _subquery" -{ - "QueryType": "SELECT", - "Original": "SELECT table_name FROM (SELECT * FROM information_schema.tables WHERE table_schema = 'table_schema') _subquery", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select table_name from (select * from information_schema.`tables` where 1 != 1) as _subquery where 1 != 1", - "Query": "select table_name from (select * from information_schema.`tables` where table_schema = :__vtschemaname) as _subquery", - "SysTableTableSchema": "[VARBINARY(\"table_schema\")]", - "Table": "information_schema.`tables`" - } -} - -#rails_query 10 -"SELECT table_name FROM (SELECT * FROM information_schema.tables WHERE table_schema = 'table_schema') _subquery WHERE _subquery.table_type = 'table_type' AND _subquery.table_name = 'table_name'" -{ - "QueryType": "SELECT", - "Original": "SELECT table_name FROM (SELECT * FROM information_schema.tables WHERE table_schema = 'table_schema') _subquery WHERE _subquery.table_type = 'table_type' AND _subquery.table_name = 'table_name'", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select table_name from (select * from information_schema.`tables` where 1 != 1) as _subquery where 1 != 1", - "Query": "select table_name from (select * from information_schema.`tables` where table_schema = :__vtschemaname) as _subquery where _subquery.table_type = 'table_type' and _subquery.table_name = :__vttablename", - "SysTableTableName": "[VARBINARY(\"table_name\")]", - "SysTableTableSchema": "[VARBINARY(\"table_schema\")]", - "Table": "information_schema.`tables`" - } -} - -# two predicates specifying the database for the same table work if the database is the same -"SELECT cc.constraint_name AS 'name' FROM information_schema.check_constraints cc WHERE cc.constraint_schema = 'a' AND cc.table_schema = 'a'" -{ - "QueryType": "SELECT", - "Original": "SELECT cc.constraint_name AS 'name' FROM information_schema.check_constraints cc WHERE cc.constraint_schema = 'a' AND cc.table_schema = 'a'", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select cc.constraint_name as `name` from information_schema.check_constraints as cc where 1 != 1", - "Query": "select cc.constraint_name as `name` from information_schema.check_constraints as cc where cc.constraint_schema = :__vtschemaname and cc.table_schema = :__vtschemaname", - "SysTableTableSchema": "[VARBINARY(\"a\"), VARBINARY(\"a\")]", - "Table": "information_schema.check_constraints" - } -} -Gen4 plan same as above - -# system schema in where clause of information_schema query -"SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'performance_schema' AND table_name = 'foo'" -{ - "QueryType": "SELECT", - "Original": "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'performance_schema' AND table_name = 'foo'", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select COUNT(*) from INFORMATION_SCHEMA.`TABLES` where 1 != 1", - "Query": "select COUNT(*) from INFORMATION_SCHEMA.`TABLES` where table_schema = :__vtschemaname and table_name = :__vttablename", - "SysTableTableName": "[VARBINARY(\"foo\")]", - "SysTableTableSchema": "[VARBINARY(\"performance_schema\")]", - "Table": "INFORMATION_SCHEMA.`TABLES`" - } -} -Gen4 plan same as above - # query with parens is planned correctly "select m1.col from (unsharded as m1, unsharded as m2)" { diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.txt b/go/vt/vtgate/planbuilder/testdata/select_cases.txt index a7fe027e933..b1c805cc4a6 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.txt @@ -1249,25 +1249,6 @@ Gen4 plan same as above "select t.col from (select user.id from user join user_extra) as t" "symbol t.col not found in table or subquery" -# union of information_schema -"select * from information_schema.a union select * from information_schema.b" -{ - "QueryType": "SELECT", - "Original": "select * from information_schema.a union select * from information_schema.b", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select * from information_schema.a where 1 != 1 union select * from information_schema.b where 1 != 1", - "Query": "select * from information_schema.a union select * from information_schema.b", - "Table": "information_schema.a" - } -} -Gen4 plan same as above - # union with the same target shard "select * from music where user_id = 1 union select * from user where id = 1" { @@ -1773,123 +1754,3 @@ Gen4 plan same as above } } Gen4 plan same as above - -# Select from information schema query with two tables that route should be merged -"SELECT DELETE_RULE, UPDATE_RULE FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC ON KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME WHERE KCU.TABLE_SCHEMA = 'test' AND KCU.TABLE_NAME = 'data_type_table' AND KCU.COLUMN_NAME = 'id' AND KCU.REFERENCED_TABLE_SCHEMA = 'test' AND KCU.CONSTRAINT_NAME = 'data_type_table_id_fkey' ORDER BY KCU.CONSTRAINT_NAME, KCU.COLUMN_NAME" -{ - "QueryType": "SELECT", - "Original": "SELECT DELETE_RULE, UPDATE_RULE FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC ON KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME WHERE KCU.TABLE_SCHEMA = 'test' AND KCU.TABLE_NAME = 'data_type_table' AND KCU.COLUMN_NAME = 'id' AND KCU.REFERENCED_TABLE_SCHEMA = 'test' AND KCU.CONSTRAINT_NAME = 'data_type_table_id_fkey' ORDER BY KCU.CONSTRAINT_NAME, KCU.COLUMN_NAME", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select DELETE_RULE, UPDATE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC on KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME where 1 != 1", - "Query": "select DELETE_RULE, UPDATE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC on KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME where KCU.TABLE_SCHEMA = :__vtschemaname and KCU.TABLE_NAME = :__vttablename and KCU.COLUMN_NAME = 'id' and KCU.REFERENCED_TABLE_SCHEMA = 'test' and KCU.CONSTRAINT_NAME = 'data_type_table_id_fkey' order by KCU.CONSTRAINT_NAME asc, KCU.COLUMN_NAME asc", - "SysTableTableName": "[VARBINARY(\"data_type_table\")]", - "SysTableTableSchema": "[VARBINARY(\"test\")]", - "Table": "INFORMATION_SCHEMA.KEY_COLUMN_USAGE, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS" - } -} - -# Select from information schema query with three tables such that route for 2 should be merged but not for the last. -"SELECT KCU.DELETE_RULE, S.UPDATE_RULE FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC ON KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME, INFORMATION_SCHEMA.K AS S WHERE KCU.TABLE_SCHEMA = 'test' AND KCU.TABLE_NAME = 'data_type_table' AND KCU.TABLE_NAME = 'data_type_table' AND S.TABLE_SCHEMA = 'test' AND S.TABLE_NAME = 'sc' ORDER BY KCU.CONSTRAINT_NAME, KCU.COLUMN_NAME" -{ - "QueryType": "SELECT", - "Original": "SELECT KCU.DELETE_RULE, S.UPDATE_RULE FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC ON KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME, INFORMATION_SCHEMA.K AS S WHERE KCU.TABLE_SCHEMA = 'test' AND KCU.TABLE_NAME = 'data_type_table' AND KCU.TABLE_NAME = 'data_type_table' AND S.TABLE_SCHEMA = 'test' AND S.TABLE_NAME = 'sc' ORDER BY KCU.CONSTRAINT_NAME, KCU.COLUMN_NAME", - "Instructions": { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "-1,1", - "TableName": "INFORMATION_SCHEMA.KEY_COLUMN_USAGE, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS_INFORMATION_SCHEMA.K", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select KCU.DELETE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC on KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME where 1 != 1", - "Query": "select KCU.DELETE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC on KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME where KCU.TABLE_SCHEMA = :__vtschemaname and KCU.TABLE_NAME = :__vttablename and KCU.TABLE_NAME = :__vttablename order by KCU.CONSTRAINT_NAME asc, KCU.COLUMN_NAME asc", - "SysTableTableName": "[VARBINARY(\"data_type_table\"), VARBINARY(\"data_type_table\")]", - "SysTableTableSchema": "[VARBINARY(\"test\")]", - "Table": "INFORMATION_SCHEMA.KEY_COLUMN_USAGE, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS" - }, - { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select S.UPDATE_RULE from INFORMATION_SCHEMA.K as S where 1 != 1", - "Query": "select S.UPDATE_RULE from INFORMATION_SCHEMA.K as S where S.TABLE_SCHEMA = :__vtschemaname and S.TABLE_NAME = :__vttablename", - "SysTableTableName": "[VARBINARY(\"sc\")]", - "SysTableTableSchema": "[VARBINARY(\"test\")]", - "Table": "INFORMATION_SCHEMA.K" - } - ] - } -} - -#information_schema.routines -"SELECT routine_name AS name, routine_definition AS definition FROM information_schema.routines WHERE ROUTINE_SCHEMA = ? AND ROUTINE_TYPE = 'PROCEDURE'" -{ - "QueryType": "SELECT", - "Original": "SELECT routine_name AS name, routine_definition AS definition FROM information_schema.routines WHERE ROUTINE_SCHEMA = ? AND ROUTINE_TYPE = 'PROCEDURE'", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select routine_name as `name`, routine_definition as definition from information_schema.routines where 1 != 1", - "Query": "select routine_name as `name`, routine_definition as definition from information_schema.routines where ROUTINE_SCHEMA = :__vtschemaname and ROUTINE_TYPE = 'PROCEDURE'", - "SysTableTableSchema": "[:v1]", - "Table": "information_schema.routines" - } -} -Gen4 plan same as above - -#information_schema table sizes -"SELECT SUM(data_length + index_length) as size FROM information_schema.TABLES WHERE table_schema = ?" -{ - "QueryType": "SELECT", - "Original": "SELECT SUM(data_length + index_length) as size FROM information_schema.TABLES WHERE table_schema = ?", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select SUM(data_length + index_length) as size from information_schema.`TABLES` where 1 != 1", - "Query": "select SUM(data_length + index_length) as size from information_schema.`TABLES` where table_schema = :__vtschemaname", - "SysTableTableSchema": "[:v1]", - "Table": "information_schema.`TABLES`" - } -} -Gen4 plan same as above - -#information_schema referential contraints -"SELECT kcu.constraint_name constraint_name, kcu.column_name column_name, kcu.referenced_table_name referenced_table_name, kcu.referenced_column_name referenced_column_name, kcu.ordinal_position ordinal_position, kcu.table_name table_name, rc.delete_rule delete_rule, rc.update_rule update_rule FROM information_schema.key_column_usage AS kcu INNER JOIN information_schema.referential_constraints AS rc ON kcu.constraint_name = rc.constraint_name WHERE kcu.table_schema = ? AND rc.constraint_schema = ? AND kcu.referenced_column_name IS NOT NULL ORDER BY ordinal_position" -{ - "QueryType": "SELECT", - "Original": "SELECT kcu.constraint_name constraint_name, kcu.column_name column_name, kcu.referenced_table_name referenced_table_name, kcu.referenced_column_name referenced_column_name, kcu.ordinal_position ordinal_position, kcu.table_name table_name, rc.delete_rule delete_rule, rc.update_rule update_rule FROM information_schema.key_column_usage AS kcu INNER JOIN information_schema.referential_constraints AS rc ON kcu.constraint_name = rc.constraint_name WHERE kcu.table_schema = ? AND rc.constraint_schema = ? AND kcu.referenced_column_name IS NOT NULL ORDER BY ordinal_position", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select kcu.constraint_name as constraint_name, kcu.column_name as column_name, kcu.referenced_table_name as referenced_table_name, kcu.referenced_column_name as referenced_column_name, kcu.ordinal_position as ordinal_position, kcu.table_name as table_name, rc.delete_rule as delete_rule, rc.update_rule as update_rule from information_schema.key_column_usage as kcu join information_schema.referential_constraints as rc on kcu.constraint_name = rc.constraint_name where 1 != 1", - "Query": "select kcu.constraint_name as constraint_name, kcu.column_name as column_name, kcu.referenced_table_name as referenced_table_name, kcu.referenced_column_name as referenced_column_name, kcu.ordinal_position as ordinal_position, kcu.table_name as table_name, rc.delete_rule as delete_rule, rc.update_rule as update_rule from information_schema.key_column_usage as kcu join information_schema.referential_constraints as rc on kcu.constraint_name = rc.constraint_name where kcu.table_schema = :__vtschemaname and rc.constraint_schema = :__vtschemaname and kcu.referenced_column_name is not null order by ordinal_position asc", - "SysTableTableSchema": "[:v1, :v2]", - "Table": "information_schema.key_column_usage, information_schema.referential_constraints" - } -} diff --git a/go/vt/vtgate/planbuilder/testdata/set_sysvar_disabled_cases.txt b/go/vt/vtgate/planbuilder/testdata/set_sysvar_disabled_cases.txt index f213ba1a96b..46cbdfd4e0d 100644 --- a/go/vt/vtgate/planbuilder/testdata/set_sysvar_disabled_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/set_sysvar_disabled_cases.txt @@ -34,3 +34,5 @@ ] } } +Gen4 plan same as above + diff --git a/go/vt/vtgate/planbuilder/testdata/sysschema_default.txt b/go/vt/vtgate/planbuilder/testdata/sysschema_default.txt index f6e58dd2c18..2d33f6d517d 100644 --- a/go/vt/vtgate/planbuilder/testdata/sysschema_default.txt +++ b/go/vt/vtgate/planbuilder/testdata/sysschema_default.txt @@ -15,3 +15,4 @@ "Table": "dual" } } +Gen4 plan same as above diff --git a/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt b/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt new file mode 100644 index 00000000000..41f6868bd7a --- /dev/null +++ b/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt @@ -0,0 +1,723 @@ +# Single information_schema query +"select col from information_schema.foo" +{ + "QueryType": "SELECT", + "Original": "select col from information_schema.foo", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select col from information_schema.foo where 1 != 1", + "Query": "select col from information_schema.foo", + "Table": "information_schema.foo" + } +} +Gen4 plan same as above + +# ',' join information_schema +"select a.id,b.id from information_schema.a as a, information_schema.b as b" +{ + "QueryType": "SELECT", + "Original": "select a.id,b.id from information_schema.a as a, information_schema.b as b", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select a.id, b.id from information_schema.a as a, information_schema.b as b where 1 != 1", + "Query": "select a.id, b.id from information_schema.a as a, information_schema.b as b", + "Table": "information_schema.a, information_schema.b" + } +} +Gen4 plan same as above + +# information schema query that uses table_schema +"select column_name from information_schema.columns where table_schema = (select schema())" +{ + "QueryType": "SELECT", + "Original": "select column_name from information_schema.columns where table_schema = (select schema())", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select column_name from information_schema.`columns` where 1 != 1", + "Query": "select column_name from information_schema.`columns` where table_schema = schema()", + "Table": "information_schema.`columns`" + } +} +Gen4 plan same as above + +# information schema join +"select * from information_schema.a join information_schema.b" +{ + "QueryType": "SELECT", + "Original": "select * from information_schema.a join information_schema.b", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select * from information_schema.a join information_schema.b where 1 != 1", + "Query": "select * from information_schema.a join information_schema.b", + "Table": "information_schema.a, information_schema.b" + } +} +{ + "QueryType": "SELECT", + "Original": "select * from information_schema.a join information_schema.b", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select * from information_schema.a, information_schema.b where 1 != 1", + "Query": "select * from information_schema.a, information_schema.b", + "Table": "information_schema.a, information_schema.b" + } +} + +# access to unqualified column names in information_schema +"select * from information_schema.a where b=10" +{ + "QueryType": "SELECT", + "Original": "select * from information_schema.a where b=10", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select * from information_schema.a where 1 != 1", + "Query": "select * from information_schema.a where b = 10", + "Table": "information_schema.a" + } +} +Gen4 plan same as above + +# access to qualified column names in information_schema +"select * from information_schema.a where information_schema.a.b=10" +{ + "QueryType": "SELECT", + "Original": "select * from information_schema.a where information_schema.a.b=10", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select * from information_schema.a where 1 != 1", + "Query": "select * from information_schema.a where information_schema.a.b = 10", + "Table": "information_schema.a" + } +} +Gen4 plan same as above + +# union of information_schema +"select * from information_schema.a union select * from information_schema.b" +{ + "QueryType": "SELECT", + "Original": "select * from information_schema.a union select * from information_schema.b", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select * from information_schema.a where 1 != 1 union select * from information_schema.b where 1 != 1", + "Query": "select * from information_schema.a union select * from information_schema.b", + "Table": "information_schema.a" + } +} +Gen4 plan same as above + +# Select from information schema query with two tables that route should be merged +"SELECT DELETE_RULE, UPDATE_RULE FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC ON KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME WHERE KCU.TABLE_SCHEMA = 'test' AND KCU.TABLE_NAME = 'data_type_table' AND KCU.COLUMN_NAME = 'id' AND KCU.REFERENCED_TABLE_SCHEMA = 'test' AND KCU.CONSTRAINT_NAME = 'data_type_table_id_fkey' ORDER BY KCU.CONSTRAINT_NAME, KCU.COLUMN_NAME" +{ + "QueryType": "SELECT", + "Original": "SELECT DELETE_RULE, UPDATE_RULE FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC ON KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME WHERE KCU.TABLE_SCHEMA = 'test' AND KCU.TABLE_NAME = 'data_type_table' AND KCU.COLUMN_NAME = 'id' AND KCU.REFERENCED_TABLE_SCHEMA = 'test' AND KCU.CONSTRAINT_NAME = 'data_type_table_id_fkey' ORDER BY KCU.CONSTRAINT_NAME, KCU.COLUMN_NAME", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select DELETE_RULE, UPDATE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC on KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME where 1 != 1", + "Query": "select DELETE_RULE, UPDATE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC on KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME where KCU.TABLE_SCHEMA = :__vtschemaname and KCU.TABLE_NAME = :__vttablename and KCU.COLUMN_NAME = 'id' and KCU.REFERENCED_TABLE_SCHEMA = 'test' and KCU.CONSTRAINT_NAME = 'data_type_table_id_fkey' order by KCU.CONSTRAINT_NAME asc, KCU.COLUMN_NAME asc", + "SysTableTableName": "[VARBINARY(\"data_type_table\")]", + "SysTableTableSchema": "[VARBINARY(\"test\")]", + "Table": "INFORMATION_SCHEMA.KEY_COLUMN_USAGE, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS" + } +} +{ + "QueryType": "SELECT", + "Original": "SELECT DELETE_RULE, UPDATE_RULE FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC ON KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME WHERE KCU.TABLE_SCHEMA = 'test' AND KCU.TABLE_NAME = 'data_type_table' AND KCU.COLUMN_NAME = 'id' AND KCU.REFERENCED_TABLE_SCHEMA = 'test' AND KCU.CONSTRAINT_NAME = 'data_type_table_id_fkey' ORDER BY KCU.CONSTRAINT_NAME, KCU.COLUMN_NAME", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select DELETE_RULE, UPDATE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC where 1 != 1", + "Query": "select DELETE_RULE, UPDATE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC where KCU.TABLE_SCHEMA = :__vtschemaname and KCU.TABLE_NAME = :__vttablename and KCU.COLUMN_NAME = 'id' and KCU.REFERENCED_TABLE_SCHEMA = 'test' and KCU.CONSTRAINT_NAME = 'data_type_table_id_fkey' and KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME order by KCU.CONSTRAINT_NAME asc, KCU.COLUMN_NAME asc", + "SysTableTableName": "[VARBINARY(\"data_type_table\")]", + "SysTableTableSchema": "[VARBINARY(\"test\")]", + "Table": "INFORMATION_SCHEMA.KEY_COLUMN_USAGE, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS" + } +} + +# Select from information schema query with three tables such that route for 2 should be merged but not for the last. +"SELECT KCU.DELETE_RULE, S.UPDATE_RULE FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC ON KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME, INFORMATION_SCHEMA.K AS S WHERE KCU.TABLE_SCHEMA = 'test' AND KCU.TABLE_NAME = 'data_type_table' AND KCU.TABLE_NAME = 'data_type_table' AND S.TABLE_SCHEMA = 'test' AND S.TABLE_NAME = 'sc' ORDER BY KCU.CONSTRAINT_NAME, KCU.COLUMN_NAME" +{ + "QueryType": "SELECT", + "Original": "SELECT KCU.DELETE_RULE, S.UPDATE_RULE FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC ON KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME, INFORMATION_SCHEMA.K AS S WHERE KCU.TABLE_SCHEMA = 'test' AND KCU.TABLE_NAME = 'data_type_table' AND KCU.TABLE_NAME = 'data_type_table' AND S.TABLE_SCHEMA = 'test' AND S.TABLE_NAME = 'sc' ORDER BY KCU.CONSTRAINT_NAME, KCU.COLUMN_NAME", + "Instructions": { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "-1,1", + "TableName": "INFORMATION_SCHEMA.KEY_COLUMN_USAGE, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS_INFORMATION_SCHEMA.K", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select KCU.DELETE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC on KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME where 1 != 1", + "Query": "select KCU.DELETE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC on KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME where KCU.TABLE_SCHEMA = :__vtschemaname and KCU.TABLE_NAME = :__vttablename and KCU.TABLE_NAME = :__vttablename order by KCU.CONSTRAINT_NAME asc, KCU.COLUMN_NAME asc", + "SysTableTableName": "[VARBINARY(\"data_type_table\"), VARBINARY(\"data_type_table\")]", + "SysTableTableSchema": "[VARBINARY(\"test\")]", + "Table": "INFORMATION_SCHEMA.KEY_COLUMN_USAGE, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS" + }, + { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select S.UPDATE_RULE from INFORMATION_SCHEMA.K as S where 1 != 1", + "Query": "select S.UPDATE_RULE from INFORMATION_SCHEMA.K as S where S.TABLE_SCHEMA = :__vtschemaname and S.TABLE_NAME = :__vttablename", + "SysTableTableName": "[VARBINARY(\"sc\")]", + "SysTableTableSchema": "[VARBINARY(\"test\")]", + "Table": "INFORMATION_SCHEMA.K" + } + ] + } +} + +#information_schema.routines +"SELECT routine_name AS name, routine_definition AS definition FROM information_schema.routines WHERE ROUTINE_SCHEMA = ? AND ROUTINE_TYPE = 'PROCEDURE'" +{ + "QueryType": "SELECT", + "Original": "SELECT routine_name AS name, routine_definition AS definition FROM information_schema.routines WHERE ROUTINE_SCHEMA = ? AND ROUTINE_TYPE = 'PROCEDURE'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select routine_name as `name`, routine_definition as definition from information_schema.routines where 1 != 1", + "Query": "select routine_name as `name`, routine_definition as definition from information_schema.routines where ROUTINE_SCHEMA = :__vtschemaname and ROUTINE_TYPE = 'PROCEDURE'", + "SysTableTableSchema": "[:v1]", + "Table": "information_schema.routines" + } +} +Gen4 plan same as above + +#information_schema table sizes +"SELECT SUM(data_length + index_length) as size FROM information_schema.TABLES WHERE table_schema = ?" +{ + "QueryType": "SELECT", + "Original": "SELECT SUM(data_length + index_length) as size FROM information_schema.TABLES WHERE table_schema = ?", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select SUM(data_length + index_length) as size from information_schema.`TABLES` where 1 != 1", + "Query": "select SUM(data_length + index_length) as size from information_schema.`TABLES` where table_schema = :__vtschemaname", + "SysTableTableSchema": "[:v1]", + "Table": "information_schema.`TABLES`" + } +} +Gen4 plan same as above + +#information_schema referential contraints +"SELECT kcu.constraint_name constraint_name, kcu.column_name column_name, kcu.referenced_table_name referenced_table_name, kcu.referenced_column_name referenced_column_name, kcu.ordinal_position ordinal_position, kcu.table_name table_name, rc.delete_rule delete_rule, rc.update_rule update_rule FROM information_schema.key_column_usage AS kcu INNER JOIN information_schema.referential_constraints AS rc ON kcu.constraint_name = rc.constraint_name WHERE kcu.table_schema = ? AND rc.constraint_schema = ? AND kcu.referenced_column_name IS NOT NULL ORDER BY ordinal_position" +{ + "QueryType": "SELECT", + "Original": "SELECT kcu.constraint_name constraint_name, kcu.column_name column_name, kcu.referenced_table_name referenced_table_name, kcu.referenced_column_name referenced_column_name, kcu.ordinal_position ordinal_position, kcu.table_name table_name, rc.delete_rule delete_rule, rc.update_rule update_rule FROM information_schema.key_column_usage AS kcu INNER JOIN information_schema.referential_constraints AS rc ON kcu.constraint_name = rc.constraint_name WHERE kcu.table_schema = ? AND rc.constraint_schema = ? AND kcu.referenced_column_name IS NOT NULL ORDER BY ordinal_position", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select kcu.constraint_name as constraint_name, kcu.column_name as column_name, kcu.referenced_table_name as referenced_table_name, kcu.referenced_column_name as referenced_column_name, kcu.ordinal_position as ordinal_position, kcu.table_name as table_name, rc.delete_rule as delete_rule, rc.update_rule as update_rule from information_schema.key_column_usage as kcu join information_schema.referential_constraints as rc on kcu.constraint_name = rc.constraint_name where 1 != 1", + "Query": "select kcu.constraint_name as constraint_name, kcu.column_name as column_name, kcu.referenced_table_name as referenced_table_name, kcu.referenced_column_name as referenced_column_name, kcu.ordinal_position as ordinal_position, kcu.table_name as table_name, rc.delete_rule as delete_rule, rc.update_rule as update_rule from information_schema.key_column_usage as kcu join information_schema.referential_constraints as rc on kcu.constraint_name = rc.constraint_name where kcu.table_schema = :__vtschemaname and rc.constraint_schema = :__vtschemaname and kcu.referenced_column_name is not null order by ordinal_position asc", + "SysTableTableSchema": "[:v1, :v2]", + "Table": "information_schema.key_column_usage, information_schema.referential_constraints" + } +} +{ + "QueryType": "SELECT", + "Original": "SELECT kcu.constraint_name constraint_name, kcu.column_name column_name, kcu.referenced_table_name referenced_table_name, kcu.referenced_column_name referenced_column_name, kcu.ordinal_position ordinal_position, kcu.table_name table_name, rc.delete_rule delete_rule, rc.update_rule update_rule FROM information_schema.key_column_usage AS kcu INNER JOIN information_schema.referential_constraints AS rc ON kcu.constraint_name = rc.constraint_name WHERE kcu.table_schema = ? AND rc.constraint_schema = ? AND kcu.referenced_column_name IS NOT NULL ORDER BY ordinal_position", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select kcu.constraint_name as constraint_name, kcu.column_name as column_name, kcu.referenced_table_name as referenced_table_name, kcu.referenced_column_name as referenced_column_name, kcu.ordinal_position as ordinal_position, kcu.table_name as table_name, rc.delete_rule as delete_rule, rc.update_rule as update_rule from information_schema.key_column_usage as kcu, information_schema.referential_constraints as rc where 1 != 1", + "Query": "select kcu.constraint_name as constraint_name, kcu.column_name as column_name, kcu.referenced_table_name as referenced_table_name, kcu.referenced_column_name as referenced_column_name, kcu.ordinal_position as ordinal_position, kcu.table_name as table_name, rc.delete_rule as delete_rule, rc.update_rule as update_rule from information_schema.key_column_usage as kcu, information_schema.referential_constraints as rc where kcu.table_schema = :__vtschemaname and kcu.referenced_column_name is not null and rc.constraint_schema = :__vtschemaname and kcu.constraint_name = rc.constraint_name order by ordinal_position asc", + "SysTableTableSchema": "[:v1, :v2]", + "Table": "information_schema.key_column_usage, information_schema.referential_constraints" + } +} + +# rails query +"select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as name, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk using (constraint_schema, constraint_name) where fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = ':vtg1' and rc.constraint_schema = database() and rc.table_name = ':vtg1'" +{ + "QueryType": "SELECT", + "Original": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as name, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk using (constraint_schema, constraint_name) where fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = ':vtg1' and rc.constraint_schema = database() and rc.table_name = ':vtg1'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name where 1 != 1", + "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name where fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = :__vttablename and rc.constraint_schema = database() and rc.table_name = :__vttablename", + "SysTableTableName": "[VARBINARY(\":vtg1\"), VARBINARY(\":vtg1\")]", + "Table": "information_schema.referential_constraints, information_schema.key_column_usage" + } +} +{ + "QueryType": "SELECT", + "Original": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as name, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk using (constraint_schema, constraint_name) where fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = ':vtg1' and rc.constraint_schema = database() and rc.table_name = ':vtg1'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc, information_schema.key_column_usage as fk where 1 != 1", + "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc, information_schema.key_column_usage as fk where rc.constraint_schema = database() and rc.table_name = :__vttablename and fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = :__vttablename and rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name", + "SysTableTableName": "[VARBINARY(\":vtg1\"), VARBINARY(\":vtg1\")]", + "Table": "information_schema.key_column_usage, information_schema.referential_constraints" + } +} + +#rails_query 2 +"SELECT * FROM information_schema.schemata WHERE schema_name = 'user'" +{ + "QueryType": "SELECT", + "Original": "SELECT * FROM information_schema.schemata WHERE schema_name = 'user'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select * from information_schema.schemata where 1 != 1", + "Query": "select * from information_schema.schemata where schema_name = :__vtschemaname", + "SysTableTableSchema": "[VARBINARY(\"user\")]", + "Table": "information_schema.schemata" + } +} +Gen4 plan same as above + +#rails_query 3 +"SELECT table_comment FROM information_schema.tables WHERE table_schema = 'schema_name' AND table_name = 'table_name'" +{ + "QueryType": "SELECT", + "Original": "SELECT table_comment FROM information_schema.tables WHERE table_schema = 'schema_name' AND table_name = 'table_name'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select table_comment from information_schema.`tables` where 1 != 1", + "Query": "select table_comment from information_schema.`tables` where table_schema = :__vtschemaname and table_name = :__vttablename", + "SysTableTableName": "[VARBINARY(\"table_name\")]", + "SysTableTableSchema": "[VARBINARY(\"schema_name\")]", + "Table": "information_schema.`tables`" + } +} +Gen4 plan same as above + +#rails_query 4 +"SELECT fk.referenced_table_name AS 'to_table', fk.referenced_column_name AS 'primary_key',fk.column_name AS 'column',fk.constraint_name AS 'name',rc.update_rule AS 'on_update',rc.delete_rule AS 'on_delete' FROM information_schema.referential_constraints rc JOIN information_schema.key_column_usage fk USING (constraint_schema, constraint_name) WHERE fk.referenced_column_name IS NOT NULL AND fk.table_schema = 'table_schema' AND fk.table_name = 'table_name' AND rc.constraint_schema = 'table_schema' AND rc.table_name = 'table_name'" +{ + "QueryType": "SELECT", + "Original": "SELECT fk.referenced_table_name AS 'to_table', fk.referenced_column_name AS 'primary_key',fk.column_name AS 'column',fk.constraint_name AS 'name',rc.update_rule AS 'on_update',rc.delete_rule AS 'on_delete' FROM information_schema.referential_constraints rc JOIN information_schema.key_column_usage fk USING (constraint_schema, constraint_name) WHERE fk.referenced_column_name IS NOT NULL AND fk.table_schema = 'table_schema' AND fk.table_name = 'table_name' AND rc.constraint_schema = 'table_schema' AND rc.table_name = 'table_name'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name where 1 != 1", + "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name where fk.referenced_column_name is not null and fk.table_schema = :__vtschemaname and fk.table_name = :__vttablename and rc.constraint_schema = :__vtschemaname and rc.table_name = :__vttablename", + "SysTableTableName": "[VARBINARY(\"table_name\"), VARBINARY(\"table_name\")]", + "SysTableTableSchema": "[VARBINARY(\"table_schema\"), VARBINARY(\"table_schema\")]", + "Table": "information_schema.referential_constraints, information_schema.key_column_usage" + } +} +{ + "QueryType": "SELECT", + "Original": "SELECT fk.referenced_table_name AS 'to_table', fk.referenced_column_name AS 'primary_key',fk.column_name AS 'column',fk.constraint_name AS 'name',rc.update_rule AS 'on_update',rc.delete_rule AS 'on_delete' FROM information_schema.referential_constraints rc JOIN information_schema.key_column_usage fk USING (constraint_schema, constraint_name) WHERE fk.referenced_column_name IS NOT NULL AND fk.table_schema = 'table_schema' AND fk.table_name = 'table_name' AND rc.constraint_schema = 'table_schema' AND rc.table_name = 'table_name'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc, information_schema.key_column_usage as fk where 1 != 1", + "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc, information_schema.key_column_usage as fk where rc.constraint_schema = :__vtschemaname and rc.table_name = :__vttablename and fk.referenced_column_name is not null and fk.table_schema = :__vtschemaname and fk.table_name = :__vttablename and rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name", + "SysTableTableName": "[VARBINARY(\"table_name\"), VARBINARY(\"table_name\")]", + "SysTableTableSchema": "[VARBINARY(\"table_schema\"), VARBINARY(\"table_schema\")]", + "Table": "information_schema.key_column_usage, information_schema.referential_constraints" + } +} + +#rails_query 5 +"SELECT cc.constraint_name AS 'name', cc.check_clause AS 'expression' FROM information_schema.check_constraints cc JOIN information_schema.table_constraints tc USING (constraint_schema, constraint_name) WHERE tc.table_schema = 'table_schema' AND tc.table_name = 'table_name' AND cc.constraint_schema = 'constraint_schema'" +{ + "QueryType": "SELECT", + "Original": "SELECT cc.constraint_name AS 'name', cc.check_clause AS 'expression' FROM information_schema.check_constraints cc JOIN information_schema.table_constraints tc USING (constraint_schema, constraint_name) WHERE tc.table_schema = 'table_schema' AND tc.table_name = 'table_name' AND cc.constraint_schema = 'constraint_schema'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select cc.constraint_name as `name`, cc.check_clause as expression from information_schema.check_constraints as cc join information_schema.table_constraints as tc on cc.constraint_schema = tc.constraint_schema and cc.constraint_name = tc.constraint_name where 1 != 1", + "Query": "select cc.constraint_name as `name`, cc.check_clause as expression from information_schema.check_constraints as cc join information_schema.table_constraints as tc on cc.constraint_schema = tc.constraint_schema and cc.constraint_name = tc.constraint_name where tc.table_schema = :__vtschemaname and tc.table_name = :__vttablename and cc.constraint_schema = :__vtschemaname", + "SysTableTableName": "[VARBINARY(\"table_name\")]", + "SysTableTableSchema": "[VARBINARY(\"table_schema\"), VARBINARY(\"constraint_schema\")]", + "Table": "information_schema.check_constraints, information_schema.table_constraints" + } +} +{ + "QueryType": "SELECT", + "Original": "SELECT cc.constraint_name AS 'name', cc.check_clause AS 'expression' FROM information_schema.check_constraints cc JOIN information_schema.table_constraints tc USING (constraint_schema, constraint_name) WHERE tc.table_schema = 'table_schema' AND tc.table_name = 'table_name' AND cc.constraint_schema = 'constraint_schema'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select cc.constraint_name as `name`, cc.check_clause as expression from information_schema.check_constraints as cc, information_schema.table_constraints as tc where 1 != 1", + "Query": "select cc.constraint_name as `name`, cc.check_clause as expression from information_schema.check_constraints as cc, information_schema.table_constraints as tc where cc.constraint_schema = :__vtschemaname and tc.table_schema = :__vtschemaname and tc.table_name = :__vttablename and cc.constraint_schema = tc.constraint_schema and cc.constraint_name = tc.constraint_name", + "SysTableTableName": "[VARBINARY(\"table_name\")]", + "SysTableTableSchema": "[VARBINARY(\"constraint_schema\"), VARBINARY(\"table_schema\")]", + "Table": "information_schema.check_constraints, information_schema.table_constraints" + } +} + +#rails_query 6 +"SELECT column_name FROM information_schema.statistics WHERE index_name = 'PRIMARY' AND table_schema = 'table_schema' AND table_name = 'table_name' ORDER BY seq_in_index" +{ + "QueryType": "SELECT", + "Original": "SELECT column_name FROM information_schema.statistics WHERE index_name = 'PRIMARY' AND table_schema = 'table_schema' AND table_name = 'table_name' ORDER BY seq_in_index", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select column_name from information_schema.statistics where 1 != 1", + "Query": "select column_name from information_schema.statistics where index_name = 'PRIMARY' and table_schema = :__vtschemaname and table_name = :__vttablename order by seq_in_index asc", + "SysTableTableName": "[VARBINARY(\"table_name\")]", + "SysTableTableSchema": "[VARBINARY(\"table_schema\")]", + "Table": "information_schema.statistics" + } +} +Gen4 plan same as above + +#rails_query 7 +"SELECT generation_expression FROM information_schema.columns WHERE table_schema = 'table_schema' AND table_name = 'table_name' AND column_name = 'column_name'" +{ + "QueryType": "SELECT", + "Original": "SELECT generation_expression FROM information_schema.columns WHERE table_schema = 'table_schema' AND table_name = 'table_name' AND column_name = 'column_name'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select generation_expression from information_schema.`columns` where 1 != 1", + "Query": "select generation_expression from information_schema.`columns` where table_schema = :__vtschemaname and table_name = :__vttablename and column_name = 'column_name'", + "SysTableTableName": "[VARBINARY(\"table_name\")]", + "SysTableTableSchema": "[VARBINARY(\"table_schema\")]", + "Table": "information_schema.`columns`" + } +} +Gen4 plan same as above + +#rails_query 8 +"SELECT id FROM information_schema.processlist WHERE info LIKE '% FOR UPDATE'" +{ + "QueryType": "SELECT", + "Original": "SELECT id FROM information_schema.processlist WHERE info LIKE '% FOR UPDATE'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select id from information_schema.`processlist` where 1 != 1", + "Query": "select id from information_schema.`processlist` where info like '% FOR UPDATE'", + "Table": "information_schema.`processlist`" + } +} +Gen4 plan same as above + +#rails_query 9 +"SELECT table_name FROM (SELECT * FROM information_schema.tables WHERE table_schema = 'table_schema') _subquery" +{ + "QueryType": "SELECT", + "Original": "SELECT table_name FROM (SELECT * FROM information_schema.tables WHERE table_schema = 'table_schema') _subquery", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select table_name from (select * from information_schema.`tables` where 1 != 1) as _subquery where 1 != 1", + "Query": "select table_name from (select * from information_schema.`tables` where table_schema = :__vtschemaname) as _subquery", + "SysTableTableSchema": "[VARBINARY(\"table_schema\")]", + "Table": "information_schema.`tables`" + } +} + +#rails_query 10 +"SELECT table_name FROM (SELECT * FROM information_schema.tables WHERE table_schema = 'table_schema') _subquery WHERE _subquery.table_type = 'table_type' AND _subquery.table_name = 'table_name'" +{ + "QueryType": "SELECT", + "Original": "SELECT table_name FROM (SELECT * FROM information_schema.tables WHERE table_schema = 'table_schema') _subquery WHERE _subquery.table_type = 'table_type' AND _subquery.table_name = 'table_name'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select table_name from (select * from information_schema.`tables` where 1 != 1) as _subquery where 1 != 1", + "Query": "select table_name from (select * from information_schema.`tables` where table_schema = :__vtschemaname) as _subquery where _subquery.table_type = 'table_type' and _subquery.table_name = :__vttablename", + "SysTableTableName": "[VARBINARY(\"table_name\")]", + "SysTableTableSchema": "[VARBINARY(\"table_schema\")]", + "Table": "information_schema.`tables`" + } +} + +# two predicates specifying the database for the same table work if the database is the same +"SELECT cc.constraint_name AS 'name' FROM information_schema.check_constraints cc WHERE cc.constraint_schema = 'a' AND cc.table_schema = 'a'" +{ + "QueryType": "SELECT", + "Original": "SELECT cc.constraint_name AS 'name' FROM information_schema.check_constraints cc WHERE cc.constraint_schema = 'a' AND cc.table_schema = 'a'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select cc.constraint_name as `name` from information_schema.check_constraints as cc where 1 != 1", + "Query": "select cc.constraint_name as `name` from information_schema.check_constraints as cc where cc.constraint_schema = :__vtschemaname and cc.table_schema = :__vtschemaname", + "SysTableTableSchema": "[VARBINARY(\"a\"), VARBINARY(\"a\")]", + "Table": "information_schema.check_constraints" + } +} +Gen4 plan same as above + +# system schema in where clause of information_schema query +"SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'performance_schema' AND table_name = 'foo'" +{ + "QueryType": "SELECT", + "Original": "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'performance_schema' AND table_name = 'foo'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select COUNT(*) from INFORMATION_SCHEMA.`TABLES` where 1 != 1", + "Query": "select COUNT(*) from INFORMATION_SCHEMA.`TABLES` where table_schema = :__vtschemaname and table_name = :__vttablename", + "SysTableTableName": "[VARBINARY(\"foo\")]", + "SysTableTableSchema": "[VARBINARY(\"performance_schema\")]", + "Table": "INFORMATION_SCHEMA.`TABLES`" + } +} +Gen4 plan same as above + +# subquery of information_schema with itself +"select * from information_schema.a where id in (select * from information_schema.b)" +{ + "QueryType": "SELECT", + "Original": "select * from information_schema.a where id in (select * from information_schema.b)", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select * from information_schema.a where 1 != 1", + "Query": "select * from information_schema.a where id in (select * from information_schema.b)", + "Table": "information_schema.a" + } +} + +# query trying to query two different keyspaces at the same time +"SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'user' AND TABLE_SCHEMA = 'main'" +{ + "QueryType": "SELECT", + "Original": "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'user' AND TABLE_SCHEMA = 'main'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select * from INFORMATION_SCHEMA.`TABLES` where 1 != 1", + "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = :__vtschemaname and TABLE_SCHEMA = :__vtschemaname", + "SysTableTableSchema": "[VARBINARY(\"user\"), VARBINARY(\"main\")]", + "Table": "INFORMATION_SCHEMA.`TABLES`" + } +} +{ + "QueryType": "SELECT", + "Original": "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'user' AND TABLE_SCHEMA = 'main'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select * from INFORMATION_SCHEMA.`TABLES` where 1 != 1", + "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = :__vtschemaname", + "SysTableTableSchema": "[VARBINARY(\"user\"), VARBINARY(\"main\")]", + "Table": "INFORMATION_SCHEMA.`TABLES`" + } +} + +# information_schema query using database() func +"SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = database()" +{ + "QueryType": "SELECT", + "Original": "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = database()", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select * from INFORMATION_SCHEMA.`TABLES` where 1 != 1", + "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = database()", + "Table": "INFORMATION_SCHEMA.`TABLES`" + } +} +Gen4 plan same as above + +# table_schema predicate the wrong way around +"SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE 'ks' = TABLE_SCHEMA" +{ + "QueryType": "SELECT", + "Original": "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE 'ks' = TABLE_SCHEMA", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select * from INFORMATION_SCHEMA.`TABLES` where 1 != 1", + "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = :__vtschemaname", + "SysTableTableSchema": "[VARBINARY(\"ks\")]", + "Table": "INFORMATION_SCHEMA.`TABLES`" + } +} +Gen4 plan same as above + +# table_name predicate against a routed table +"SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ks' AND TABLE_NAME = 'route1'" +{ + "QueryType": "SELECT", + "Original": "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ks' AND TABLE_NAME = 'route1'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select * from INFORMATION_SCHEMA.`TABLES` where 1 != 1", + "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = :__vtschemaname and TABLE_NAME = :__vttablename", + "SysTableTableName": "[VARBINARY(\"route1\")]", + "SysTableTableSchema": "[VARBINARY(\"ks\")]", + "Table": "INFORMATION_SCHEMA.`TABLES`" + } +} +Gen4 plan same as above + +# information_schema query with additional predicates +"SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ks' and other_column = 42" +{ + "QueryType": "SELECT", + "Original": "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ks' and other_column = 42", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select * from INFORMATION_SCHEMA.`TABLES` where 1 != 1", + "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = :__vtschemaname and other_column = 42", + "SysTableTableSchema": "[VARBINARY(\"ks\")]", + "Table": "INFORMATION_SCHEMA.`TABLES`" + } +} +Gen4 plan same as above From 3fadd813527f29c7be953795d725823544cfc246 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Mon, 19 Jul 2021 11:46:34 +0530 Subject: [PATCH 3/9] use reservedvars to replace the argument in table_name predicated. Use them to validate that all the tables points to same keyspace routing Signed-off-by: Harshit Gangal --- go/test/endtoend/vtgate/system_schema_test.go | 6 +- go/vt/vtgate/engine/cached_size.go | 24 ++++-- go/vt/vtgate/engine/route.go | 81 ++++++++++--------- go/vt/vtgate/planbuilder/jointree.go | 2 +- go/vt/vtgate/planbuilder/route_planning.go | 49 ++++++----- go/vt/vtgate/planbuilder/select.go | 2 +- go/vt/vtgate/planbuilder/system_tables.go | 31 ++++--- 7 files changed, 113 insertions(+), 82 deletions(-) diff --git a/go/test/endtoend/vtgate/system_schema_test.go b/go/test/endtoend/vtgate/system_schema_test.go index ad2fb0f5e93..31e5353eff7 100644 --- a/go/test/endtoend/vtgate/system_schema_test.go +++ b/go/test/endtoend/vtgate/system_schema_test.go @@ -169,14 +169,16 @@ func TestSystemSchemaQueryWithoutQualifier(t *testing.T) { "from information_schema.tables t "+ "join information_schema.columns c "+ "on c.table_schema = t.table_schema and c.table_name = t.table_name "+ - "where t.table_schema = '%s' and c.table_schema = '%s'", KeyspaceName, KeyspaceName) + "where t.table_schema = '%s' and c.table_schema = '%s' "+ + "order by t.table_schema,t.table_name,c.column_name", KeyspaceName, KeyspaceName) qr1 := exec(t, conn, queryWithQualifier) queryWithoutQualifier := fmt.Sprintf("select t.table_schema,t.table_name,c.column_name,c.column_type "+ "from tables t "+ "join columns c "+ "on c.table_schema = t.table_schema and c.table_name = t.table_name "+ - "where t.table_schema = '%s' and c.table_schema = '%s'", KeyspaceName, KeyspaceName) + "where t.table_schema = '%s' and c.table_schema = '%s' "+ + "order by t.table_schema,t.table_name,c.column_name", KeyspaceName, KeyspaceName) exec(t, conn, "use information_schema") qr2 := exec(t, conn, queryWithoutQualifier) require.Equal(t, qr1, qr2) diff --git a/go/vt/vtgate/engine/cached_size.go b/go/vt/vtgate/engine/cached_size.go index 0c1ce058f6b..acfc640f6e4 100644 --- a/go/vt/vtgate/engine/cached_size.go +++ b/go/vt/vtgate/engine/cached_size.go @@ -562,13 +562,15 @@ func (cached *RevertMigration) CachedSize(alloc bool) int64 { } return size } + +//go:nocheckptr func (cached *Route) CachedSize(alloc bool) int64 { if cached == nil { return int64(0) } size := int64(0) if alloc { - size += int64(224) + size += int64(208) } // field Keyspace *vitess.io/vitess/go/vt/vtgate/vindexes.Keyspace size += cached.Keyspace.CachedSize(true) @@ -606,11 +608,19 @@ func (cached *Route) CachedSize(alloc bool) int64 { } } } - // field SysTableTableName []vitess.io/vitess/go/vt/vtgate/evalengine.Expr - { - size += int64(cap(cached.SysTableTableName)) * int64(16) - for _, elem := range cached.SysTableTableName { - if cc, ok := elem.(cachedObject); ok { + // field SysTableTableName map[string]vitess.io/vitess/go/vt/vtgate/evalengine.Expr + if cached.SysTableTableName != nil { + size += int64(48) + hmap := reflect.ValueOf(cached.SysTableTableName) + numBuckets := int(math.Pow(2, float64((*(*uint8)(unsafe.Pointer(hmap.Pointer() + uintptr(9))))))) + numOldBuckets := (*(*uint16)(unsafe.Pointer(hmap.Pointer() + uintptr(10)))) + size += int64(numOldBuckets * 272) + if len(cached.SysTableTableName) > 0 || numBuckets > 1 { + size += int64(numBuckets * 272) + } + for k, v := range cached.SysTableTableName { + size += int64(len(k)) + if cc, ok := v.(cachedObject); ok { size += cc.CachedSize(true) } } @@ -670,7 +680,7 @@ func (cached *Send) CachedSize(alloc bool) int64 { } size := int64(0) if alloc { - size += int64(43) + size += int64(44) } // field Keyspace *vitess.io/vitess/go/vt/vtgate/vindexes.Keyspace size += cached.Keyspace.CachedSize(true) diff --git a/go/vt/vtgate/engine/route.go b/go/vt/vtgate/engine/route.go index cc5df58aea0..7472ae2cd45 100644 --- a/go/vt/vtgate/engine/route.go +++ b/go/vt/vtgate/engine/route.go @@ -95,7 +95,7 @@ type Route struct { // The following two fields are used when routing information_schema queries SysTableTableSchema []evalengine.Expr - SysTableTableName []evalengine.Expr + SysTableTableName map[string]evalengine.Expr // Route does not take inputs noInputs @@ -476,32 +476,25 @@ func (route *Route) routeInfoSchemaQuery(vcursor VCursor, bindVars map[string]*q bindVars[sqltypes.BvSchemaName] = sqltypes.StringBindVariable(specifiedKS) } - var tableName string - for _, sysTableName := range route.SysTableTableName { + tableNames := map[string]string{} + for tblBvName, sysTableName := range route.SysTableTableName { val, err := sysTableName.Evaluate(env) if err != nil { return nil, err } tabName := val.Value().ToString() - if tableName == "" { - tableName = tabName - } - if tableName != tabName { - return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "two predicates for table_name not supported") - } - } - if tableName != "" { - bindVars[BvTableName] = sqltypes.StringBindVariable(tableName) + tableNames[tblBvName] = tabName + bindVars[tblBvName] = sqltypes.StringBindVariable(tabName) } - // if the table_schema is system system, route to default keyspace. + // if the table_schema is system schema, route to default keyspace. if sqlparser.SystemSchema(specifiedKS) { return defaultRoute() } // the use has specified a table_name - let's check if it's a routed table - if tableName != "" { - rss, err := route.paramsRoutedTable(vcursor, bindVars, specifiedKS, tableName) + if len(tableNames) > 0 { + rss, err := route.paramsRoutedTable(vcursor, bindVars, specifiedKS, tableNames) if err != nil { // Only if keyspace is not found in vschema, we try with default keyspace. // As the in the table_schema predicates for a keyspace 'ks' it can contain 'vt_ks'. @@ -531,28 +524,39 @@ func (route *Route) routeInfoSchemaQuery(vcursor VCursor, bindVars map[string]*q return destinations, nil } -func (route *Route) paramsRoutedTable(vcursor VCursor, bindVars map[string]*querypb.BindVariable, tableSchema string, tableName string) ([]*srvtopo.ResolvedShard, error) { - tbl := sqlparser.TableName{ - Name: sqlparser.NewTableIdent(tableName), - Qualifier: sqlparser.NewTableIdent(tableSchema), - } - destination, err := vcursor.FindRoutedTable(tbl) - if err != nil { - return nil, err - } +func (route *Route) paramsRoutedTable(vcursor VCursor, bindVars map[string]*querypb.BindVariable, tableSchema string, tableNames map[string]string) ([]*srvtopo.ResolvedShard, error) { + var routedKs *vindexes.Keyspace + for tblBvName, tableName := range tableNames { + tbl := sqlparser.TableName{ + Name: sqlparser.NewTableIdent(tableName), + Qualifier: sqlparser.NewTableIdent(tableSchema), + } + routedTable, err := vcursor.FindRoutedTable(tbl) + if err != nil { + return nil, err + } + + if routedTable != nil { + // if we were able to find information about this table, let's use it - if destination != nil { - // if we were able to find information about this table, let's use it - shards, _, err := vcursor.ResolveDestinations(destination.Keyspace.Name, nil, []key.Destination{key.DestinationAnyShard{}}) - bindVars[BvTableName] = sqltypes.StringBindVariable(destination.Name.String()) - if tableSchema != "" { - setReplaceSchemaName(bindVars) + // check if the query is send to single keyspace. + if routedKs == nil { + routedKs = routedTable.Keyspace + } + if routedKs.Name != routedTable.Keyspace.Name { + return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "cannot send the query to multiple keyspace due to different table_name: %s, %s", routedKs.Name, routedTable.Keyspace.Name) + } + + shards, _, err := vcursor.ResolveDestinations(routedTable.Keyspace.Name, nil, []key.Destination{key.DestinationAnyShard{}}) + bindVars[tblBvName] = sqltypes.StringBindVariable(routedTable.Name.String()) + if tableSchema != "" { + setReplaceSchemaName(bindVars) + } + return shards, err } - return shards, err + // no routed table info found. we'll return nil and check on the outside if we can find the table_schema + bindVars[tblBvName] = sqltypes.StringBindVariable(tableName) } - - // no routed table info found. we'll return nil and check on the outside if we can find the table_schema - bindVars[BvTableName] = sqltypes.StringBindVariable(tableName) return nil, nil } @@ -796,12 +800,14 @@ func (route *Route) description() PrimitiveDescription { other["SysTableTableSchema"] = sysTabSchema } if len(route.SysTableTableName) != 0 { + idx := 0 sysTableName := "[" - for idx, tableName := range route.SysTableTableName { + for k, v := range route.SysTableTableName { if idx != 0 { sysTableName += ", " } - sysTableName += tableName.String() + sysTableName += k + ":" + v.String() + idx++ } sysTableName += "]" other["SysTableTableName"] = sysTableName @@ -828,6 +834,3 @@ func (route *Route) description() PrimitiveDescription { func orderByToString(in interface{}) string { return in.(OrderByParams).String() } - -// BvTableName is used to fill in the table name for information_schema queries with routed tables -const BvTableName = "__vttablename" diff --git a/go/vt/vtgate/planbuilder/jointree.go b/go/vt/vtgate/planbuilder/jointree.go index ec5420e5320..9ea7c5c07d2 100644 --- a/go/vt/vtgate/planbuilder/jointree.go +++ b/go/vt/vtgate/planbuilder/jointree.go @@ -100,7 +100,7 @@ type ( // The following two fields are used when routing information_schema queries SysTableTableSchema []evalengine.Expr - SysTableTableName []evalengine.Expr + SysTableTableName map[string]evalengine.Expr } joinPlan struct { diff --git a/go/vt/vtgate/planbuilder/route_planning.go b/go/vt/vtgate/planbuilder/route_planning.go index c1ddcbb1903..d5226d1778b 100644 --- a/go/vt/vtgate/planbuilder/route_planning.go +++ b/go/vt/vtgate/planbuilder/route_planning.go @@ -41,11 +41,11 @@ func gen4Planner(_ string) func(sqlparser.Statement, *sqlparser.ReservedVars, Co if !ok { return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "%T not yet supported", stmt) } - return newBuildSelectPlan(sel, vschema) + return newBuildSelectPlan(sel, reservedVars, vschema) } } -func newBuildSelectPlan(sel *sqlparser.Select, vschema ContextVSchema) (engine.Primitive, error) { +func newBuildSelectPlan(sel *sqlparser.Select, reservedVars *sqlparser.ReservedVars, vschema ContextVSchema) (engine.Primitive, error) { directives := sqlparser.ExtractCommentDirectives(sel.Comments) if len(directives) > 0 { @@ -70,7 +70,7 @@ func newBuildSelectPlan(sel *sqlparser.Select, vschema ContextVSchema) (engine.P return nil, err } - tree, err := optimizeQuery(opTree, semTable, vschema) + tree, err := optimizeQuery(opTree, reservedVars, semTable, vschema) if err != nil { return nil, err } @@ -103,31 +103,31 @@ func newBuildSelectPlan(sel *sqlparser.Select, vschema ContextVSchema) (engine.P return plan.Primitive(), nil } -func optimizeQuery(opTree abstract.Operator, semTable *semantics.SemTable, vschema ContextVSchema) (joinTree, error) { +func optimizeQuery(opTree abstract.Operator, reservedVars *sqlparser.ReservedVars, semTable *semantics.SemTable, vschema ContextVSchema) (joinTree, error) { switch op := opTree.(type) { case *abstract.QueryGraph: switch { case vschema.Planner() == Gen4Left2Right: - return leftToRightSolve(op, semTable, vschema) + return leftToRightSolve(op, reservedVars, semTable, vschema) default: - return greedySolve(op, semTable, vschema) + return greedySolve(op, reservedVars, semTable, vschema) } case *abstract.LeftJoin: - treeInner, err := optimizeQuery(op.Left, semTable, vschema) + treeInner, err := optimizeQuery(op.Left, reservedVars, semTable, vschema) if err != nil { return nil, err } - treeOuter, err := optimizeQuery(op.Right, semTable, vschema) + treeOuter, err := optimizeQuery(op.Right, reservedVars, semTable, vschema) if err != nil { return nil, err } return mergeOrJoin(treeInner, treeOuter, []sqlparser.Expr{op.Predicate}, semTable, false) case *abstract.Join: - treeInner, err := optimizeQuery(op.LHS, semTable, vschema) + treeInner, err := optimizeQuery(op.LHS, reservedVars, semTable, vschema) if err != nil { return nil, err } - treeOuter, err := optimizeQuery(op.RHS, semTable, vschema) + treeOuter, err := optimizeQuery(op.RHS, reservedVars, semTable, vschema) if err != nil { return nil, err } @@ -424,8 +424,8 @@ type ( and removes the two inputs to this cheapest plan and instead adds the join. As an optimization, it first only considers joining tables that have predicates defined between them */ -func greedySolve(qg *abstract.QueryGraph, semTable *semantics.SemTable, vschema ContextVSchema) (joinTree, error) { - joinTrees, err := seedPlanList(qg, semTable, vschema) +func greedySolve(qg *abstract.QueryGraph, reservedVars *sqlparser.ReservedVars, semTable *semantics.SemTable, vschema ContextVSchema) (joinTree, error) { + joinTrees, err := seedPlanList(qg, reservedVars, semTable, vschema) planCache := cacheMap{} if err != nil { return nil, err @@ -517,8 +517,8 @@ func findBestJoinTree( return bestPlan, lIdx, rIdx, nil } -func leftToRightSolve(qg *abstract.QueryGraph, semTable *semantics.SemTable, vschema ContextVSchema) (joinTree, error) { - plans, err := seedPlanList(qg, semTable, vschema) +func leftToRightSolve(qg *abstract.QueryGraph, reservedVars *sqlparser.ReservedVars, semTable *semantics.SemTable, vschema ContextVSchema) (joinTree, error) { + plans, err := seedPlanList(qg, reservedVars, semTable, vschema) if err != nil { return nil, err } @@ -540,13 +540,13 @@ func leftToRightSolve(qg *abstract.QueryGraph, semTable *semantics.SemTable, vsc } // seedPlanList returns a routePlan for each table in the qg -func seedPlanList(qg *abstract.QueryGraph, semTable *semantics.SemTable, vschema ContextVSchema) ([]joinTree, error) { +func seedPlanList(qg *abstract.QueryGraph, reservedVars *sqlparser.ReservedVars, semTable *semantics.SemTable, vschema ContextVSchema) ([]joinTree, error) { plans := make([]joinTree, len(qg.Tables)) // we start by seeding the table with the single routes for i, table := range qg.Tables { solves := semTable.TableSetFor(table.Alias) - plan, err := createRoutePlan(table, solves, vschema) + plan, err := createRoutePlan(table, solves, reservedVars, vschema) if err != nil { return nil, err } @@ -562,7 +562,7 @@ func removeAt(plans []joinTree, idx int) []joinTree { return append(plans[:idx], plans[idx+1:]...) } -func createRoutePlan(table *abstract.QueryTable, solves semantics.TableSet, vschema ContextVSchema) (*routePlan, error) { +func createRoutePlan(table *abstract.QueryTable, solves semantics.TableSet, reservedVars *sqlparser.ReservedVars, vschema ContextVSchema) (*routePlan, error) { if table.IsInfSchema { defaultKeyspace, err := vschema.DefaultKeyspace() if err != nil { @@ -582,7 +582,7 @@ func createRoutePlan(table *abstract.QueryTable, solves semantics.TableSet, vsch }}, predicates: table.Predicates, } - err = rp.findSysInfoRoutingPredicatesGen4() + err = rp.findSysInfoRoutingPredicatesGen4(reservedVars) if err != nil { return nil, err } @@ -773,6 +773,17 @@ func createRoutePlanForInner(aRoute *routePlan, bRoute *routePlan, newTabletSet } else { tables = append(parenTables{aRoute.tables}, bRoute.tables...) } + + // append system table names from both the routes. + sysTableName := aRoute.SysTableTableName + if sysTableName == nil { + sysTableName = bRoute.SysTableTableName + } else { + for k, v := range bRoute.SysTableTableName { + sysTableName[k] = v + } + } + return &routePlan{ routeOpCode: aRoute.routeOpCode, solved: newTabletSet, @@ -784,7 +795,7 @@ func createRoutePlanForInner(aRoute *routePlan, bRoute *routePlan, newTabletSet vindexPreds: append(aRoute.vindexPreds, bRoute.vindexPreds...), leftJoins: append(aRoute.leftJoins, bRoute.leftJoins...), SysTableTableSchema: append(aRoute.SysTableTableSchema, bRoute.SysTableTableSchema...), - SysTableTableName: append(aRoute.SysTableTableName, bRoute.SysTableTableName...), + SysTableTableName: sysTableName, } } diff --git a/go/vt/vtgate/planbuilder/select.go b/go/vt/vtgate/planbuilder/select.go index 3a7cba1cd53..44bb541a9b7 100644 --- a/go/vt/vtgate/planbuilder/select.go +++ b/go/vt/vtgate/planbuilder/select.go @@ -371,7 +371,7 @@ func (pb *primitiveBuilder) pushFilter(in sqlparser.Expr, whereType string, rese } rut, isRoute := origin.(*route) if isRoute && rut.eroute.Opcode == engine.SelectDBA { - err := pb.findSysInfoRoutingPredicates(expr, rut) + err := pb.findSysInfoRoutingPredicates(expr, rut, reservedVars) if err != nil { return err } diff --git a/go/vt/vtgate/planbuilder/system_tables.go b/go/vt/vtgate/planbuilder/system_tables.go index c2338d809a4..136918ff1fd 100644 --- a/go/vt/vtgate/planbuilder/system_tables.go +++ b/go/vt/vtgate/planbuilder/system_tables.go @@ -19,12 +19,11 @@ package planbuilder import ( "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vtgate/engine" "vitess.io/vitess/go/vt/vtgate/evalengine" ) -func (pb *primitiveBuilder) findSysInfoRoutingPredicates(expr sqlparser.Expr, rut *route) error { - isTableSchema, out, err := extractInfoSchemaRoutingPredicate(expr) +func (pb *primitiveBuilder) findSysInfoRoutingPredicates(expr sqlparser.Expr, rut *route, reservedVars *sqlparser.ReservedVars) error { + isTableSchema, bvName, out, err := extractInfoSchemaRoutingPredicate(expr, reservedVars) if err != nil { return err } @@ -36,15 +35,18 @@ func (pb *primitiveBuilder) findSysInfoRoutingPredicates(expr sqlparser.Expr, ru if isTableSchema { rut.eroute.SysTableTableSchema = append(rut.eroute.SysTableTableSchema, out) } else { - rut.eroute.SysTableTableName = append(rut.eroute.SysTableTableName, out) + if rut.eroute.SysTableTableName == nil { + rut.eroute.SysTableTableName = map[string]evalengine.Expr{} + } + rut.eroute.SysTableTableName[bvName] = out } return nil } -func (rp *routePlan) findSysInfoRoutingPredicatesGen4() error { +func (rp *routePlan) findSysInfoRoutingPredicatesGen4(reservedVars *sqlparser.ReservedVars) error { for _, pred := range rp.predicates { - isTableSchema, out, err := extractInfoSchemaRoutingPredicate(pred) + isTableSchema, bvName, out, err := extractInfoSchemaRoutingPredicate(pred, reservedVars) if err != nil { return err } @@ -56,7 +58,10 @@ func (rp *routePlan) findSysInfoRoutingPredicatesGen4() error { if isTableSchema { rp.SysTableTableSchema = append(rp.SysTableTableSchema, out) } else { - rp.SysTableTableName = append(rp.SysTableTableName, out) + if rp.SysTableTableName == nil { + rp.SysTableTableName = map[string]evalengine.Expr{} + } + rp.SysTableTableName[bvName] = out } } return nil @@ -93,7 +98,7 @@ func isTableNameCol(col *sqlparser.ColName) bool { return col.Name.EqualString("table_name") } -func extractInfoSchemaRoutingPredicate(in sqlparser.Expr) (bool, evalengine.Expr, error) { +func extractInfoSchemaRoutingPredicate(in sqlparser.Expr, reservedVars *sqlparser.ReservedVars) (bool, string, evalengine.Expr, error) { switch cmp := in.(type) { case *sqlparser.ComparisonExpr: if cmp.Operator == sqlparser.EqualOp { @@ -104,22 +109,22 @@ func extractInfoSchemaRoutingPredicate(in sqlparser.Expr) (bool, evalengine.Expr if err == sqlparser.ErrExprNotSupported { // This just means we can't rewrite this particular expression, // not that we have to exit altogether - return false, nil, nil + return false, "", nil, nil } - return false, nil, err + return false, "", nil, err } var name string if isSchemaName { name = sqltypes.BvSchemaName } else { - name = engine.BvTableName + name = reservedVars.ReserveColName(col.(*sqlparser.ColName)) } replaceOther(sqlparser.NewArgument(name)) - return isSchemaName, evalExpr, nil + return isSchemaName, name, evalExpr, nil } } } - return false, nil, nil + return false, "", nil, nil } func shouldRewrite(e sqlparser.Expr) bool { From 260e67c9bce77811fede49845410f0055708d624 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Mon, 19 Jul 2021 12:06:56 +0530 Subject: [PATCH 4/9] fix tests for information_schema with table_name in predicates Signed-off-by: Harshit Gangal --- go/vt/vtgate/engine/fuzz_flaky_test.go | 2 +- go/vt/vtgate/engine/route_test.go | 34 ++++---- go/vt/vtgate/executor_select_test.go | 10 +-- .../testdata/systemtables_cases.txt | 81 +++++++++++-------- 4 files changed, 73 insertions(+), 54 deletions(-) diff --git a/go/vt/vtgate/engine/fuzz_flaky_test.go b/go/vt/vtgate/engine/fuzz_flaky_test.go index 538875e9a72..1eb93bf3a0c 100644 --- a/go/vt/vtgate/engine/fuzz_flaky_test.go +++ b/go/vt/vtgate/engine/fuzz_flaky_test.go @@ -220,7 +220,7 @@ func execRouteSelectDBA(query, field, tablename, schema, shards string) { Query: query, FieldQuery: field, SysTableTableSchema: stringToExpr(schema), - SysTableTableName: stringToExpr(tablename), + SysTableTableName: map[string]evalengine.Expr{"table_name": evalengine.NewLiteralString([]byte(tablename))}, } vc := &loggingVCursor{ shards: []string{shards}, diff --git a/go/vt/vtgate/engine/route_test.go b/go/vt/vtgate/engine/route_test.go index aee0abf936e..d7cad32ba63 100644 --- a/go/vt/vtgate/engine/route_test.go +++ b/go/vt/vtgate/engine/route_test.go @@ -88,54 +88,57 @@ func TestSelectInformationSchemaWithTableAndSchemaWithRoutedTables(t *testing.T) } type testCase struct { - tableSchema, tableName []string - testName string - expectedLog []string - routed bool + tableSchema []string + tableName map[string]evalengine.Expr + testName string + expectedLog []string + routed bool } tests := []testCase{{ testName: "both schema and table predicates - routed table", tableSchema: []string{"schema"}, - tableName: []string{"table"}, + tableName: map[string]evalengine.Expr{"table_name": evalengine.NewLiteralString([]byte("table"))}, routed: true, expectedLog: []string{ "FindTable(`schema`.`table`)", "ResolveDestinations routedKeyspace [] Destinations:DestinationAnyShard()", - "ExecuteMultiShard routedKeyspace.1: dummy_select {__replacevtschemaname: type:INT64 value:\"1\" __vttablename: type:VARBINARY value:\"routedTable\"} false false"}, + "ExecuteMultiShard routedKeyspace.1: dummy_select {__replacevtschemaname: type:INT64 value:\"1\" table_name: type:VARBINARY value:\"routedTable\"} false false"}, }, { testName: "both schema and table predicates - not routed", tableSchema: []string{"schema"}, - tableName: []string{"table"}, + tableName: map[string]evalengine.Expr{"table_name": evalengine.NewLiteralString([]byte("table"))}, routed: false, expectedLog: []string{ "FindTable(`schema`.`table`)", "ResolveDestinations schema [] Destinations:DestinationAnyShard()", - "ExecuteMultiShard schema.1: dummy_select {__replacevtschemaname: type:INT64 value:\"1\" __vttablename: type:VARBINARY value:\"table\"} false false"}, + "ExecuteMultiShard schema.1: dummy_select {__replacevtschemaname: type:INT64 value:\"1\" table_name: type:VARBINARY value:\"table\"} false false"}, }, { testName: "multiple schema and table predicates", tableSchema: []string{"schema", "schema", "schema"}, - tableName: []string{"table", "table", "table"}, + tableName: map[string]evalengine.Expr{"t1": evalengine.NewLiteralString([]byte("table")), "t2": evalengine.NewLiteralString([]byte("table")), "t3": evalengine.NewLiteralString([]byte("table"))}, routed: false, expectedLog: []string{ + "FindTable(`schema`.`table`)", + "FindTable(`schema`.`table`)", "FindTable(`schema`.`table`)", "ResolveDestinations schema [] Destinations:DestinationAnyShard()", - "ExecuteMultiShard schema.1: dummy_select {__replacevtschemaname: type:INT64 value:\"1\" __vttablename: type:VARBINARY value:\"table\"} false false"}, + "ExecuteMultiShard schema.1: dummy_select {__replacevtschemaname: type:INT64 value:\"1\" t1: type:VARBINARY value:\"table\" t2: type:VARBINARY value:\"table\" t3: type:VARBINARY value:\"table\"} false false"}, }, { testName: "table name predicate - routed table", - tableName: []string{"tableName"}, + tableName: map[string]evalengine.Expr{"table_name": evalengine.NewLiteralString([]byte("tableName"))}, routed: true, expectedLog: []string{ "FindTable(tableName)", "ResolveDestinations routedKeyspace [] Destinations:DestinationAnyShard()", - "ExecuteMultiShard routedKeyspace.1: dummy_select {__vttablename: type:VARBINARY value:\"routedTable\"} false false"}, + "ExecuteMultiShard routedKeyspace.1: dummy_select {table_name: type:VARBINARY value:\"routedTable\"} false false"}, }, { testName: "table name predicate - not routed", - tableName: []string{"tableName"}, + tableName: map[string]evalengine.Expr{"table_name": evalengine.NewLiteralString([]byte("tableName"))}, routed: false, expectedLog: []string{ "FindTable(tableName)", "ResolveDestinations ks [] Destinations:DestinationAnyShard()", - "ExecuteMultiShard ks.1: dummy_select {__vttablename: type:VARBINARY value:\"tableName\"} false false"}, + "ExecuteMultiShard ks.1: dummy_select {table_name: type:VARBINARY value:\"tableName\"} false false"}, }, { testName: "schema predicate", tableSchema: []string{"myKeyspace"}, @@ -154,7 +157,6 @@ func TestSelectInformationSchemaWithTableAndSchemaWithRoutedTables(t *testing.T) "ResolveDestinations ks [] Destinations:DestinationAnyShard()", "ExecuteMultiShard ks.1: dummy_select {} false false"}, }} - for _, tc := range tests { t.Run(tc.testName, func(t *testing.T) { sel := &Route{ @@ -166,7 +168,7 @@ func TestSelectInformationSchemaWithTableAndSchemaWithRoutedTables(t *testing.T) Query: "dummy_select", FieldQuery: "dummy_select_field", SysTableTableSchema: stringListToExprList(tc.tableSchema), - SysTableTableName: stringListToExprList(tc.tableName), + SysTableTableName: tc.tableName, } vc := &loggingVCursor{ shards: []string{"1"}, diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index 05c1ba5af7f..a5794243b74 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -74,16 +74,16 @@ func TestSelectDBA(t *testing.T) { utils.MustMatch(t, wantQueries, sbc1.Queries) sbc1.Queries = nil - query = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'performance_schema' AND table_name = 'foo'" + query = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES ist WHERE ist.table_schema = 'performance_schema' AND ist.table_name = 'foo'" _, err = executor.Execute(context.Background(), "TestSelectDBA", NewSafeSession(&vtgatepb.Session{TargetString: "TestExecutor"}), query, map[string]*querypb.BindVariable{}, ) require.NoError(t, err) - wantQueries = []*querypb.BoundQuery{{Sql: "select COUNT(*) from INFORMATION_SCHEMA.`TABLES` where table_schema = :__vtschemaname and table_name = :__vttablename", + wantQueries = []*querypb.BoundQuery{{Sql: "select COUNT(*) from INFORMATION_SCHEMA.`TABLES` as ist where ist.table_schema = :__vtschemaname and ist.table_name = :ist_table_name", BindVariables: map[string]*querypb.BindVariable{ "__vtschemaname": sqltypes.StringBindVariable("performance_schema"), - "__vttablename": sqltypes.StringBindVariable("foo"), + "ist_table_name": sqltypes.StringBindVariable("foo"), }}} utils.MustMatch(t, wantQueries, sbc1.Queries) @@ -94,10 +94,10 @@ func TestSelectDBA(t *testing.T) { query, map[string]*querypb.BindVariable{}, ) require.NoError(t, err) - wantQueries = []*querypb.BoundQuery{{Sql: "select 1 from information_schema.table_constraints where constraint_schema = :__vtschemaname and table_name = :__vttablename", + wantQueries = []*querypb.BoundQuery{{Sql: "select 1 from information_schema.table_constraints where constraint_schema = :__vtschemaname and table_name = :table_name", BindVariables: map[string]*querypb.BindVariable{ "__vtschemaname": sqltypes.StringBindVariable("vt_ks"), - "__vttablename": sqltypes.StringBindVariable("user"), + "table_name": sqltypes.StringBindVariable("user"), }}} utils.MustMatch(t, wantQueries, sbc1.Queries) diff --git a/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt b/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt index 41f6868bd7a..538090af6db 100644 --- a/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt @@ -158,8 +158,8 @@ Gen4 plan same as above "Sharded": false }, "FieldQuery": "select DELETE_RULE, UPDATE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC on KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME where 1 != 1", - "Query": "select DELETE_RULE, UPDATE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC on KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME where KCU.TABLE_SCHEMA = :__vtschemaname and KCU.TABLE_NAME = :__vttablename and KCU.COLUMN_NAME = 'id' and KCU.REFERENCED_TABLE_SCHEMA = 'test' and KCU.CONSTRAINT_NAME = 'data_type_table_id_fkey' order by KCU.CONSTRAINT_NAME asc, KCU.COLUMN_NAME asc", - "SysTableTableName": "[VARBINARY(\"data_type_table\")]", + "Query": "select DELETE_RULE, UPDATE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC on KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME where KCU.TABLE_SCHEMA = :__vtschemaname and KCU.TABLE_NAME = :KCU_TABLE_NAME and KCU.COLUMN_NAME = 'id' and KCU.REFERENCED_TABLE_SCHEMA = 'test' and KCU.CONSTRAINT_NAME = 'data_type_table_id_fkey' order by KCU.CONSTRAINT_NAME asc, KCU.COLUMN_NAME asc", + "SysTableTableName": "[KCU_TABLE_NAME:VARBINARY(\"data_type_table\")]", "SysTableTableSchema": "[VARBINARY(\"test\")]", "Table": "INFORMATION_SCHEMA.KEY_COLUMN_USAGE, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS" } @@ -175,8 +175,8 @@ Gen4 plan same as above "Sharded": false }, "FieldQuery": "select DELETE_RULE, UPDATE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC where 1 != 1", - "Query": "select DELETE_RULE, UPDATE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC where KCU.TABLE_SCHEMA = :__vtschemaname and KCU.TABLE_NAME = :__vttablename and KCU.COLUMN_NAME = 'id' and KCU.REFERENCED_TABLE_SCHEMA = 'test' and KCU.CONSTRAINT_NAME = 'data_type_table_id_fkey' and KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME order by KCU.CONSTRAINT_NAME asc, KCU.COLUMN_NAME asc", - "SysTableTableName": "[VARBINARY(\"data_type_table\")]", + "Query": "select DELETE_RULE, UPDATE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC where KCU.TABLE_SCHEMA = :__vtschemaname and KCU.TABLE_NAME = :KCU_TABLE_NAME and KCU.COLUMN_NAME = 'id' and KCU.REFERENCED_TABLE_SCHEMA = 'test' and KCU.CONSTRAINT_NAME = 'data_type_table_id_fkey' and KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME order by KCU.CONSTRAINT_NAME asc, KCU.COLUMN_NAME asc", + "SysTableTableName": "[KCU_TABLE_NAME:VARBINARY(\"data_type_table\")]", "SysTableTableSchema": "[VARBINARY(\"test\")]", "Table": "INFORMATION_SCHEMA.KEY_COLUMN_USAGE, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS" } @@ -201,8 +201,8 @@ Gen4 plan same as above "Sharded": false }, "FieldQuery": "select KCU.DELETE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC on KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME where 1 != 1", - "Query": "select KCU.DELETE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC on KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME where KCU.TABLE_SCHEMA = :__vtschemaname and KCU.TABLE_NAME = :__vttablename and KCU.TABLE_NAME = :__vttablename order by KCU.CONSTRAINT_NAME asc, KCU.COLUMN_NAME asc", - "SysTableTableName": "[VARBINARY(\"data_type_table\"), VARBINARY(\"data_type_table\")]", + "Query": "select KCU.DELETE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC on KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME where KCU.TABLE_SCHEMA = :__vtschemaname and KCU.TABLE_NAME = :KCU_TABLE_NAME and KCU.TABLE_NAME = :KCU_TABLE_NAME order by KCU.CONSTRAINT_NAME asc, KCU.COLUMN_NAME asc", + "SysTableTableName": "[KCU_TABLE_NAME:VARBINARY(\"data_type_table\")]", "SysTableTableSchema": "[VARBINARY(\"test\")]", "Table": "INFORMATION_SCHEMA.KEY_COLUMN_USAGE, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS" }, @@ -214,14 +214,31 @@ Gen4 plan same as above "Sharded": false }, "FieldQuery": "select S.UPDATE_RULE from INFORMATION_SCHEMA.K as S where 1 != 1", - "Query": "select S.UPDATE_RULE from INFORMATION_SCHEMA.K as S where S.TABLE_SCHEMA = :__vtschemaname and S.TABLE_NAME = :__vttablename", - "SysTableTableName": "[VARBINARY(\"sc\")]", + "Query": "select S.UPDATE_RULE from INFORMATION_SCHEMA.K as S where S.TABLE_SCHEMA = :__vtschemaname and S.TABLE_NAME = :S_TABLE_NAME", + "SysTableTableName": "[S_TABLE_NAME:VARBINARY(\"sc\")]", "SysTableTableSchema": "[VARBINARY(\"test\")]", "Table": "INFORMATION_SCHEMA.K" } ] } } +{ + "QueryType": "SELECT", + "Original": "SELECT KCU.DELETE_RULE, S.UPDATE_RULE FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC ON KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME, INFORMATION_SCHEMA.K AS S WHERE KCU.TABLE_SCHEMA = 'test' AND KCU.TABLE_NAME = 'data_type_table' AND KCU.TABLE_NAME = 'data_type_table' AND S.TABLE_SCHEMA = 'test' AND S.TABLE_NAME = 'sc' ORDER BY KCU.CONSTRAINT_NAME, KCU.COLUMN_NAME", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select KCU.DELETE_RULE, S.UPDATE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC, INFORMATION_SCHEMA.K as S where 1 != 1", + "Query": "select KCU.DELETE_RULE, S.UPDATE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC, INFORMATION_SCHEMA.K as S where S.TABLE_SCHEMA = :__vtschemaname and S.TABLE_NAME = :S_TABLE_NAME and KCU.TABLE_SCHEMA = :__vtschemaname and KCU.TABLE_NAME = :KCU_TABLE_NAME and KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME order by KCU.CONSTRAINT_NAME asc, KCU.COLUMN_NAME asc", + "SysTableTableName": "[S_TABLE_NAME:VARBINARY(\"sc\"), KCU_TABLE_NAME:VARBINARY(\"data_type_table\")]", + "SysTableTableSchema": "[VARBINARY(\"test\"), VARBINARY(\"test\")]", + "Table": "INFORMATION_SCHEMA.K, INFORMATION_SCHEMA.KEY_COLUMN_USAGE, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS" + } +} #information_schema.routines "SELECT routine_name AS name, routine_definition AS definition FROM information_schema.routines WHERE ROUTINE_SCHEMA = ? AND ROUTINE_TYPE = 'PROCEDURE'" @@ -311,8 +328,8 @@ Gen4 plan same as above "Sharded": false }, "FieldQuery": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name where 1 != 1", - "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name where fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = :__vttablename and rc.constraint_schema = database() and rc.table_name = :__vttablename", - "SysTableTableName": "[VARBINARY(\":vtg1\"), VARBINARY(\":vtg1\")]", + "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name where fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = :fk_table_name and rc.constraint_schema = database() and rc.table_name = :rc_table_name", + "SysTableTableName": "[fk_table_name:VARBINARY(\":vtg1\"), rc_table_name:VARBINARY(\":vtg1\")]", "Table": "information_schema.referential_constraints, information_schema.key_column_usage" } } @@ -327,8 +344,8 @@ Gen4 plan same as above "Sharded": false }, "FieldQuery": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc, information_schema.key_column_usage as fk where 1 != 1", - "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc, information_schema.key_column_usage as fk where rc.constraint_schema = database() and rc.table_name = :__vttablename and fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = :__vttablename and rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name", - "SysTableTableName": "[VARBINARY(\":vtg1\"), VARBINARY(\":vtg1\")]", + "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc, information_schema.key_column_usage as fk where rc.constraint_schema = database() and rc.table_name = :rc_table_name and fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = :fk_table_name and rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name", + "SysTableTableName": "[rc_table_name:VARBINARY(\":vtg1\"), fk_table_name:VARBINARY(\":vtg1\")]", "Table": "information_schema.key_column_usage, information_schema.referential_constraints" } } @@ -366,8 +383,8 @@ Gen4 plan same as above "Sharded": false }, "FieldQuery": "select table_comment from information_schema.`tables` where 1 != 1", - "Query": "select table_comment from information_schema.`tables` where table_schema = :__vtschemaname and table_name = :__vttablename", - "SysTableTableName": "[VARBINARY(\"table_name\")]", + "Query": "select table_comment from information_schema.`tables` where table_schema = :__vtschemaname and table_name = :table_name", + "SysTableTableName": "[table_name:VARBINARY(\"table_name\")]", "SysTableTableSchema": "[VARBINARY(\"schema_name\")]", "Table": "information_schema.`tables`" } @@ -387,8 +404,8 @@ Gen4 plan same as above "Sharded": false }, "FieldQuery": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name where 1 != 1", - "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name where fk.referenced_column_name is not null and fk.table_schema = :__vtschemaname and fk.table_name = :__vttablename and rc.constraint_schema = :__vtschemaname and rc.table_name = :__vttablename", - "SysTableTableName": "[VARBINARY(\"table_name\"), VARBINARY(\"table_name\")]", + "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name where fk.referenced_column_name is not null and fk.table_schema = :__vtschemaname and fk.table_name = :fk_table_name and rc.constraint_schema = :__vtschemaname and rc.table_name = :rc_table_name", + "SysTableTableName": "[fk_table_name:VARBINARY(\"table_name\"), rc_table_name:VARBINARY(\"table_name\")]", "SysTableTableSchema": "[VARBINARY(\"table_schema\"), VARBINARY(\"table_schema\")]", "Table": "information_schema.referential_constraints, information_schema.key_column_usage" } @@ -404,8 +421,8 @@ Gen4 plan same as above "Sharded": false }, "FieldQuery": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc, information_schema.key_column_usage as fk where 1 != 1", - "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc, information_schema.key_column_usage as fk where rc.constraint_schema = :__vtschemaname and rc.table_name = :__vttablename and fk.referenced_column_name is not null and fk.table_schema = :__vtschemaname and fk.table_name = :__vttablename and rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name", - "SysTableTableName": "[VARBINARY(\"table_name\"), VARBINARY(\"table_name\")]", + "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc, information_schema.key_column_usage as fk where rc.constraint_schema = :__vtschemaname and rc.table_name = :rc_table_name and fk.referenced_column_name is not null and fk.table_schema = :__vtschemaname and fk.table_name = :fk_table_name and rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name", + "SysTableTableName": "[rc_table_name:VARBINARY(\"table_name\"), fk_table_name:VARBINARY(\"table_name\")]", "SysTableTableSchema": "[VARBINARY(\"table_schema\"), VARBINARY(\"table_schema\")]", "Table": "information_schema.key_column_usage, information_schema.referential_constraints" } @@ -424,8 +441,8 @@ Gen4 plan same as above "Sharded": false }, "FieldQuery": "select cc.constraint_name as `name`, cc.check_clause as expression from information_schema.check_constraints as cc join information_schema.table_constraints as tc on cc.constraint_schema = tc.constraint_schema and cc.constraint_name = tc.constraint_name where 1 != 1", - "Query": "select cc.constraint_name as `name`, cc.check_clause as expression from information_schema.check_constraints as cc join information_schema.table_constraints as tc on cc.constraint_schema = tc.constraint_schema and cc.constraint_name = tc.constraint_name where tc.table_schema = :__vtschemaname and tc.table_name = :__vttablename and cc.constraint_schema = :__vtschemaname", - "SysTableTableName": "[VARBINARY(\"table_name\")]", + "Query": "select cc.constraint_name as `name`, cc.check_clause as expression from information_schema.check_constraints as cc join information_schema.table_constraints as tc on cc.constraint_schema = tc.constraint_schema and cc.constraint_name = tc.constraint_name where tc.table_schema = :__vtschemaname and tc.table_name = :tc_table_name and cc.constraint_schema = :__vtschemaname", + "SysTableTableName": "[tc_table_name:VARBINARY(\"table_name\")]", "SysTableTableSchema": "[VARBINARY(\"table_schema\"), VARBINARY(\"constraint_schema\")]", "Table": "information_schema.check_constraints, information_schema.table_constraints" } @@ -441,8 +458,8 @@ Gen4 plan same as above "Sharded": false }, "FieldQuery": "select cc.constraint_name as `name`, cc.check_clause as expression from information_schema.check_constraints as cc, information_schema.table_constraints as tc where 1 != 1", - "Query": "select cc.constraint_name as `name`, cc.check_clause as expression from information_schema.check_constraints as cc, information_schema.table_constraints as tc where cc.constraint_schema = :__vtschemaname and tc.table_schema = :__vtschemaname and tc.table_name = :__vttablename and cc.constraint_schema = tc.constraint_schema and cc.constraint_name = tc.constraint_name", - "SysTableTableName": "[VARBINARY(\"table_name\")]", + "Query": "select cc.constraint_name as `name`, cc.check_clause as expression from information_schema.check_constraints as cc, information_schema.table_constraints as tc where cc.constraint_schema = :__vtschemaname and tc.table_schema = :__vtschemaname and tc.table_name = :tc_table_name and cc.constraint_schema = tc.constraint_schema and cc.constraint_name = tc.constraint_name", + "SysTableTableName": "[tc_table_name:VARBINARY(\"table_name\")]", "SysTableTableSchema": "[VARBINARY(\"constraint_schema\"), VARBINARY(\"table_schema\")]", "Table": "information_schema.check_constraints, information_schema.table_constraints" } @@ -461,8 +478,8 @@ Gen4 plan same as above "Sharded": false }, "FieldQuery": "select column_name from information_schema.statistics where 1 != 1", - "Query": "select column_name from information_schema.statistics where index_name = 'PRIMARY' and table_schema = :__vtschemaname and table_name = :__vttablename order by seq_in_index asc", - "SysTableTableName": "[VARBINARY(\"table_name\")]", + "Query": "select column_name from information_schema.statistics where index_name = 'PRIMARY' and table_schema = :__vtschemaname and table_name = :table_name order by seq_in_index asc", + "SysTableTableName": "[table_name:VARBINARY(\"table_name\")]", "SysTableTableSchema": "[VARBINARY(\"table_schema\")]", "Table": "information_schema.statistics" } @@ -482,8 +499,8 @@ Gen4 plan same as above "Sharded": false }, "FieldQuery": "select generation_expression from information_schema.`columns` where 1 != 1", - "Query": "select generation_expression from information_schema.`columns` where table_schema = :__vtschemaname and table_name = :__vttablename and column_name = 'column_name'", - "SysTableTableName": "[VARBINARY(\"table_name\")]", + "Query": "select generation_expression from information_schema.`columns` where table_schema = :__vtschemaname and table_name = :table_name and column_name = 'column_name'", + "SysTableTableName": "[table_name:VARBINARY(\"table_name\")]", "SysTableTableSchema": "[VARBINARY(\"table_schema\")]", "Table": "information_schema.`columns`" } @@ -541,8 +558,8 @@ Gen4 plan same as above "Sharded": false }, "FieldQuery": "select table_name from (select * from information_schema.`tables` where 1 != 1) as _subquery where 1 != 1", - "Query": "select table_name from (select * from information_schema.`tables` where table_schema = :__vtschemaname) as _subquery where _subquery.table_type = 'table_type' and _subquery.table_name = :__vttablename", - "SysTableTableName": "[VARBINARY(\"table_name\")]", + "Query": "select table_name from (select * from information_schema.`tables` where table_schema = :__vtschemaname) as _subquery where _subquery.table_type = 'table_type' and _subquery.table_name = :_subquery_table_name", + "SysTableTableName": "[_subquery_table_name:VARBINARY(\"table_name\")]", "SysTableTableSchema": "[VARBINARY(\"table_schema\")]", "Table": "information_schema.`tables`" } @@ -581,8 +598,8 @@ Gen4 plan same as above "Sharded": false }, "FieldQuery": "select COUNT(*) from INFORMATION_SCHEMA.`TABLES` where 1 != 1", - "Query": "select COUNT(*) from INFORMATION_SCHEMA.`TABLES` where table_schema = :__vtschemaname and table_name = :__vttablename", - "SysTableTableName": "[VARBINARY(\"foo\")]", + "Query": "select COUNT(*) from INFORMATION_SCHEMA.`TABLES` where table_schema = :__vtschemaname and table_name = :table_name", + "SysTableTableName": "[table_name:VARBINARY(\"foo\")]", "SysTableTableSchema": "[VARBINARY(\"performance_schema\")]", "Table": "INFORMATION_SCHEMA.`TABLES`" } @@ -694,8 +711,8 @@ Gen4 plan same as above "Sharded": false }, "FieldQuery": "select * from INFORMATION_SCHEMA.`TABLES` where 1 != 1", - "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = :__vtschemaname and TABLE_NAME = :__vttablename", - "SysTableTableName": "[VARBINARY(\"route1\")]", + "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = :__vtschemaname and TABLE_NAME = :TABLE_NAME", + "SysTableTableName": "[TABLE_NAME:VARBINARY(\"route1\")]", "SysTableTableSchema": "[VARBINARY(\"ks\")]", "Table": "INFORMATION_SCHEMA.`TABLES`" } From 38f506b1d09c787492fc5eb8b30bb0fc7184e154 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Mon, 19 Jul 2021 12:27:11 +0530 Subject: [PATCH 5/9] add cnf rewriting to system schema queries Signed-off-by: Harshit Gangal --- go/vt/vtgate/engine/route.go | 14 ++++------ go/vt/vtgate/planbuilder/route_planning.go | 24 ++++++++++++++--- .../planbuilder/testdata/filter_cases.txt | 19 -------------- .../testdata/systemtables_cases.txt | 26 ++++++++++++++++--- 4 files changed, 49 insertions(+), 34 deletions(-) diff --git a/go/vt/vtgate/engine/route.go b/go/vt/vtgate/engine/route.go index 7472ae2cd45..42e7d82bf99 100644 --- a/go/vt/vtgate/engine/route.go +++ b/go/vt/vtgate/engine/route.go @@ -21,6 +21,7 @@ import ( "fmt" "sort" "strconv" + "strings" "time" "vitess.io/vitess/go/vt/log" @@ -800,17 +801,12 @@ func (route *Route) description() PrimitiveDescription { other["SysTableTableSchema"] = sysTabSchema } if len(route.SysTableTableName) != 0 { - idx := 0 - sysTableName := "[" + var sysTableName []string for k, v := range route.SysTableTableName { - if idx != 0 { - sysTableName += ", " - } - sysTableName += k + ":" + v.String() - idx++ + sysTableName = append(sysTableName, k+":"+v.String()) } - sysTableName += "]" - other["SysTableTableName"] = sysTableName + sort.Strings(sysTableName) + other["SysTableTableName"] = "[" + strings.Join(sysTableName, ", ") + "]" } orderBy := GenericJoin(route.OrderBy, orderByToString) if orderBy != "" { diff --git a/go/vt/vtgate/planbuilder/route_planning.go b/go/vt/vtgate/planbuilder/route_planning.go index d5226d1778b..e1ae6fc4b7d 100644 --- a/go/vt/vtgate/planbuilder/route_planning.go +++ b/go/vt/vtgate/planbuilder/route_planning.go @@ -41,11 +41,28 @@ func gen4Planner(_ string) func(sqlparser.Statement, *sqlparser.ReservedVars, Co if !ok { return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "%T not yet supported", stmt) } - return newBuildSelectPlan(sel, reservedVars, vschema) + + getPlan := func(sel *sqlparser.Select) (logicalPlan, error) { + return newBuildSelectPlan(sel, reservedVars, vschema) + } + + plan, err := getPlan(sel) + if err != nil { + return nil, err + } + + if shouldRetryWithCNFRewriting(plan) { + // by transforming the predicates to CNF, the planner will sometimes find better plans + primitive := rewriteToCNFAndReplan(stmt, getPlan) + if primitive != nil { + return primitive, nil + } + } + return plan.Primitive(), nil } } -func newBuildSelectPlan(sel *sqlparser.Select, reservedVars *sqlparser.ReservedVars, vschema ContextVSchema) (engine.Primitive, error) { +func newBuildSelectPlan(sel *sqlparser.Select, reservedVars *sqlparser.ReservedVars, vschema ContextVSchema) (logicalPlan, error) { directives := sqlparser.ExtractCommentDirectives(sel.Comments) if len(directives) > 0 { @@ -100,7 +117,8 @@ func newBuildSelectPlan(sel *sqlparser.Select, reservedVars *sqlparser.ReservedV if err := plan.WireupGen4(semTable); err != nil { return nil, err } - return plan.Primitive(), nil + + return plan, nil } func optimizeQuery(opTree abstract.Operator, reservedVars *sqlparser.ReservedVars, semTable *semantics.SemTable, vschema ContextVSchema) (joinTree, error) { diff --git a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt index dda43a33e56..7ad39a0391d 100644 --- a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt @@ -1959,25 +1959,6 @@ Gen4 plan same as above } } -# able to isolate table_schema value even when hidden inside of ORs -"SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE (TABLE_SCHEMA = 'ks' and other_column = 42) OR (TABLE_SCHEMA = 'ks' and foobar = 'value')" -{ - "QueryType": "SELECT", - "Original": "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE (TABLE_SCHEMA = 'ks' and other_column = 42) OR (TABLE_SCHEMA = 'ks' and foobar = 'value')", - "Instructions": { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select * from INFORMATION_SCHEMA.`TABLES` where 1 != 1", - "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = :__vtschemaname and (other_column = 42 or TABLE_SCHEMA = 'ks') and (other_column = 42 or foobar = 'value')", - "SysTableTableSchema": "[VARBINARY(\"ks\")]", - "Table": "INFORMATION_SCHEMA.`TABLES`" - } -} - # solving LIKE query with a CFC prefix vindex "select c2 from cfc_vindex_col where c1 like 'A%'" { diff --git a/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt b/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt index 538090af6db..ffbe3fe54d3 100644 --- a/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/systemtables_cases.txt @@ -234,7 +234,7 @@ Gen4 plan same as above }, "FieldQuery": "select KCU.DELETE_RULE, S.UPDATE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC, INFORMATION_SCHEMA.K as S where 1 != 1", "Query": "select KCU.DELETE_RULE, S.UPDATE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC, INFORMATION_SCHEMA.K as S where S.TABLE_SCHEMA = :__vtschemaname and S.TABLE_NAME = :S_TABLE_NAME and KCU.TABLE_SCHEMA = :__vtschemaname and KCU.TABLE_NAME = :KCU_TABLE_NAME and KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME order by KCU.CONSTRAINT_NAME asc, KCU.COLUMN_NAME asc", - "SysTableTableName": "[S_TABLE_NAME:VARBINARY(\"sc\"), KCU_TABLE_NAME:VARBINARY(\"data_type_table\")]", + "SysTableTableName": "[KCU_TABLE_NAME:VARBINARY(\"data_type_table\"), S_TABLE_NAME:VARBINARY(\"sc\")]", "SysTableTableSchema": "[VARBINARY(\"test\"), VARBINARY(\"test\")]", "Table": "INFORMATION_SCHEMA.K, INFORMATION_SCHEMA.KEY_COLUMN_USAGE, INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS" } @@ -345,7 +345,7 @@ Gen4 plan same as above }, "FieldQuery": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc, information_schema.key_column_usage as fk where 1 != 1", "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc, information_schema.key_column_usage as fk where rc.constraint_schema = database() and rc.table_name = :rc_table_name and fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = :fk_table_name and rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name", - "SysTableTableName": "[rc_table_name:VARBINARY(\":vtg1\"), fk_table_name:VARBINARY(\":vtg1\")]", + "SysTableTableName": "[fk_table_name:VARBINARY(\":vtg1\"), rc_table_name:VARBINARY(\":vtg1\")]", "Table": "information_schema.key_column_usage, information_schema.referential_constraints" } } @@ -422,7 +422,7 @@ Gen4 plan same as above }, "FieldQuery": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc, information_schema.key_column_usage as fk where 1 != 1", "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc, information_schema.key_column_usage as fk where rc.constraint_schema = :__vtschemaname and rc.table_name = :rc_table_name and fk.referenced_column_name is not null and fk.table_schema = :__vtschemaname and fk.table_name = :fk_table_name and rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name", - "SysTableTableName": "[rc_table_name:VARBINARY(\"table_name\"), fk_table_name:VARBINARY(\"table_name\")]", + "SysTableTableName": "[fk_table_name:VARBINARY(\"table_name\"), rc_table_name:VARBINARY(\"table_name\")]", "SysTableTableSchema": "[VARBINARY(\"table_schema\"), VARBINARY(\"table_schema\")]", "Table": "information_schema.key_column_usage, information_schema.referential_constraints" } @@ -738,3 +738,23 @@ Gen4 plan same as above } } Gen4 plan same as above + +# able to isolate table_schema value even when hidden inside of ORs +"SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE (TABLE_SCHEMA = 'ks' and other_column = 42) OR (TABLE_SCHEMA = 'ks' and foobar = 'value')" +{ + "QueryType": "SELECT", + "Original": "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE (TABLE_SCHEMA = 'ks' and other_column = 42) OR (TABLE_SCHEMA = 'ks' and foobar = 'value')", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select * from INFORMATION_SCHEMA.`TABLES` where 1 != 1", + "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = :__vtschemaname and (other_column = 42 or TABLE_SCHEMA = 'ks') and (other_column = 42 or foobar = 'value')", + "SysTableTableSchema": "[VARBINARY(\"ks\")]", + "Table": "INFORMATION_SCHEMA.`TABLES`" + } +} +Gen4 plan same as above From 9312892e4da749a36be8e8a00321d0950a6b51a5 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Mon, 19 Jul 2021 15:48:17 +0530 Subject: [PATCH 6/9] added gen4 tests for system schema and fix planner to not fail if default keyspace is not set Signed-off-by: Harshit Gangal --- go/test/endtoend/vtgate/gen4/main_test.go | 20 ++ .../vtgate/gen4/system_schema_test.go | 202 ++++++++++++++++++ go/test/endtoend/vtgate/mysql80/misc_test.go | 32 +++ go/test/endtoend/vtgate/system_schema_test.go | 24 +-- go/vt/vtgate/executor_select_test.go | 81 +++++++ go/vt/vtgate/plan_execute.go | 4 + go/vt/vtgate/planbuilder/builder.go | 4 +- go/vt/vtgate/planbuilder/plan_test.go | 20 +- go/vt/vtgate/planbuilder/route_planning.go | 15 +- .../testdata/sysschema_default.txt | 35 +++ 10 files changed, 400 insertions(+), 37 deletions(-) create mode 100644 go/test/endtoend/vtgate/gen4/system_schema_test.go diff --git a/go/test/endtoend/vtgate/gen4/main_test.go b/go/test/endtoend/vtgate/gen4/main_test.go index d892042ae18..4969d5d8e50 100644 --- a/go/test/endtoend/vtgate/gen4/main_test.go +++ b/go/test/endtoend/vtgate/gen4/main_test.go @@ -77,6 +77,15 @@ create table t2( } } }` + + routingRules = ` +{"rules": [ + { + "from_table": "ks.t1000", + "to_tables": ["ks.t1"] + } +]} +` ) func TestMain(m *testing.M) { @@ -104,6 +113,17 @@ func TestMain(m *testing.M) { return 1 } + // apply routing rules + err = clusterInstance.VtctlclientProcess.ApplyRoutingRules(routingRules) + if err != nil { + return 1 + } + + err = clusterInstance.VtctlclientProcess.ExecuteCommand("RebuildVSchemaGraph") + if err != nil { + return 1 + } + // Start vtgate clusterInstance.VtGateExtraArgs = []string{"-planner_version", "Gen4"} // enable Gen4 planner. err = clusterInstance.StartVtgate() diff --git a/go/test/endtoend/vtgate/gen4/system_schema_test.go b/go/test/endtoend/vtgate/gen4/system_schema_test.go new file mode 100644 index 00000000000..c957e85446c --- /dev/null +++ b/go/test/endtoend/vtgate/gen4/system_schema_test.go @@ -0,0 +1,202 @@ +/* +Copyright 2020 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package vtgate + +import ( + "context" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +func TestDbNameOverride(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.Nil(t, err) + defer conn.Close() + qr, err := conn.ExecuteFetch("SELECT distinct database() FROM information_schema.tables WHERE table_schema = database()", 1000, true) + + require.Nil(t, err) + assert.Equal(t, 1, len(qr.Rows), "did not get enough rows back") + assert.Equal(t, "vt_ks", qr.Rows[0][0].ToString()) +} + +func TestInformationSchemaQuery(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.NoError(t, err) + defer conn.Close() + + assertSingleRowIsReturned(t, conn, "table_schema = 'ks'", "vt_ks") + assertSingleRowIsReturned(t, conn, "table_schema = 'vt_ks'", "vt_ks") + assertResultIsEmpty(t, conn, "table_schema = 'NONE'") + assertSingleRowIsReturned(t, conn, "table_schema = 'performance_schema'", "performance_schema") + assertResultIsEmpty(t, conn, "table_schema = 'PERFORMANCE_SCHEMA'") + assertSingleRowIsReturned(t, conn, "table_schema = 'performance_schema' and table_name = 'users'", "performance_schema") + assertResultIsEmpty(t, conn, "table_schema = 'performance_schema' and table_name = 'foo'") + assertSingleRowIsReturned(t, conn, "table_schema = 'vt_ks' and table_name = 't1'", "vt_ks") + assertSingleRowIsReturned(t, conn, "table_schema = 'ks' and table_name = 't1'", "vt_ks") +} + +func assertResultIsEmpty(t *testing.T, conn *mysql.Conn, pre string) { + t.Run(pre, func(t *testing.T) { + qr, err := conn.ExecuteFetch("SELECT distinct table_schema FROM information_schema.tables WHERE "+pre, 1000, true) + require.NoError(t, err) + assert.Empty(t, qr.Rows) + }) +} + +func assertSingleRowIsReturned(t *testing.T, conn *mysql.Conn, predicate string, expectedKs string) { + t.Run(predicate, func(t *testing.T) { + qr, err := conn.ExecuteFetch("SELECT distinct table_schema FROM information_schema.tables WHERE "+predicate, 1000, true) + require.NoError(t, err) + assert.Equal(t, 1, len(qr.Rows), "did not get enough rows back") + assert.Equal(t, expectedKs, qr.Rows[0][0].ToString()) + }) +} + +func TestInformationSchemaWithSubquery(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.NoError(t, err) + defer conn.Close() + + result := checkedExec(t, conn, "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = (SELECT SCHEMA()) AND TABLE_NAME = 'not_exists'") + assert.Empty(t, result.Rows) +} + +func TestInformationSchemaQueryGetsRoutedToTheRightTableAndKeyspace(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.NoError(t, err) + defer conn.Close() + + _ = checkedExec(t, conn, "SELECT id FROM t1000") // test that the routed table is available to us + result := checkedExec(t, conn, "SELECT * FROM information_schema.tables WHERE table_schema = database() and table_name='t1000'") + assert.NotEmpty(t, result.Rows) +} + +func TestFKConstraintUsingInformationSchema(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.NoError(t, err) + defer conn.Close() + + checkedExec(t, conn, "create table t7_xxhash(uid varchar(50),phone bigint,msg varchar(100),primary key(uid)) Engine=InnoDB") + checkedExec(t, conn, "create table t7_fk(id bigint,t7_uid varchar(50),primary key(id),CONSTRAINT t7_fk_ibfk_1 foreign key (t7_uid) references t7_xxhash(uid) on delete set null on update cascade) Engine=InnoDB;") + defer checkedExec(t, conn, "drop table t7_xxhash, t7_fk") + + query := "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as name, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk using (constraint_schema, constraint_name) where fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = 't7_fk' and rc.constraint_schema = database() and rc.table_name = 't7_fk'" + assertMatches(t, conn, query, `[[VARCHAR("t7_xxhash") VARCHAR("uid") VARCHAR("t7_uid") VARCHAR("t7_fk_ibfk_1") VARCHAR("CASCADE") VARCHAR("SET NULL")]]`) +} + +func TestConnectWithSystemSchema(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + for _, dbname := range []string{"information_schema", "mysql", "performance_schema", "sys"} { + connParams := vtParams + connParams.DbName = dbname + conn, err := mysql.Connect(ctx, &connParams) + require.NoError(t, err) + checkedExec(t, conn, `select @@max_allowed_packet from dual`) + conn.Close() + } +} + +func TestUseSystemSchema(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.NoError(t, err) + defer conn.Close() + for _, dbname := range []string{"information_schema", "mysql", "performance_schema", "sys"} { + checkedExec(t, conn, fmt.Sprintf("use %s", dbname)) + checkedExec(t, conn, `select @@max_allowed_packet from dual`) + } +} + +func TestSystemSchemaQueryWithoutQualifier(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.NoError(t, err) + defer conn.Close() + + queryWithQualifier := fmt.Sprintf("select t.table_schema,t.table_name,c.column_name,c.column_type "+ + "from information_schema.tables t "+ + "join information_schema.columns c "+ + "on c.table_schema = t.table_schema and c.table_name = t.table_name "+ + "where t.table_schema = '%s' and c.table_schema = '%s' "+ + "order by t.table_schema,t.table_name,c.column_name", KeyspaceName, KeyspaceName) + qr1 := checkedExec(t, conn, queryWithQualifier) + + checkedExec(t, conn, "use information_schema") + queryWithoutQualifier := fmt.Sprintf("select t.table_schema,t.table_name,c.column_name,c.column_type "+ + "from tables t "+ + "join columns c "+ + "on c.table_schema = t.table_schema and c.table_name = t.table_name "+ + "where t.table_schema = '%s' and c.table_schema = '%s' "+ + "order by t.table_schema,t.table_name,c.column_name", KeyspaceName, KeyspaceName) + qr2 := checkedExec(t, conn, queryWithoutQualifier) + require.Equal(t, qr1, qr2) + + connParams := vtParams + connParams.DbName = "information_schema" + conn2, err := mysql.Connect(ctx, &connParams) + require.NoError(t, err) + defer conn2.Close() + + qr3 := checkedExec(t, conn2, queryWithoutQualifier) + require.Equal(t, qr2, qr3) +} + +func TestMultipleSchemaPredicates(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.NoError(t, err) + defer conn.Close() + + query := fmt.Sprintf("select t.table_schema,t.table_name,c.column_name,c.column_type "+ + "from information_schema.tables t "+ + "join information_schema.columns c "+ + "on c.table_schema = t.table_schema and c.table_name = t.table_name "+ + "where t.table_schema = '%s' and c.table_schema = '%s' and c.table_schema = '%s' and c.table_schema = '%s'", KeyspaceName, KeyspaceName, KeyspaceName, KeyspaceName) + qr1 := checkedExec(t, conn, query) + require.EqualValues(t, 4, len(qr1.Fields)) + + // test a query with two keyspace names + query = fmt.Sprintf("select t.table_schema,t.table_name,c.column_name,c.column_type "+ + "from information_schema.tables t "+ + "join information_schema.columns c "+ + "on c.table_schema = t.table_schema and c.table_name = t.table_name "+ + "where t.table_schema = '%s' and c.table_schema = '%s' and c.table_schema = '%s'", KeyspaceName, KeyspaceName, "a") + _, err = conn.ExecuteFetch(query, 1000, true) + require.Error(t, err) + require.Contains(t, err.Error(), "specifying two different database in the query is not supported") +} diff --git a/go/test/endtoend/vtgate/mysql80/misc_test.go b/go/test/endtoend/vtgate/mysql80/misc_test.go index 0f614535dc1..c0e50459ea6 100644 --- a/go/test/endtoend/vtgate/mysql80/misc_test.go +++ b/go/test/endtoend/vtgate/mysql80/misc_test.go @@ -18,8 +18,11 @@ package vtgate import ( "context" + "fmt" "testing" + "github.com/google/go-cmp/cmp" + "vitess.io/vitess/go/test/endtoend/cluster" "github.com/stretchr/testify/require" @@ -71,6 +74,35 @@ ts12 TIMESTAMP DEFAULT LOCALTIME() exec(t, conn, "drop table function_default") } +// TestCheckConstraint test check constraints on CREATE TABLE +// This feature is supported from MySQL 8.0.16 and MariaDB 10.2.1. +func TestCheckConstraint(t *testing.T) { + conn, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + defer conn.Close() + + query := `CREATE TABLE t7 (CHECK (c1 <> c2), c1 INT CHECK (c1 > 10), c2 INT CONSTRAINT c2_positive CHECK (c2 > 0), c3 INT CHECK (c3 < 100), CONSTRAINT c1_nonzero CHECK (c1 <> 0), CHECK (c1 > c3));` + exec(t, conn, query) + + checkQuery := `SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 't7' order by CONSTRAINT_NAME;` + expected := `[[VARCHAR("c1_nonzero")] [VARCHAR("c2_positive")] [VARCHAR("t7_chk_1")] [VARCHAR("t7_chk_2")] [VARCHAR("t7_chk_3")] [VARCHAR("t7_chk_4")]]` + + assertMatches(t, conn, checkQuery, expected) + + cleanup := `DROP TABLE t7` + exec(t, conn, cleanup) +} + +func assertMatches(t *testing.T, conn *mysql.Conn, query, expected string) { + t.Helper() + qr := exec(t, conn, query) + got := fmt.Sprintf("%v", qr.Rows) + diff := cmp.Diff(expected, got) + if diff != "" { + t.Errorf("Query: %s (-want +got):\n%s", query, diff) + } +} + func exec(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result { t.Helper() qr, err := conn.ExecuteFetch(query, 1000, true) diff --git a/go/test/endtoend/vtgate/system_schema_test.go b/go/test/endtoend/vtgate/system_schema_test.go index 31e5353eff7..ee400184c6d 100644 --- a/go/test/endtoend/vtgate/system_schema_test.go +++ b/go/test/endtoend/vtgate/system_schema_test.go @@ -29,28 +29,6 @@ import ( "vitess.io/vitess/go/test/endtoend/cluster" ) -// TestCheckConstraint test check constraints on CREATE TABLE -// This feature is supported from MySQL 8.0.16 and MariaDB 10.2.1. -func TestCheckConstraint(t *testing.T) { - // Skipping as tests are run against MySQL 5.7 - t.Skip() - - conn, err := mysql.Connect(context.Background(), &vtParams) - require.NoError(t, err) - defer conn.Close() - - query := `CREATE TABLE t7 (CHECK (c1 <> c2), c1 INT CHECK (c1 > 10), c2 INT CONSTRAINT c2_positive CHECK (c2 > 0), c3 INT CHECK (c3 < 100), CONSTRAINT c1_nonzero CHECK (c1 <> 0), CHECK (c1 > c3));` - exec(t, conn, query) - - checkQuery := `SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 't7';` - expected := `[[VARCHAR("t7_chk_1")] [VARCHAR("t7_chk_2")] [VARCHAR("c2_positive")] [VARCHAR("t7_chk_3")] [VARCHAR("c1_nonzero")] [VARCHAR("t7_chk_4")]]` - - assertMatches(t, conn, checkQuery, expected) - - cleanup := `DROP TABLE t7` - exec(t, conn, cleanup) -} - func TestDbNameOverride(t *testing.T) { defer cluster.PanicHandler(t) ctx := context.Background() @@ -173,13 +151,13 @@ func TestSystemSchemaQueryWithoutQualifier(t *testing.T) { "order by t.table_schema,t.table_name,c.column_name", KeyspaceName, KeyspaceName) qr1 := exec(t, conn, queryWithQualifier) + exec(t, conn, "use information_schema") queryWithoutQualifier := fmt.Sprintf("select t.table_schema,t.table_name,c.column_name,c.column_type "+ "from tables t "+ "join columns c "+ "on c.table_schema = t.table_schema and c.table_name = t.table_name "+ "where t.table_schema = '%s' and c.table_schema = '%s' "+ "order by t.table_schema,t.table_name,c.column_name", KeyspaceName, KeyspaceName) - exec(t, conn, "use information_schema") qr2 := exec(t, conn, queryWithoutQualifier) require.Equal(t, qr1, qr2) diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index a5794243b74..80100598098 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -115,6 +115,87 @@ func TestSelectDBA(t *testing.T) { utils.MustMatch(t, wantQueries, sbc1.Queries) } +func TestGen4SelectDBA(t *testing.T) { + executor, sbc1, _, _ := createExecutorEnv() + executor.normalize = true + *plannerVersion = "Gen4" + defer func() { + // change it back to v3 + *plannerVersion = "v3" + }() + + query := "select * from INFORMATION_SCHEMA.foo" + _, err := executor.Execute(context.Background(), "TestSelectDBA", + NewSafeSession(&vtgatepb.Session{TargetString: "TestExecutor"}), + query, map[string]*querypb.BindVariable{}, + ) + require.NoError(t, err) + wantQueries := []*querypb.BoundQuery{{Sql: query, BindVariables: map[string]*querypb.BindVariable{}}} + utils.MustMatch(t, wantQueries, sbc1.Queries) + + sbc1.Queries = nil + query = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES ist WHERE ist.table_schema = 'performance_schema' AND ist.table_name = 'foo'" + _, err = executor.Execute(context.Background(), "TestSelectDBA", + NewSafeSession(&vtgatepb.Session{TargetString: "TestExecutor"}), + query, map[string]*querypb.BindVariable{}, + ) + require.NoError(t, err) + wantQueries = []*querypb.BoundQuery{{Sql: "select COUNT(*) from INFORMATION_SCHEMA.`TABLES` as ist where ist.table_schema = :__vtschemaname and ist.table_name = :ist_table_name", + BindVariables: map[string]*querypb.BindVariable{ + "vtg1": sqltypes.StringBindVariable("performance_schema"), + "vtg2": sqltypes.StringBindVariable("foo"), + "__vtschemaname": sqltypes.StringBindVariable("performance_schema"), + "ist_table_name": sqltypes.StringBindVariable("foo"), + }}} + utils.MustMatch(t, wantQueries, sbc1.Queries) + + sbc1.Queries = nil + query = "select 1 from information_schema.table_constraints where constraint_schema = 'vt_ks' and table_name = 'user'" + _, err = executor.Execute(context.Background(), "TestSelectDBA", + NewSafeSession(&vtgatepb.Session{TargetString: "TestExecutor"}), + query, map[string]*querypb.BindVariable{}, + ) + require.NoError(t, err) + wantQueries = []*querypb.BoundQuery{{Sql: "select :vtg1 from information_schema.table_constraints where constraint_schema = :__vtschemaname and table_name = :table_name", + BindVariables: map[string]*querypb.BindVariable{ + "vtg1": sqltypes.Int64BindVariable(1), + "vtg2": sqltypes.StringBindVariable("vt_ks"), + "vtg3": sqltypes.StringBindVariable("user"), + "__vtschemaname": sqltypes.StringBindVariable("vt_ks"), + "table_name": sqltypes.StringBindVariable("user"), + }}} + utils.MustMatch(t, wantQueries, sbc1.Queries) + + sbc1.Queries = nil + query = "select 1 from information_schema.table_constraints where constraint_schema = 'vt_ks'" + _, err = executor.Execute(context.Background(), "TestSelectDBA", + NewSafeSession(&vtgatepb.Session{TargetString: "TestExecutor"}), + query, map[string]*querypb.BindVariable{}, + ) + require.NoError(t, err) + wantQueries = []*querypb.BoundQuery{{Sql: "select :vtg1 from information_schema.table_constraints where constraint_schema = :__vtschemaname", + BindVariables: map[string]*querypb.BindVariable{ + "vtg1": sqltypes.Int64BindVariable(1), + "vtg2": sqltypes.StringBindVariable("vt_ks"), + "__vtschemaname": sqltypes.StringBindVariable("vt_ks"), + }}} + utils.MustMatch(t, wantQueries, sbc1.Queries) + + sbc1.Queries = nil + query = "select t.table_schema,t.table_name,c.column_name,c.column_type from tables t join columns c on c.table_schema = t.table_schema and c.table_name = t.table_name where t.table_schema = 'TestExecutor' and c.table_schema = 'TestExecutor' order by t.table_schema,t.table_name,c.column_name" + _, err = executor.Execute(context.Background(), "TestSelectDBA", + NewSafeSession(&vtgatepb.Session{TargetString: "information_schema"}), + query, map[string]*querypb.BindVariable{}, + ) + require.NoError(t, err) + wantQueries = []*querypb.BoundQuery{{Sql: "select t.table_schema, t.table_name, c.column_name, c.column_type from information_schema.`tables` as t, information_schema.`columns` as c where t.table_schema = :__vtschemaname and c.table_schema = :__vtschemaname and c.table_schema = t.table_schema and c.table_name = t.table_name order by t.table_schema asc, t.table_name asc, c.column_name asc", + BindVariables: map[string]*querypb.BindVariable{ + "vtg1": sqltypes.StringBindVariable("TestExecutor"), + "__replacevtschemaname": sqltypes.Int64BindVariable(1), + }}} + utils.MustMatch(t, wantQueries, sbc1.Queries) +} + func TestUnsharded(t *testing.T) { executor, _, _, sbclookup := createLegacyExecutorEnv() diff --git a/go/vt/vtgate/plan_execute.go b/go/vt/vtgate/plan_execute.go index 3865ffabad3..2341619863f 100644 --- a/go/vt/vtgate/plan_execute.go +++ b/go/vt/vtgate/plan_execute.go @@ -18,6 +18,8 @@ package vtgate import ( "context" + "encoding/json" + "fmt" "time" "vitess.io/vitess/go/sqltypes" @@ -60,6 +62,8 @@ func (e *Executor) newExecute(ctx context.Context, safeSession *SafeSession, sql if err == planbuilder.ErrPlanNotSupported { return 0, nil, err } + bout, _ := json.MarshalIndent(plan, "", " ") + fmt.Println(string(bout)) execStart := e.logPlanningFinished(logStats, plan) if err != nil { diff --git a/go/vt/vtgate/planbuilder/builder.go b/go/vt/vtgate/planbuilder/builder.go index 5260ff184c4..2f61da958e4 100644 --- a/go/vt/vtgate/planbuilder/builder.go +++ b/go/vt/vtgate/planbuilder/builder.go @@ -88,12 +88,12 @@ type truncater interface { // TestBuilder builds a plan for a query based on the specified vschema. // This method is only used from tests -func TestBuilder(query string, vschema ContextVSchema) (*engine.Plan, error) { +func TestBuilder(query string, vschema ContextVSchema, keyspace string) (*engine.Plan, error) { stmt, reserved, err := sqlparser.Parse2(query) if err != nil { return nil, err } - result, err := sqlparser.RewriteAST(stmt, "") + result, err := sqlparser.RewriteAST(stmt, keyspace) if err != nil { return nil, err } diff --git a/go/vt/vtgate/planbuilder/plan_test.go b/go/vt/vtgate/planbuilder/plan_test.go index 852b0caf4c7..f3ca82587e9 100644 --- a/go/vt/vtgate/planbuilder/plan_test.go +++ b/go/vt/vtgate/planbuilder/plan_test.go @@ -287,7 +287,7 @@ func TestWithSystemSchemaAsDefaultKeyspace(t *testing.T) { defer os.RemoveAll(testOutputTempDir) vschema := &vschemaWrapper{ v: loadSchema(t, "schema_test.json"), - keyspace: &vindexes.Keyspace{Name: "mysql"}, + keyspace: &vindexes.Keyspace{Name: "information_schema"}, tabletType: topodatapb.TabletType_MASTER, } @@ -469,6 +469,10 @@ func escapeNewLines(in string) string { } func testFile(t *testing.T, filename, tempDir string, vschema *vschemaWrapper, checkGen4equalPlan bool) { + ksName := "" + if vschema.keyspace != nil { + ksName = vschema.keyspace.Name + } var checkAllTests = false t.Run(filename, func(t *testing.T) { expected := &strings.Builder{} @@ -477,7 +481,7 @@ func testFile(t *testing.T, filename, tempDir string, vschema *vschemaWrapper, c for tcase := range iterateExecFile(filename) { t.Run(fmt.Sprintf("%d V3: %s", tcase.lineno, tcase.comments), func(t *testing.T) { vschema.version = V3 - plan, err := TestBuilder(tcase.input, vschema) + plan, err := TestBuilder(tcase.input, vschema, ksName) out := getPlanOrErrorOutput(err, plan) if out != tcase.output { @@ -554,7 +558,11 @@ func getPlanOutput(tcase testCase, vschema *vschemaWrapper) (out string, err err out = fmt.Sprintf("panicked: %v\n%s", r, string(debug.Stack())) } }() - plan, err := TestBuilder(tcase.input, vschema) + ksName := "" + if vschema.keyspace != nil { + ksName = vschema.keyspace.Name + } + plan, err := TestBuilder(tcase.input, vschema, ksName) out = getPlanOrErrorOutput(err, plan) return out, err } @@ -739,12 +747,16 @@ func BenchmarkSelectVsDML(b *testing.B) { } func benchmarkPlanner(b *testing.B, version PlannerVersion, testCases []testCase, vschema *vschemaWrapper) { + ksName := "" + if vschema.keyspace != nil { + ksName = vschema.keyspace.Name + } b.ReportAllocs() for n := 0; n < b.N; n++ { for _, tcase := range testCases { if tcase.output2ndPlanner != "" { vschema.version = version - _, _ = TestBuilder(tcase.input, vschema) + _, _ = TestBuilder(tcase.input, vschema, ksName) } } } diff --git a/go/vt/vtgate/planbuilder/route_planning.go b/go/vt/vtgate/planbuilder/route_planning.go index e1ae6fc4b7d..c74907c8cd2 100644 --- a/go/vt/vtgate/planbuilder/route_planning.go +++ b/go/vt/vtgate/planbuilder/route_planning.go @@ -68,11 +68,11 @@ func newBuildSelectPlan(sel *sqlparser.Select, reservedVars *sqlparser.ReservedV if len(directives) > 0 { return nil, semantics.Gen4NotSupportedF("comment directives") } - keyspace, err := vschema.DefaultKeyspace() - if err != nil { - return nil, err + ksName := "" + if ks, _ := vschema.DefaultKeyspace(); ks != nil { + ksName = ks.Name } - semTable, err := semantics.Analyze(sel, keyspace.Name, vschema) + semTable, err := semantics.Analyze(sel, ksName, vschema) if err != nil { return nil, err } @@ -582,20 +582,19 @@ func removeAt(plans []joinTree, idx int) []joinTree { func createRoutePlan(table *abstract.QueryTable, solves semantics.TableSet, reservedVars *sqlparser.ReservedVars, vschema ContextVSchema) (*routePlan, error) { if table.IsInfSchema { - defaultKeyspace, err := vschema.DefaultKeyspace() + ks, err := vschema.AnyKeyspace() if err != nil { return nil, err } rp := &routePlan{ routeOpCode: engine.SelectDBA, solved: solves, - // TODO: find keyspace to route using the predicates as in v3 - keyspace: defaultKeyspace, + keyspace: ks, tables: []relation{&routeTable{ qtable: table, vtable: &vindexes.Table{ Name: table.Table.Name, - Keyspace: defaultKeyspace, + Keyspace: ks, }, }}, predicates: table.Predicates, diff --git a/go/vt/vtgate/planbuilder/testdata/sysschema_default.txt b/go/vt/vtgate/planbuilder/testdata/sysschema_default.txt index 2d33f6d517d..0fc59247f61 100644 --- a/go/vt/vtgate/planbuilder/testdata/sysschema_default.txt +++ b/go/vt/vtgate/planbuilder/testdata/sysschema_default.txt @@ -16,3 +16,38 @@ } } Gen4 plan same as above + +# unqualified table name +"select t.table_schema,t.table_name,c.column_name,c.column_type from tables t join columns c on c.table_schema = t.table_schema and c.table_name = t.table_name where t.table_schema = 'user' and c.table_schema = 'user' order by t.table_schema,t.table_name,c.column_name" +{ + "QueryType": "SELECT", + "Original": "select t.table_schema,t.table_name,c.column_name,c.column_type from tables t join columns c on c.table_schema = t.table_schema and c.table_name = t.table_name where t.table_schema = 'user' and c.table_schema = 'user' order by t.table_schema,t.table_name,c.column_name", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select t.table_schema, t.table_name, c.column_name, c.column_type from information_schema.`tables` as t join information_schema.`columns` as c on c.table_schema = t.table_schema and c.table_name = t.table_name where 1 != 1", + "Query": "select t.table_schema, t.table_name, c.column_name, c.column_type from information_schema.`tables` as t join information_schema.`columns` as c on c.table_schema = t.table_schema and c.table_name = t.table_name where t.table_schema = :__vtschemaname and c.table_schema = :__vtschemaname order by t.table_schema asc, t.table_name asc, c.column_name asc", + "SysTableTableSchema": "[VARBINARY(\"user\"), VARBINARY(\"user\")]", + "Table": "information_schema.`tables`, information_schema.`columns`" + } +} +{ + "QueryType": "SELECT", + "Original": "select t.table_schema,t.table_name,c.column_name,c.column_type from tables t join columns c on c.table_schema = t.table_schema and c.table_name = t.table_name where t.table_schema = 'user' and c.table_schema = 'user' order by t.table_schema,t.table_name,c.column_name", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select t.table_schema, t.table_name, c.column_name, c.column_type from information_schema.`tables` as t, information_schema.`columns` as c where 1 != 1", + "Query": "select t.table_schema, t.table_name, c.column_name, c.column_type from information_schema.`tables` as t, information_schema.`columns` as c where t.table_schema = :__vtschemaname and c.table_schema = :__vtschemaname and c.table_schema = t.table_schema and c.table_name = t.table_name order by t.table_schema asc, t.table_name asc, c.column_name asc", + "SysTableTableSchema": "[VARBINARY(\"user\"), VARBINARY(\"user\")]", + "Table": "information_schema.`columns`, information_schema.`tables`" + } +} From b2e4f414e5d2d49a8a4adcb0e05b497ffddb465f Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Mon, 19 Jul 2021 17:09:07 +0530 Subject: [PATCH 7/9] fix tests Signed-off-by: Harshit Gangal --- go/test/endtoend/vtgate/gen4/system_schema_test.go | 2 +- go/vt/vtgate/executor_select_test.go | 6 +++--- go/vt/vtgate/plan_execute.go | 4 ---- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/go/test/endtoend/vtgate/gen4/system_schema_test.go b/go/test/endtoend/vtgate/gen4/system_schema_test.go index c957e85446c..cbd3cd2489f 100644 --- a/go/test/endtoend/vtgate/gen4/system_schema_test.go +++ b/go/test/endtoend/vtgate/gen4/system_schema_test.go @@ -109,7 +109,7 @@ func TestFKConstraintUsingInformationSchema(t *testing.T) { checkedExec(t, conn, "create table t7_xxhash(uid varchar(50),phone bigint,msg varchar(100),primary key(uid)) Engine=InnoDB") checkedExec(t, conn, "create table t7_fk(id bigint,t7_uid varchar(50),primary key(id),CONSTRAINT t7_fk_ibfk_1 foreign key (t7_uid) references t7_xxhash(uid) on delete set null on update cascade) Engine=InnoDB;") - defer checkedExec(t, conn, "drop table t7_xxhash, t7_fk") + defer checkedExec(t, conn, "drop table t7_fk, t7_xxhash") query := "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as name, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk using (constraint_schema, constraint_name) where fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = 't7_fk' and rc.constraint_schema = database() and rc.table_name = 't7_fk'" assertMatches(t, conn, query, `[[VARCHAR("t7_xxhash") VARCHAR("uid") VARCHAR("t7_uid") VARCHAR("t7_fk_ibfk_1") VARCHAR("CASCADE") VARCHAR("SET NULL")]]`) diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index 80100598098..96fadd80842 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -118,7 +118,7 @@ func TestSelectDBA(t *testing.T) { func TestGen4SelectDBA(t *testing.T) { executor, sbc1, _, _ := createExecutorEnv() executor.normalize = true - *plannerVersion = "Gen4" + *plannerVersion = "gen4" defer func() { // change it back to v3 *plannerVersion = "v3" @@ -182,13 +182,13 @@ func TestGen4SelectDBA(t *testing.T) { utils.MustMatch(t, wantQueries, sbc1.Queries) sbc1.Queries = nil - query = "select t.table_schema,t.table_name,c.column_name,c.column_type from tables t join columns c on c.table_schema = t.table_schema and c.table_name = t.table_name where t.table_schema = 'TestExecutor' and c.table_schema = 'TestExecutor' order by t.table_schema,t.table_name,c.column_name" + query = "select t.table_schema,t.table_name,c.column_name,c.column_type from tables t join columns c on c.table_schema = t.table_schema and c.table_name = t.table_name where t.table_schema = 'TestExecutor' order by t.table_schema,t.table_name,c.column_name" _, err = executor.Execute(context.Background(), "TestSelectDBA", NewSafeSession(&vtgatepb.Session{TargetString: "information_schema"}), query, map[string]*querypb.BindVariable{}, ) require.NoError(t, err) - wantQueries = []*querypb.BoundQuery{{Sql: "select t.table_schema, t.table_name, c.column_name, c.column_type from information_schema.`tables` as t, information_schema.`columns` as c where t.table_schema = :__vtschemaname and c.table_schema = :__vtschemaname and c.table_schema = t.table_schema and c.table_name = t.table_name order by t.table_schema asc, t.table_name asc, c.column_name asc", + wantQueries = []*querypb.BoundQuery{{Sql: "select t.table_schema, t.table_name, c.column_name, c.column_type from information_schema.`tables` as t, information_schema.`columns` as c where t.table_schema = :__vtschemaname and c.table_schema = t.table_schema and c.table_name = t.table_name order by t.table_schema asc, t.table_name asc, c.column_name asc", BindVariables: map[string]*querypb.BindVariable{ "vtg1": sqltypes.StringBindVariable("TestExecutor"), "__replacevtschemaname": sqltypes.Int64BindVariable(1), diff --git a/go/vt/vtgate/plan_execute.go b/go/vt/vtgate/plan_execute.go index 2341619863f..3865ffabad3 100644 --- a/go/vt/vtgate/plan_execute.go +++ b/go/vt/vtgate/plan_execute.go @@ -18,8 +18,6 @@ package vtgate import ( "context" - "encoding/json" - "fmt" "time" "vitess.io/vitess/go/sqltypes" @@ -62,8 +60,6 @@ func (e *Executor) newExecute(ctx context.Context, safeSession *SafeSession, sql if err == planbuilder.ErrPlanNotSupported { return 0, nil, err } - bout, _ := json.MarshalIndent(plan, "", " ") - fmt.Println(string(bout)) execStart := e.logPlanningFinished(logStats, plan) if err != nil { From 321dd4e49a356a8df70a3dfc04b6389e01dca302 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Mon, 19 Jul 2021 19:52:42 +0530 Subject: [PATCH 8/9] check keyspace before merging routes only if both the route opcodes are not information_schema queries Signed-off-by: Harshit Gangal --- go/vt/vtgate/executor_select_test.go | 4 ++-- go/vt/vtgate/planbuilder/route_planning.go | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index 96fadd80842..413cbb4eb0e 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -182,13 +182,13 @@ func TestGen4SelectDBA(t *testing.T) { utils.MustMatch(t, wantQueries, sbc1.Queries) sbc1.Queries = nil - query = "select t.table_schema,t.table_name,c.column_name,c.column_type from tables t join columns c on c.table_schema = t.table_schema and c.table_name = t.table_name where t.table_schema = 'TestExecutor' order by t.table_schema,t.table_name,c.column_name" + query = "select t.table_schema,t.table_name,c.column_name,c.column_type from tables t join columns c on c.table_schema = t.table_schema and c.table_name = t.table_name where t.table_schema = 'TestExecutor' and c.table_schema = 'TestExecutor' order by t.table_schema,t.table_name,c.column_name" _, err = executor.Execute(context.Background(), "TestSelectDBA", NewSafeSession(&vtgatepb.Session{TargetString: "information_schema"}), query, map[string]*querypb.BindVariable{}, ) require.NoError(t, err) - wantQueries = []*querypb.BoundQuery{{Sql: "select t.table_schema, t.table_name, c.column_name, c.column_type from information_schema.`tables` as t, information_schema.`columns` as c where t.table_schema = :__vtschemaname and c.table_schema = t.table_schema and c.table_name = t.table_name order by t.table_schema asc, t.table_name asc, c.column_name asc", + wantQueries = []*querypb.BoundQuery{{Sql: "select t.table_schema, t.table_name, c.column_name, c.column_type from information_schema.`tables` as t, information_schema.`columns` as c where t.table_schema = :__vtschemaname and c.table_schema = :__vtschemaname and c.table_schema = t.table_schema and c.table_name = t.table_name order by t.table_schema asc, t.table_name asc, c.column_name asc", BindVariables: map[string]*querypb.BindVariable{ "vtg1": sqltypes.StringBindVariable("TestExecutor"), "__replacevtschemaname": sqltypes.Int64BindVariable(1), diff --git a/go/vt/vtgate/planbuilder/route_planning.go b/go/vt/vtgate/planbuilder/route_planning.go index c74907c8cd2..92033cd6a34 100644 --- a/go/vt/vtgate/planbuilder/route_planning.go +++ b/go/vt/vtgate/planbuilder/route_planning.go @@ -729,6 +729,11 @@ func tryMerge(a, b joinTree, joinPredicates []sqlparser.Expr, semTable *semantic if aRoute == nil || bRoute == nil { return nil } + // If both the routes are system schema queries then we do not validate the keyspaces at plan time. As they are not always the ones where the query will be sent to. + if (aRoute.routeOpCode != engine.SelectDBA || + bRoute.routeOpCode != engine.SelectDBA) && aRoute.keyspace != bRoute.keyspace { + return nil + } newTabletSet := aRoute.solved | bRoute.solved @@ -777,9 +782,6 @@ func joinTreesToRoutes(a, b joinTree) (*routePlan, *routePlan) { if !ok { return nil, nil } - if aRoute.keyspace != bRoute.keyspace { - return nil, nil - } return aRoute, bRoute } From 08fc0be9232eae57482bc2670b26d2656fd9c18f Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Mon, 19 Jul 2021 20:19:34 +0530 Subject: [PATCH 9/9] fix route plan unit test Signed-off-by: Harshit Gangal --- go/vt/vtgate/planbuilder/route_planning_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go/vt/vtgate/planbuilder/route_planning_test.go b/go/vt/vtgate/planbuilder/route_planning_test.go index 75b656c88cc..e392ae25035 100644 --- a/go/vt/vtgate/planbuilder/route_planning_test.go +++ b/go/vt/vtgate/planbuilder/route_planning_test.go @@ -82,11 +82,11 @@ func TestMergeJoins(t *testing.T) { }, { l: selectDBA(1, ks), r: selectDBA(2, ks2), - expected: nil, + expected: selectDBA(1|2, ks), }, { l: selectDBA(2, ks), r: selectDBA(1, ks2), - expected: nil, + expected: selectDBA(1|2, ks), }, { l: unsharded(1, ks), r: selectDBA(2, ks),