diff --git a/go/test/endtoend/vtgate/misc_test.go b/go/test/endtoend/vtgate/misc_test.go index 415d67a2840..09a075556ae 100644 --- a/go/test/endtoend/vtgate/misc_test.go +++ b/go/test/endtoend/vtgate/misc_test.go @@ -496,6 +496,20 @@ func TestCreateView(t *testing.T) { assertMatches(t, conn, "select * from v1", `[[INT64(1) INT64(1)] [INT64(2) INT64(2)] [INT64(3) INT64(3)] [INT64(4) INT64(4)] [INT64(5) INT64(5)]]`) } +func TestSubQueryOnTopOfSubQuery(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.NoError(t, err) + defer conn.Close() + defer exec(t, conn, `delete from t1`) + + exec(t, conn, `insert into t1(id1, id2) values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5)`) + exec(t, conn, `insert into t2(id3, id4) values (1, 3), (2, 4)`) + + assertMatches(t, conn, "select id1 from t1 where id1 not in (select id3 from t2) and id2 in (select id4 from t2)", `[[INT64(3)] [INT64(4)]]`) +} + func assertMatches(t *testing.T, conn *mysql.Conn, query, expected string) { t.Helper() qr := exec(t, conn, query) diff --git a/go/vt/vtexplain/testdata/multi-output/selectsharded-output.txt b/go/vt/vtexplain/testdata/multi-output/selectsharded-output.txt index ccad1126651..f17fa13e4cc 100644 --- a/go/vt/vtexplain/testdata/multi-output/selectsharded-output.txt +++ b/go/vt/vtexplain/testdata/multi-output/selectsharded-output.txt @@ -166,3 +166,9 @@ select id, 'abc' as test from user where id = 1 union all select id, 'def' as te 1 ks_sharded/-40: select id, 'abc' as test from user where id = 1 union all select id, 'def' as test from user where id = 1 union all select id, 'ghi' as test from user where id = 1 limit 10001 /* union all */ ---------------------------------------------------------------------- +select id from user where not id in (select col from music where music.user_id = 42) and id in (select col from music where music.user_id = 411) + +1 ks_sharded/40-80: select col from music where music.user_id = 42 limit 10001 +2 ks_sharded/40-80: select col from music where music.user_id = 411 limit 10001 + +---------------------------------------------------------------------- diff --git a/go/vt/vtexplain/testdata/selectsharded-queries.sql b/go/vt/vtexplain/testdata/selectsharded-queries.sql index e2fdfc3171e..a32e1a6cd21 100644 --- a/go/vt/vtexplain/testdata/selectsharded-queries.sql +++ b/go/vt/vtexplain/testdata/selectsharded-queries.sql @@ -32,3 +32,5 @@ select id, case when name = 'alice' then 'ALICE' when name = 'bob' then 'BOB' el select id, case when substr(name, 1, 5) = 'alice' then 'ALICE' when name = 'bob' then 'BOB' else 'OTHER' end as name from user where id = 1 /* select case */; select id, 'abc' as test from user where id = 1 union all select id, 'def' as test from user where id = 1 union all select id, 'ghi' as test from user where id = 1 /* union all */; + +select id from user where not id in (select col from music where music.user_id = 42) and id in (select col from music where music.user_id = 411); diff --git a/go/vt/vtgate/planbuilder/filtering.go b/go/vt/vtgate/planbuilder/filtering.go index 4e22a3cdbc6..6b442a2f169 100644 --- a/go/vt/vtgate/planbuilder/filtering.go +++ b/go/vt/vtgate/planbuilder/filtering.go @@ -64,7 +64,12 @@ func planFilter(pb *primitiveBuilder, input logicalPlan, filter sqlparser.Expr, node.UpdatePlan(pb, filter) return node, nil case *pulloutSubquery: - return planFilter(pb, node.underlying, filter, whereType, origin) + plan, err := planFilter(pb, node.underlying, filter, whereType, origin) + if err != nil { + return nil, err + } + node.underlying = plan + return node, nil case *vindexFunc: return filterVindexFunc(node, filter) case *subquery: diff --git a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt index 038e498bc60..a2ba4862a31 100644 --- a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt @@ -1799,19 +1799,40 @@ "Vindex": "user_index" }, { - "OperatorType": "Route", - "Variant": "SelectIN", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id from user where 1 != 1", - "Query": "select id from user where :__sq_has_values1 = 1 and id in ::__vals and not (:__sq_has_values2 = 1 and id in ::__sq2)", - "Table": "user", - "Values": [ - "::__sq1" - ], - "Vindex": "user_index" + "OperatorType": "Subquery", + "Variant": "PulloutIn", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "SelectEqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select user_extra.col from user_extra where 1 != 1", + "Query": "select user_extra.col from user_extra where user_extra.user_id = 411", + "Table": "user_extra", + "Values": [ + 411 + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "SelectIN", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from user where 1 != 1", + "Query": "select id from user where :__sq_has_values1 = 1 and id in ::__vals and not (:__sq_has_values2 = 1 and id in ::__sq2)", + "Table": "user", + "Values": [ + "::__sq1" + ], + "Vindex": "user_index" + } + ] } ] }