diff --git a/go/vt/sqlparser/ast_funcs.go b/go/vt/sqlparser/ast_funcs.go index 201a0b8315c..af57e02ee88 100644 --- a/go/vt/sqlparser/ast_funcs.go +++ b/go/vt/sqlparser/ast_funcs.go @@ -2145,6 +2145,18 @@ func RemoveKeyspace(in SQLNode) { }, in) } +// RemoveKeyspaceInTables removes the database qualifier for all table names in the AST +func RemoveKeyspaceInTables(in SQLNode) { + Rewrite(in, nil, func(cursor *Cursor) bool { + if tbl, ok := cursor.Node().(TableName); ok && !tbl.Qualifier.IsEmpty() { + tbl.Qualifier = NewIdentifierCS("") + cursor.Replace(tbl) + } + + return true + }) +} + func convertStringToInt(integer string) int { val, _ := strconv.Atoi(integer) return val diff --git a/go/vt/vtgate/planbuilder/operators/merging.go b/go/vt/vtgate/planbuilder/operators/merging.go index ef8da1ef280..6055eb4354d 100644 --- a/go/vt/vtgate/planbuilder/operators/merging.go +++ b/go/vt/vtgate/planbuilder/operators/merging.go @@ -274,6 +274,8 @@ func (s *subQueryMerger) markPredicateInOuterRouting(outer *ShardedRouting, inne func (s *subQueryMerger) mergeTables(outer, inner *ShardedRouting, op1, op2 *Route) (*Route, error) { s.subq.ExtractedSubquery.Merged = true + // we need to make sure that table qualifiers are removed before sending the query to MySQL + sqlparser.RemoveKeyspaceInTables(s.subq.ExtractedSubquery) routing, err := s.markPredicateInOuterRouting(outer, inner) if err != nil { diff --git a/go/vt/vtgate/planbuilder/testdata/filter_cases.json b/go/vt/vtgate/planbuilder/testdata/filter_cases.json index c596875f2df..e4f92c6b226 100644 --- a/go/vt/vtgate/planbuilder/testdata/filter_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/filter_cases.json @@ -846,6 +846,44 @@ ] } }, + { + "comment": "Merging subqueries should remove keyspace from query", + "query": "select u.id from user.user as u where not exists (select 1 from user.user_extra as ue where u.id = ue.user_id)", + "v3-plan": { + "QueryType": "SELECT", + "Original": "select u.id from user.user as u where not exists (select 1 from user.user_extra as ue where u.id = ue.user_id)", + "Instructions": { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select u.id from `user` as u where 1 != 1", + "Query": "select u.id from `user` as u where not exists (select 1 from user_extra as ue where u.id = ue.user_id limit 1)", + "Table": "`user`" + } + }, + "gen4-plan": { + "QueryType": "SELECT", + "Original": "select u.id from user.user as u where not exists (select 1 from user.user_extra as ue where u.id = ue.user_id)", + "Instructions": { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select u.id from `user` as u where 1 != 1", + "Query": "select u.id from `user` as u where not exists (select 1 from user_extra as ue where u.id = ue.user_id limit 1)", + "Table": "`user`" + }, + "TablesUsed": [ + "user.user", + "user.user_extra" + ] + } + }, { "comment": "Composite IN: tuple inside tuple", "query": "select id from user where ((col1, name), col2) in ((('aa', 'bb'), 'cc'), (('dd', 'ee'), 'ff'))",