diff --git a/go/vt/vtgate/planbuilder/route.go b/go/vt/vtgate/planbuilder/route.go index a522f7fee04..d976278ddb6 100644 --- a/go/vt/vtgate/planbuilder/route.go +++ b/go/vt/vtgate/planbuilder/route.go @@ -394,6 +394,18 @@ func (rb *route) Inputs() []logicalPlan { // with the outer route. func (rb *route) MergeSubquery(pb *primitiveBuilder, inner *route) bool { if rb.SubqueryCanMerge(pb, inner) { + if inner.eroute.Opcode == engine.SelectDBA && (len(inner.eroute.SysTableTableName) > 0 || len(inner.eroute.SysTableTableSchema) > 0) { + switch rb.eroute.Opcode { + case engine.SelectDBA, engine.SelectReference: + rb.eroute.SysTableTableSchema = append(rb.eroute.SysTableTableSchema, inner.eroute.SysTableTableSchema...) + for k, v := range inner.eroute.SysTableTableName { + rb.eroute.SysTableTableName[k] = v + } + rb.eroute.Opcode = engine.SelectDBA + default: + return false + } + } rb.substitutions = append(rb.substitutions, inner.substitutions...) inner.Redirect = rb return true diff --git a/go/vt/vtgate/planbuilder/route_planning.go b/go/vt/vtgate/planbuilder/route_planning.go index 14f2d784646..e5461de3b98 100644 --- a/go/vt/vtgate/planbuilder/route_planning.go +++ b/go/vt/vtgate/planbuilder/route_planning.go @@ -150,7 +150,7 @@ func optimizeSubQuery(ctx *planningContext, op *abstract.SubQuery) (queryTree, e preds := inner.Inner.UnsolvedPredicates(ctx.semTable) merger := func(a, b *routeTree) (*routeTree, error) { - return mergeSubQuery(ctx, a, inner) + return mergeSubQuery(ctx, a, b, inner) } merged, err := tryMergeSubQuery(ctx, outerTree, treeInner, inner, preds, merger) @@ -279,7 +279,7 @@ func rewriteSubqueryDependenciesForJoin(ctx *planningContext, otherTree queryTre return rewriteError } -func mergeSubQuery(ctx *planningContext, outer *routeTree, subq *abstract.SubQueryInner) (*routeTree, error) { +func mergeSubQuery(ctx *planningContext, outer *routeTree, inner *routeTree, subq *abstract.SubQueryInner) (*routeTree, error) { ctx.sqToReplace[subq.ArgName] = subq.SelectStatement // go over the subquery and add its tables to the one's solved by the route it is merged with // this is needed to so that later when we try to push projections, we get the correct @@ -294,6 +294,11 @@ func mergeSubQuery(ctx *planningContext, outer *routeTree, subq *abstract.SubQue if err != nil { return nil, err } + outer.SysTableTableSchema = append(outer.SysTableTableSchema, inner.SysTableTableSchema...) + for k, v := range inner.SysTableTableName { + outer.SysTableTableName[k] = v + } + err = outer.resetRoutingSelections(ctx) if err != nil { return nil, err diff --git a/go/vt/vtgate/planbuilder/testdata/sysschema_default.txt b/go/vt/vtgate/planbuilder/testdata/sysschema_default.txt index 0fc59247f61..17f9390b579 100644 --- a/go/vt/vtgate/planbuilder/testdata/sysschema_default.txt +++ b/go/vt/vtgate/planbuilder/testdata/sysschema_default.txt @@ -51,3 +51,58 @@ Gen4 plan same as above "Table": "information_schema.`columns`, information_schema.`tables`" } } + +# system schema query as a subquery +"SELECT (SELECT 1 FROM information_schema.schemata WHERE schema_name='MyDatabase' LIMIT 1);" +{ + "QueryType": "SELECT", + "Original": "SELECT (SELECT 1 FROM information_schema.schemata WHERE schema_name='MyDatabase' LIMIT 1);", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select (select 1 from information_schema.schemata where 1 != 1) from dual where 1 != 1", + "Query": "select (select 1 from information_schema.schemata where schema_name = :__vtschemaname limit 1) from dual", + "SysTableTableSchema": "[VARBINARY(\"MyDatabase\")]", + "Table": "dual" + } +} +Gen4 plan same as above + +# system schema query as a derived table +"SELECT * from (SELECT 1 FROM information_schema.schemata WHERE schema_name='MyDatabase' LIMIT 1) x" +{ + "QueryType": "SELECT", + "Original": "SELECT * from (SELECT 1 FROM information_schema.schemata WHERE schema_name='MyDatabase' LIMIT 1) x", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select * from (select 1 from information_schema.schemata where 1 != 1) as x where 1 != 1", + "Query": "select * from (select 1 from information_schema.schemata where schema_name = :__vtschemaname limit 1) as x", + "SysTableTableSchema": "[VARBINARY(\"MyDatabase\")]", + "Table": "information_schema.schemata" + } +} +{ + "QueryType": "SELECT", + "Original": "SELECT * from (SELECT 1 FROM information_schema.schemata WHERE schema_name='MyDatabase' LIMIT 1) x", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select x.`1` from (select 1 from information_schema.schemata where 1 != 1) as x where 1 != 1", + "Query": "select x.`1` from (select 1 from information_schema.schemata where schema_name = :__vtschemaname limit 1) as x", + "SysTableTableSchema": "[VARBINARY(\"MyDatabase\")]", + "Table": "information_schema.schemata" + } +}