Commit a87f2277 authored by Yuchen Pei's avatar Yuchen Pei

MDEV-22534 Decorrelate IN subquery

Transform

in (select inner_col' from inner_table where inner_col = outer_col)

to

, outer_col in (select inner_col', inner_col from inner_table)

Achieved by implementing Item_in_subselect::exists2in_processor(),
accompanied with comprehensive test coverage. Factored out common code
between the two transformations.

Caveat:

- Cannot recognise bad item mismatch in equalities that causes
  materialization to not materialize down the road
parent 6219630d
......@@ -133,11 +133,13 @@ create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a
explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
affected rows: 8
select * from t1;
......@@ -175,15 +177,18 @@ create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.
explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
analyze delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 100.00 12.50 Using where
1 PRIMARY a ALL NULL NULL NULL NULL 32 24.50 3.12 1.02 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 0.25 100.00 100.00
2 MATERIALIZED a ALL NULL NULL NULL NULL 32 32.00 100.00 100.00
select * from t1;
c1 c2 c3
1 2 2
......@@ -227,8 +232,9 @@ order by c3 desc limit 1;
explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3)
order by c3 desc limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using temporary; Using filesort
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using filesort
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3)
order by c3 desc limit 1;
id select_type table type possible_keys key key_len ref rows Extra
......@@ -731,15 +737,18 @@ create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.
explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where
1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 Using index; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a index t1_c2 t1_c2 10 NULL 32 Using index
explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where
1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 Using index; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a index t1_c2 t1_c2 10 NULL 32 Using index
analyze delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 100.00 12.50 Using where
1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 0.25 18.75 100.00 Using index; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 0.25 100.00 100.00
2 MATERIALIZED a index t1_c2 t1_c2 10 NULL 32 32.00 100.00 100.00 Using index
select * from t1;
c1 c2 c3
1 2 2
......@@ -783,8 +792,9 @@ order by c3 desc limit 1;
explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3)
order by c3 desc limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using temporary; Using filesort
1 PRIMARY a ALL t1_c2 NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using filesort
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL t1_c2 NULL NULL NULL 32
explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3)
order by c3 desc limit 1;
id select_type table type possible_keys key key_len ref rows Extra
......@@ -1245,12 +1255,14 @@ drop table tmp;
create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c1 1 Using where; End temporary
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 32
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c1 1 Using where; End temporary
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 32
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
affected rows: 8
select * from t1;
......@@ -1287,16 +1299,19 @@ drop table tmp;
create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 Using where; End temporary
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 32 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 Using where; End temporary
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 32 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
analyze delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
1 PRIMARY a ALL NULL NULL NULL NULL 32 1.00 100.00 100.00 Using where; Start temporary
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 1.00 3.12 100.00 Using where; End temporary
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 32 1.00 100.00 100.00 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 1.00 100.00 100.00
2 MATERIALIZED a ALL NULL NULL NULL NULL 32 32.00 100.00 100.00
select * from t1;
c1 c2 c3
1 2 2
......@@ -1896,11 +1911,13 @@ create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a
explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
affected rows: 8
select * from t1;
......@@ -1938,15 +1955,18 @@ create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.
explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
analyze delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 25.00 100.00 12.00 Using where
1 PRIMARY a ALL NULL NULL NULL NULL 32 22.67 3.12 1.47 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 0.33 100.00 100.00
2 MATERIALIZED a ALL NULL NULL NULL NULL 32 32.00 100.00 100.00
select * from t1;
c1 c2 c3
1 2 2
......@@ -1990,8 +2010,9 @@ order by c3 desc limit 1;
explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3)
order by c3 desc limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using temporary; Using filesort
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using filesort
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3)
order by c3 desc limit 1;
id select_type table type possible_keys key key_len ref rows Extra
......@@ -2716,8 +2737,8 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 Using index; FirstMatch(t1)
analyze delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 27.00 100.00 14.81 Using where
1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 0.25 18.75 100.00 Using index; FirstMatch(t1)
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 17.00 100.00 11.76 Using where
1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 0.50 18.75 100.00 Using index; FirstMatch(t1)
select * from t1;
c1 c2 c3
1 2 2
......@@ -2761,8 +2782,9 @@ order by c3 desc limit 1;
explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3)
order by c3 desc limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort
1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 Using where; FirstMatch(t1)
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using filesort
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL t1_c2 NULL NULL NULL 32
explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3)
order by c3 desc limit 1;
id select_type table type possible_keys key key_len ref rows Extra
......@@ -3394,7 +3416,7 @@ id select_type table type possible_keys key key_len ref rows Extra
analyze delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2);
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 9.38 9.38 Using where
1 PRIMARY a ALL NULL NULL NULL NULL 32 12.00 3.12 5.56 Using where; FirstMatch(t1)
1 PRIMARY a ALL NULL NULL NULL NULL 32 12.67 3.12 5.26 Using where; FirstMatch(t1)
select * from t1;
c1 c2 c3
1 3 3
......@@ -3435,12 +3457,14 @@ drop table tmp;
create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c1 1 Using where; End temporary
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 32
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c1 1 Using where; End temporary
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 32
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
affected rows: 8
select * from t1;
......@@ -3477,16 +3501,19 @@ drop table tmp;
create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 Using where; End temporary
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 32 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 Using where; End temporary
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 32 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
analyze delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
1 PRIMARY a ALL NULL NULL NULL NULL 32 4.00 100.00 100.00 Using where; Start temporary
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 1.00 3.12 25.00 Using where; End temporary
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 32 16.00 100.00 18.75 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 0.33 100.00 100.00
2 MATERIALIZED a ALL NULL NULL NULL NULL 32 32.00 100.00 100.00
select * from t1;
c1 c2 c3
1 2 2
......@@ -4301,11 +4328,13 @@ create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a
explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
affected rows: 8
select * from t1;
......@@ -4343,15 +4372,18 @@ create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.
explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
analyze delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 25.00 100.00 12.00 Using where
1 PRIMARY a ALL NULL NULL NULL NULL 32 22.67 3.12 1.47 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 0.33 100.00 100.00
2 MATERIALIZED a ALL NULL NULL NULL NULL 32 32.00 100.00 100.00
select * from t1;
c1 c2 c3
1 2 2
......@@ -4395,8 +4427,9 @@ order by c3 desc limit 1;
explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3)
order by c3 desc limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using temporary; Using filesort
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using filesort
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3)
order by c3 desc limit 1;
id select_type table type possible_keys key key_len ref rows Extra
......@@ -5121,8 +5154,8 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 Using index; FirstMatch(t1)
analyze delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 29.00 100.00 13.79 Using where
1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 0.25 18.75 100.00 Using index; FirstMatch(t1)
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 17.00 100.00 11.76 Using where
1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 0.50 18.75 100.00 Using index; FirstMatch(t1)
select * from t1;
c1 c2 c3
1 2 2
......@@ -5166,8 +5199,9 @@ order by c3 desc limit 1;
explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3)
order by c3 desc limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using temporary; Using filesort
1 PRIMARY a ALL t1_c2 NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using filesort
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL t1_c2 NULL NULL NULL 32
explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3)
order by c3 desc limit 1;
id select_type table type possible_keys key key_len ref rows Extra
......@@ -5799,7 +5833,7 @@ id select_type table type possible_keys key key_len ref rows Extra
analyze delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2);
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 9.38 9.38 Using where
1 PRIMARY a ALL NULL NULL NULL NULL 32 13.33 3.12 5.00 Using where; FirstMatch(t1)
1 PRIMARY a ALL NULL NULL NULL NULL 32 13.67 3.12 4.88 Using where; FirstMatch(t1)
select * from t1;
c1 c2 c3
1 3 3
......@@ -5840,12 +5874,14 @@ drop table tmp;
create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c1 1 Using where; End temporary
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 32
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c1 1 Using where; End temporary
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 32
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
affected rows: 8
select * from t1;
......@@ -5882,16 +5918,19 @@ drop table tmp;
create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 Using where; End temporary
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 32 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 Using where; End temporary
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 32 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
analyze delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
1 PRIMARY a ALL NULL NULL NULL NULL 32 4.00 100.00 100.00 Using where; Start temporary
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 1.00 3.12 25.00 Using where; End temporary
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 32 26.00 100.00 11.54 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 0.33 100.00 100.00
2 MATERIALIZED a ALL NULL NULL NULL NULL 32 32.00 100.00 100.00
select * from t1;
c1 c2 c3
1 2 2
......@@ -6459,7 +6498,7 @@ and c1 = 2
and exists (select 'X' from v1 a where a.c1 = v1.c1);
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL # 32.00 3.91 3.12 Using where
3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL # 3.00 25.00 33.33 Using where
3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL # 2.00 25.00 50.00 Using where
2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 # 1.00 100.00 100.00
select * from t1;
c1 c2 c3
......@@ -6791,11 +6830,13 @@ create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a
explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2);
affected rows: 8
select * from t1;
......@@ -6833,11 +6874,13 @@ create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.
explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
affected rows: 1
select * from t1;
......@@ -6883,8 +6926,9 @@ order by c3 desc limit 1;
explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3)
order by c3 desc limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using temporary; Using filesort
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using filesort
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3)
order by c3 desc limit 1;
id select_type table type possible_keys key key_len ref rows Extra
......@@ -7588,11 +7632,13 @@ create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.
explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where
1 PRIMARY a ALL t1_c2 NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL t1_c2 NULL NULL NULL 32
explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where
1 PRIMARY a ALL t1_c2 NULL NULL NULL 32 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL t1_c2 NULL NULL NULL 32
delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1;
affected rows: 1
select * from t1;
......@@ -7638,8 +7684,9 @@ order by c3 desc limit 1;
explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3)
order by c3 desc limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using temporary; Using filesort
1 PRIMARY a ALL t1_c2 NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using filesort
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL t1_c2 NULL NULL NULL 32
explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3)
order by c3 desc limit 1;
id select_type table type possible_keys key key_len ref rows Extra
......
......@@ -906,7 +906,7 @@ EXPLAIN
"buffer_type": "flat",
"buffer_size": "141",
"join_type": "BNL",
"attached_condition": "t1.b = t2.b and t1.a = t2.a"
"attached_condition": "t1.a = t2.a and t1.b = t2.b"
}
}
]
......@@ -921,7 +921,8 @@ explain
select * from t2 where t2.a in ( select a from t1 where t1.b=t2.b);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 10
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 10
explain format=json
select * from t2 where t2.a in ( select a from t1 where t1.b=t2.b);
EXPLAIN
......@@ -929,6 +930,7 @@ EXPLAIN
"query_block": {
"select_id": 1,
"cost": "COST_REPLACED",
"const_condition": "1",
"nested_loop": [
{
"table": {
......@@ -941,25 +943,36 @@ EXPLAIN
}
},
{
"duplicates_removal": [
"table": {
"table_name": "<subquery2>",
"access_type": "eq_ref",
"possible_keys": ["distinct_key"],
"key": "distinct_key",
"key_length": "8",
"used_key_parts": ["a", "b"],
"ref": ["func", "func"],
"rows": 1,
"filtered": 100,
"materialized": {
"unique": 1,
"query_block": {
"select_id": 2,
"nested_loop": [
{
"block-nl-join": {
"table": {
"table_name": "t1",
"access_type": "ALL",
"loops": 10,
"loops": 1,
"rows": 10,
"cost": "COST_REPLACED",
"filtered": 10
},
"buffer_type": "flat",
"buffer_size": "206",
"join_type": "BNL",
"attached_condition": "t1.b = t2.b and t1.a = t2.a"
"filtered": 100
}
}
]
}
}
}
}
]
}
}
......
......@@ -384,15 +384,16 @@ EXPLAIN
SELECT a FROM t1 AS t, t2 as t2_out
WHERE t2_out.c = t.a AND t.b IN (SELECT b FROM t1, t2 WHERE b = t.b);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index b b 7 NULL 10 Using index; Start temporary
1 PRIMARY t ref a,b b 3 test.t1.b 2 Using index
1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t index a,b b 7 NULL 10 Using index
1 PRIMARY t2_out eq_ref PRIMARY PRIMARY 4 test.t.a 1 Using index
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED t1 index b b 7 NULL 10 Using index
2 MATERIALIZED t2 index NULL PRIMARY 4 NULL 11 Using index; Using join buffer (flat, BNL join)
SELECT a FROM t1 AS t, t2 as t2_out
WHERE t2_out.c = t.a AND t.b IN (SELECT b FROM t1, t2 WHERE b = t.b);
a
24
Last_query_cost 0.120558
Last_query_cost 0.083937
DROP TABLE t1,t2;
#
# LP Bug #923236: hash join + extended_keys = on
......
......@@ -3435,11 +3435,11 @@ WHERE t1.c1 NOT IN (SELECT t2.c1 FROM t2, t1 AS a1
WHERE t2.i1 = t1.pk AND t2.i1 BETWEEN 3 AND 5);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 60 100.00 Using where
2 DEPENDENT SUBQUERY t2 ref|filter c1,i1 c1|i1 3|5 func 38 (25%) 25.00 Using where; Full scan on NULL key; Using rowid filter
2 DEPENDENT SUBQUERY a1 ALL NULL NULL NULL NULL 60 100.00 Using join buffer (flat, BNL join)
2 MATERIALIZED t2 ALL c1,i1 NULL NULL NULL 192 25.00 Using where
2 MATERIALIZED a1 ALL NULL NULL NULL NULL 60 100.00 Using join buffer (flat, BNL join)
Warnings:
Note 1276 Field or reference 'test.t1.pk' of SELECT #2 was resolved in SELECT #1
Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`c1` AS `c1` from `test`.`t1` where !<expr_cache><`test`.`t1`.`c1`,`test`.`t1`.`pk`>(<in_optimizer>(`test`.`t1`.`c1`,<exists>(/* select#2 */ select `test`.`t2`.`c1` from `test`.`t2` join `test`.`t1` `a1` where `test`.`t2`.`i1` = `test`.`t1`.`pk` and `test`.`t2`.`i1` between 3 and 5 and trigcond(<cache>(`test`.`t1`.`c1`) = `test`.`t2`.`c1`))))
Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`c1` AS `c1` from `test`.`t1` where !<expr_cache><`test`.`t1`.`c1`,`test`.`t1`.`pk`>(<in_optimizer>((`test`.`t1`.`c1`,`test`.`t1`.`pk`),(`test`.`t1`.`c1`,`test`.`t1`.`pk`) in ( <materialize> (/* select#2 */ select `test`.`t2`.`c1`,`test`.`t2`.`i1` from `test`.`t2` join `test`.`t1` `a1` where `test`.`t2`.`i1` is not null and `test`.`t2`.`i1` between 3 and 5 ), <primary_index_lookup>(`test`.`t1`.`c1` in <temporary table> on distinct_key where `test`.`t1`.`c1` = `<subquery2>`.`c1` and `test`.`t1`.`pk` = `<subquery2>`.`i1`))))
SELECT * FROM t1
WHERE t1.c1 NOT IN (SELECT t2.c1 FROM t2, t1 AS a1
WHERE t2.i1 = t1.pk AND t2.i1 BETWEEN 3 AND 5);
......
......@@ -225,7 +225,7 @@ EXPLAIN
SELECT * FROM t1 WHERE NULL NOT IN (SELECT t2a.i FROM t2a WHERE t2a.pk = t1.pk);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
2 DEPENDENT SUBQUERY t2a unique_subquery PRIMARY PRIMARY 8 const,test.t1.pk 1 Using index; Using where; Full scan on NULL key
2 DEPENDENT SUBQUERY t2a unique_subquery PRIMARY PRIMARY 8 const,func 1 Using index; Using where; Full scan on NULL key
SELECT * FROM t1 WHERE NULL NOT IN (SELECT t2a.i FROM t2a WHERE t2a.pk = t1.pk);
pk i
SELECT * FROM t1 WHERE 1+NULL NOT IN (SELECT t2a.i FROM t2a WHERE t2a.pk = t1.pk);
......@@ -265,7 +265,7 @@ EXPLAIN
SELECT * FROM t1 WHERE NULL NOT IN (SELECT t2c.i FROM t2c WHERE t2c.pk = t1.pk);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
2 DEPENDENT SUBQUERY t2c index_subquery it2c it2c 8 const,test.t1.pk 1 Using index; Using where; Full scan on NULL key
2 DEPENDENT SUBQUERY t2c index_subquery it2c it2c 8 const,func 1 Using index; Using where; Full scan on NULL key
SELECT * FROM t1 WHERE NULL NOT IN (SELECT t2c.i FROM t2c WHERE t2c.pk = t1.pk);
pk i
SELECT * FROM t1 WHERE NULL IN (SELECT t2c.i FROM t2c WHERE t2c.pk = t1.pk) IS UNKNOWN;
......@@ -303,7 +303,7 @@ EXPLAIN
SELECT * FROM t1 WHERE (NULL, 1) NOT IN (SELECT t2a.i, t2a.pk FROM t2a WHERE t2a.pk = t1.pk);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
2 DEPENDENT SUBQUERY t2a unique_subquery PRIMARY PRIMARY 8 const,test.t1.pk 1 Using index; Using where; Full scan on NULL key
2 DEPENDENT SUBQUERY t2a const PRIMARY PRIMARY 8 const,const 1 Using where; Using index; Full scan on NULL key
SELECT * FROM t1 WHERE (NULL, 1) NOT IN (SELECT t2a.i, t2a.pk FROM t2a WHERE t2a.pk = t1.pk);
pk i
0 10
......@@ -335,7 +335,7 @@ EXPLAIN
SELECT * FROM t1 WHERE (NULL, 1) NOT IN (SELECT t2c.i, t2c.pk FROM t2c WHERE t2c.pk = t1.pk);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
2 DEPENDENT SUBQUERY t2c index_subquery it2c it2c 8 const,test.t1.pk 1 Using index; Using where; Full scan on NULL key
2 DEPENDENT SUBQUERY t2c index_subquery it2c it2c 8 const,const 0 Using index; Using where; Full scan on NULL key
SELECT * FROM t1 WHERE (NULL, 1) NOT IN (SELECT t2c.i, t2c.pk FROM t2c WHERE t2c.pk = t1.pk);
pk i
0 10
......
#
# MDEV-22534 Trivial correlation detection/removal for IN subqueries
#
# Basic example
set optimizer_switch='materialization=on,firstmatch=off';
set optimizer_trace=1;
create table ten(a int primary key);
insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t1 (a int, b int, c int);
insert into t1 select a,a,a from ten;
create table t2 select * from t1;
explain select * from t1 where a in (select a from t2 where t1.b=t2.b);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 10
select * from t1 where a in (select a from t2 where t1.b=t2.b);
a b c
0 0 0
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
8 8 8
9 9 9
explain select * from t1 where (a, b) in (select a, b from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 10
select * from t1 where (a, b) in (select a, b from t2);
a b c
0 0 0
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
8 8 8
9 9 9
# Multiple equalities
explain select * from t1 where a in (select a from t2 where t1.b=t2.b and t1.c=t2.c);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 func,func,func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 10
select * from t1 where a in (select a from t2 where t1.b=t2.b and t1.c=t2.c);
a b c
0 0 0
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
8 8 8
9 9 9
explain select * from t1 where a in (select a from t2 where (t1.b, t1.c)=(t2.b, t2.c));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10
1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
select * from t1 where a in (select a from t2 where (t1.b, t1.c)=(t2.b, t2.c));
a b c
0 0 0
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
8 8 8
9 9 9
explain select * from t1 where (a, b) in (select a, b from t2 where t1.c=t2.c);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 func,func,func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 10
select * from t1 where (a, b) in (select a, b from t2 where t1.c=t2.c);
a b c
0 0 0
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
8 8 8
9 9 9
explain select * from t1 where a in (select a from t2 where t1.b=t2.b and t2.c+t2.b < 5);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 10 Using where
select * from t1 where a in (select a from t2 where t1.b=t2.b and t2.c+t2.b < 5);
a b c
0 0 0
1 1 1
2 2 2
explain select * from t1 where a + b in (select a * c from t2 where t1.b=t2.b and t2.c+t2.b < 9);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 func,func 1 Using where
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 10 Using where
select * from t1 where a + b in (select a * c from t2 where t1.b=t2.b and t2.c+t2.b < 9);
a b c
0 0 0
2 2 2
# Still correlated after the transformation / no materialization
explain select * from t1 where a in (select a from t2 where t1.b=t2.b and t1.c < 5);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
select * from t1 where a in (select a from t2 where t1.b=t2.b and t1.c < 5);
a b c
0 0 0
1 1 1
2 2 2
3 3 3
4 4 4
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
["decorrelation", "materialization", "semijoin"]
explain select * from t1 where a in (select a from t2 where t1.a = t2.b and t2.c+t1.a < 9);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10
1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
select * from t1 where a in (select a from t2 where t1.a = t2.b and t2.c+t1.a < 9);
a b c
0 0 0
1 1 1
2 2 2
3 3 3
4 4 4
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
["decorrelation", "materialization", "semijoin"]
# No transformation because of applicable conditions in subquery
explain select * from t1 where a in (select a from t2 where t2.c+t1.a < 9);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10
1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
select * from t1 where a in (select a from t2 where t2.c+t1.a < 9);
a b c
0 0 0
1 1 1
2 2 2
3 3 3
4 4 4
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
["materialization", "semijoin"]
drop table ten, t1, t2;
# group by and having checks in the transformer; also not in
create table t1 (a1 int not null, b1 char(8) not null);
create table t2 (a2 int not null, b2 char(8) not null);
insert into t1 values (0, '2 - 00');
insert into t1 values (1, '2 - 01');
insert into t1 values (2, '2 - 02');
insert into t2 values (1, '2 - 01');
insert into t2 values (1, '2 - 01');
insert into t2 values (2, '2 - 02');
insert into t2 values (2, '2 - 02');
insert into t2 values (3, '2 - 03');
explain select * from t1 where a1 in (select count(*) from t2 where b1 = b2 group by b2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where
select * from t1 where a1 in (select count(*) from t2 where b1 = b2 group by b2);
a1 b1
2 2 - 02
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
NULL
explain select * from t2 where a2 in (select a1 from t1 where b1 = b2 having a1 > 0);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
select * from t2 where a2 in (select a1 from t1 where b1 = b2 having a1 > 0);
a2 b2
1 2 - 01
1 2 - 01
2 2 - 02
2 2 - 02
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
NULL
explain select * from t1 where a1 not in (select a2 from t2 where b1 = b2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where
select * from t1 where a1 not in (select a2 from t2 where b1 = b2);
a1 b1
0 2 - 00
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
["decorrelation", "materialization"]
drop table t1, t2;
# check for aggregate function in the select items in the subquery; test adapted from main.delete_use_source_engines
create table t1 (c1 integer, c2 integer, c3 integer);
insert into t1(c1,c2,c3)
values (1,1,1),(1,2,2),(1,3,3),
(2,1,4),(2,2,5),(2,3,6),
(2,4,7),(2,5,8);
insert into t1 select c1+10,c2,c3+10 from t1;
insert into t1 select c1+20,c2+1,c3+20 from t1;
create view v1 as select * from t1 where c2=2;
create table tmp as select * from t1 where t1.c2 in ( select max(a.c2) from v1 a where a.c1 = t1.c1);
drop table t1, tmp;
drop view v1;
# check for subselect in left_expr; adapted from main.ps
create table t1 (a int, b int, c int);
create table t2 (x int, y int, z int);
create table t3 as select * from t1;
insert into t1 values (1,2,3),(4,5,6),(100,200,300),(400,500,600);
insert into t2 values (1,2,3),(7,8,9),(100,200,300),(400,500,600);
insert into t3 values (1,2,3),(11,12,13),(100,0,0),(400,500,600);
explain select * from t1 where (select a from t3 where t3.c=t1.c) in (select x from t2 where t1.c= t2.z);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4
1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 4 Using where
select * from t1 where (select a from t3 where t3.c=t1.c) in (select x from t2 where t1.c= t2.z);
a b c
1 2 3
400 500 600
explain select * from t1 where ((select a from t3 where t3.c=t1.c),b) in (select x, y from t2 where t1.c= t2.z);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4
1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 4 Using where
select * from t1 where ((select a from t3 where t3.c=t1.c),b) in (select x, y from t2 where t1.c= t2.z);
a b c
1 2 3
400 500 600
explain select * from t1 where (select a,b from t3 where t3.c=t1.c) in (select x,y from t2 where t1.c= t2.z);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4
1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 4 Using where
select * from t1 where (select a,b from t3 where t3.c=t1.c) in (select x,y from t2 where t1.c= t2.z);
a b c
1 2 3
400 500 600
drop table t1, t2, t3;
# check that subselect is not a part of a union
create table t1 (a1 char(8), b1 char(8));
create table t2 (a2 char(8), b2 char(8));
create table t3 (c1 char(8), c2 char(8));
insert into t1 values ('1 - 00', '2 - 00');
insert into t1 values ('1 - 01', '2 - 01');
insert into t1 values ('1 - 02', '2 - 02');
insert into t2 values ('1 - 01', '2 - 01');
insert into t2 values ('1 - 01', '2 - 01');
insert into t2 values ('1 - 02', '2 - 02');
insert into t2 values ('1 - 02', '2 - 02');
insert into t2 values ('1 - 03', '2 - 03');
insert into t3 values ('1 - 01', '2 - 01');
insert into t3 values ('1 - 01', '2 - 01');
insert into t3 values ('1 - 03', '2 - 03');
select * from t1 where a1 in
((select a2 from t2 where b1 = b2) union
(select c2 from t3 where a1 = c1));
a1 b1
1 - 01 2 - 01
1 - 02 2 - 02
drop table t1, t2, t3;
# all / any
create table t1 (a1 int, b1 int);
create table t2 (a2 int, b2 int);
insert into t1 values (0, 0);
insert into t1 values (1, 1);
insert into t1 values (3, 2);
insert into t2 values (1, 0);
insert into t2 values (1, 1);
insert into t2 values (2, 2);
insert into t2 values (3, 3);
insert into t2 values (3, 3);
explain select * from t1 where a1 = any (select a2 from t2 where b1 = b2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5
select * from t1 where a1 = any (select a2 from t2 where b1 = b2);
a1 b1
1 1
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
["decorrelation", "materialization", "semijoin"]
explain select * from t1 where a1 <> all (select a2 from t2 where b1 = b2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where
select * from t1 where a1 <> all (select a2 from t2 where b1 = b2);
a1 b1
0 0
3 2
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
["decorrelation", "materialization"]
# no transformation applied when no synonyms applied to any / all
select * from t1 where a1 >= all (select a2 from t2 where b1 = b2);
a1 b1
1 1
3 2
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
NULL
select * from t1 where a1 <> any (select a2 from t2 where b1 = b2);
a1 b1
0 0
3 2
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
NULL
drop table t1, t2;
# fix NOT IN with null values
create table t1 (a1 int, b1 int);
create table t2 (a2 int, b2 int);
insert into t1 values (0, null), (1, 1);
insert into t2 values (0, 1), (1, null);
# returns (0, null), (1, 1)
select * from t1 where not a1 in (select a2 from t2 where b1 = b2);
a1 b1
0 NULL
1 1
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
["decorrelation", "materialization"]
# returns empty
select * from t1 where not (a1, b1) in (select a2, b2 from t2);
a1 b1
# returns (0, null), (1, 1)
select * from t1 where not (b1 is not null and (a1, b1) in (select a2, b2 from t2 where b2 is not null));
a1 b1
0 NULL
1 1
drop table t1, t2;
# skip transformation when neither toplevel IN nor toplevel NOT IN; testcase adapated from main.subslect4
CREATE TABLE t1 ( a INT, b INT );
INSERT INTO t1 VALUES ( 1, NULL ), ( 2, NULL );
CREATE TABLE t2 ( c INT, d INT );
INSERT INTO t2 VALUES ( NULL, 3 ), ( NULL, 4 );
SELECT * FROM t1 WHERE a NOT IN ( SELECT c FROM t2 where b = d ) IS NULL;
a b
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
NULL
SELECT * FROM t1 WHERE a IN ( SELECT c FROM t2 where b = d ) IS NULL;
a b
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
NULL
drop table t1, t2;
# 2nd ps execution / why we need to backup and restore the query arena; test also in main.subselect_sj2_mat
CREATE TABLE t1 ( c varchar(1));
INSERT INTO t1 VALUES ('r');
CREATE TABLE t2 ( a integer, b varchar(1), c varchar(1));
INSERT INTO t2 VALUES (1,'r','r');
CREATE OR REPLACE VIEW v1 AS SELECT * FROM t1;
PREPARE st2 FROM 'SELECT * FROM t2 WHERE a IN (SELECT a FROM v1 WHERE v1.c = t2.c)';
EXECUTE st2;
a b c
1 r r
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
["decorrelation", "materialization", "semijoin"]
EXECUTE st2;
a b c
1 r r
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
NULL
drop table t1, t2;
drop view v1;
# 2nd ps execution / why we skip the transformation if we are in a ps execution and eligible equalities intersects with the free list; test also in main.subselect4
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (4),(6);
CREATE TABLE t2 (b INT);
INSERT INTO t2 VALUES (1),(8);
PREPARE st5 FROM "
SELECT * FROM t2
HAVING 0 IN (
SELECT a FROM t1
WHERE a IN (
SELECT a FROM t1
WHERE b = a
)
)
";
EXECUTE st5;
b
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
["materialization", "semijoin"]
EXECUTE st5;
b
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
NULL
drop table t1, t2;
# test case where the in subselect is wrapped in an Item_in_optimizer / the necessity to update the Item_in_optimizer; test also in main.subselect4
CREATE TABLE t1 (pk INT NOT NULL, i INT NOT NULL);
INSERT INTO t1 VALUES (0,10), (1,20), (2,30), (3,40);
CREATE TABLE t2a (pk INT NOT NULL, i INT NOT NULL, PRIMARY KEY(i,pk));
INSERT INTO t2a VALUES (0,0), (1,1), (2,2), (3,3);
EXPLAIN SELECT * FROM t1 WHERE (NULL, 1) NOT IN (SELECT t2a.i, t2a.pk FROM t2a WHERE t2a.pk = t1.pk);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
2 DEPENDENT SUBQUERY t2a const PRIMARY PRIMARY 8 const,const 1 Using where; Using index; Full scan on NULL key
SELECT * FROM t1 WHERE (NULL, 1) NOT IN (SELECT t2a.i, t2a.pk FROM t2a WHERE t2a.pk = t1.pk);
pk i
0 10
2 30
3 40
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') AS JS
from information_schema.OPTIMIZER_TRACE;
JS
["decorrelation", "materialization"]
drop table t1, t2a;
# misc cases
CREATE TABLE t2 (pk INT PRIMARY KEY, b INT);
INSERT INTO t2 VALUES (1,1),(2,7);
SELECT * FROM t2 AS alias1, t2 AS alias2
WHERE alias1.pk in ( SELECT 1 ) AND (alias2.pk = alias1.b )
ORDER BY alias1.b;
pk b pk b
1 1 1 1
drop table t2;
create table t1 (a1 char(8), b1 char(8));
create table t2 (a2 char(8), b2 char(8));
insert into t1 values ('1 - 00', '2 - 00');
insert into t1 values ('1 - 01', '2 - 01');
insert into t1 values ('1 - 02', '2 - 02');
insert into t2 values ('1 - 01', '2 - 01');
insert into t2 values ('1 - 01', '2 - 01');
insert into t2 values ('1 - 02', '2 - 02');
insert into t2 values ('1 - 03', '2 - 02');
insert into t2 values ('1 - 03', '2 - 03');
select * from t1 where a1 in (select a2 from t2 where b1 = b2 order by b2 desc limit 1, 2);
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
drop table t1, t2;
# outer_exp has subquery
create table t1 (a1 int, b1 int);
create table t2 (a2 int, b2 int);
insert into t1 values (0, 0);
insert into t1 values (1, 1);
insert into t1 values (2, 2);
insert into t2 values (1, 0);
insert into t2 values (1, 1);
insert into t2 values (2, 2);
insert into t2 values (3, 2);
insert into t2 values (3, 3);
select * from t1 where a1 in
(select a2 from t2 where
a1 + (select b2 from t2) = b2);
ERROR 21000: Subquery returns more than 1 row
explain select * from t1 where a1 in
(select a2 from t2 where
(select a1 + b2 from t2 order by b2 limit 1) = a2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 Using where
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using filesort
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
["decorrelation", "materialization", "semijoin"]
select * from t1 where a1 in
(select a2 from t2 where
(select a1 + b2 from t2 order by b2 limit 1) = a2);
a1 b1
1 1
2 2
drop table t1, t2;
# outer_exp has fulltext function
create table t1 (a1 int, b1 int);
create table t2 (a2 int, b2 text, fulltext(b2));
insert into t1 values (0, 0);
insert into t1 values (1, 1);
insert into t1 values (2, 0);
insert into t2 values (1, 'MariaDB overview');
insert into t2 values (1, 'https://mariadb.com/');
insert into t2 values (2, 'Foreign keys');
insert into t2 values (3, 'Indexes');
insert into t2 values (3, 'Triggers');
explain select * from t1 where a1 in
(select a2 from t2 where
(select b1 + count(*) from t2 where
match(b2) against('mariadb')) = a2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 Using where
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5
3 DEPENDENT SUBQUERY t2 fulltext b2 b2 0 1 Using where
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
["decorrelation", "materialization", "semijoin"]
select * from t1 where a1 in
(select a2 from t2 where
(select b1 + count(*) from t2 where
match(b2) against('mariadb')) = a2);
a1 b1
2 0
drop table t1, t2;
# type mismatch leading to no materialization after transformation
create table t1 (a1 int, b1 int);
create table t2 (a2 int);
insert into t1 values (0, 0);
insert into t1 values (1, 1);
insert into t1 values (2, 2);
insert into t2 values (1);
insert into t2 values (1);
insert into t2 values (2);
insert into t2 values (3);
insert into t2 values (3);
alter table t2 add b2 varchar(32);
explain select * from t1 where a1 in (select 1 from t2 where b1 = b2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join)
select * from t1 where a1 in (select 1 from t2 where b1 = b2);
a1 b1
select
json_detailed(json_extract(trace, '$**.join_optimization.steps[*].transformation')) as JS
from information_schema.OPTIMIZER_TRACE;
JS
[
{
"select_id": 2,
"from": "IN (SELECT)",
"to": "decorrelation",
"is_correlated": false
},
{
"select_id": 2,
"from": "IN (SELECT)",
"to": "materialization",
"possible": false,
"cause": "types mismatch"
},
{
"select_id": 2,
"from": "IN (SELECT)",
"to": "semijoin",
"converted_to_semi_join": true
}
]
drop table t1, t2;
# non-semijoin materialization
create table ten(a int);
insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table one_h(a int);
insert into one_h select A.a + B.a* 10 from ten A, ten B;
create table ten_k(a int primary key);
insert into ten_k select A.a + B.a* 100 from one_h A, one_h B;
create table t1 (a int, b int, c int );
insert into t1 select a, a, a from one_h;
create table t2 (a int, b int, c int );
insert into t2 select a,a,a from ten_k;
explain select * from t1 where 1 in (select 1 from t2 where t2.a=t1.a and t2.b=t1.b) or t1.c<333;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 100 Using where
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 10000
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
JS
["decorrelation", "materialization"]
drop table ten, one_h, ten_k, t1, t2;
#
#
#
create table t1 ( a int, b int, c int);
insert into t1 select seq, seq, seq from seq_1_to_10;
create table t2 ( x int, y int, z int);
insert into t2 select seq, seq, seq from seq_1_to_10;
insert into t1 values
( NULL , 12 , 12 ),
( 12 , NULL , 12 ),
( NULL , 13 , 13 ),
( 13 , NULL , 13 ),
( 21 , 21 , 21 ),
( 22 , 22 , 22 ),
( 12 , 12 , 12 ),
( 22 , NULL , 22 ),
( NULL , 21 , 21 ),
( 23 , NULL , 23 ),
( NULL , 23 , 23 );
create table one(w int);
insert into one values (1);
alter table t2 add key(x);
alter table t2 add key(y);
set @tmp=@@optimizer_switch, optimizer_switch='materialization=off';
# This will not show full-scan-on-null-key:
explain format=json
select * from t1
where t1.a not in (select t2.x from one,t2 ignore index(x) where t1.b=t2.y and t2.z=33);
EXPLAIN
{
"query_block": {
"select_id": 1,
"cost": "COST_REPLACED",
"nested_loop": [
{
"table": {
"table_name": "t1",
"access_type": "ALL",
"loops": 1,
"rows": 21,
"cost": "COST_REPLACED",
"filtered": 100,
"attached_condition": "!(t1.b is not null and <in_optimizer>((t1.a,t1.b),<exists>(subquery#2)))"
}
}
],
"subqueries": [
{
"query_block": {
"select_id": 2,
"cost": "COST_REPLACED",
"having_condition": "trigcond(t2.x is null)",
"nested_loop": [
{
"table": {
"table_name": "one",
"access_type": "system",
"rows": 1,
"filtered": 100
}
},
{
"table": {
"table_name": "t2",
"access_type": "ref",
"possible_keys": ["y"],
"key": "y",
"key_length": "5",
"used_key_parts": ["y"],
"ref": ["func"],
"loops": 1,
"rows": 1,
"cost": "COST_REPLACED",
"filtered": 100,
"index_condition": "t2.y is not null",
"attached_condition": "t2.z = 33 and trigcond(trigcond(<cache>(t1.a) = t2.x or t2.x is null))"
}
}
]
}
}
]
}
}
# This will show full-scan-on-null-key:
explain format=json
select * from t1
where t1.a not in (select t2.x from one,t2 ignore index(y) where t1.b=t2.y and t2.z=33);
EXPLAIN
{
"query_block": {
"select_id": 1,
"cost": "COST_REPLACED",
"nested_loop": [
{
"table": {
"table_name": "t1",
"access_type": "ALL",
"loops": 1,
"rows": 21,
"cost": "COST_REPLACED",
"filtered": 100,
"attached_condition": "!(t1.b is not null and <in_optimizer>((t1.a,t1.b),<exists>(subquery#2)))"
}
}
],
"subqueries": [
{
"query_block": {
"select_id": 2,
"cost": "COST_REPLACED",
"having_condition": "trigcond(t2.x is null)",
"nested_loop": [
{
"table": {
"table_name": "one",
"access_type": "system",
"rows": 1,
"filtered": 100
}
},
{
"full-scan-on-null_key": {
"table": {
"table_name": "t2",
"access_type": "ref_or_null",
"possible_keys": ["x"],
"key": "x",
"key_length": "5",
"used_key_parts": ["x"],
"ref": ["func"],
"loops": 1,
"rows": 4,
"cost": "COST_REPLACED",
"filtered": 100,
"attached_condition": "t2.z = 33 and t2.y is not null and trigcond(trigcond(<cache>(t1.a) = t2.x or t2.x is null)) and <cache>(t1.b) = t2.y"
}
}
}
]
}
}
]
}
}
drop table one,t1,t2;
--echo #
--echo # MDEV-22534 Trivial correlation detection/removal for IN subqueries
--echo #
# The test uses optimizer trace:
--source include/not_embedded.inc
--source include/have_sequence.inc
--echo # Basic example
set optimizer_switch='materialization=on,firstmatch=off';
set optimizer_trace=1;
create table ten(a int primary key);
insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t1 (a int, b int, c int);
insert into t1 select a,a,a from ten;
create table t2 select * from t1;
let $query=
select * from t1 where a in (select a from t2 where t1.b=t2.b);
eval explain $query;
eval $query;
let $query=
select * from t1 where (a, b) in (select a, b from t2);
eval explain $query;
eval $query;
--echo # Multiple equalities
let $query=
select * from t1 where a in (select a from t2 where t1.b=t2.b and t1.c=t2.c);
eval explain $query;
eval $query;
# Row item equality; requires extending `check_equality_for_exist2in()` to allow expr=expr to decorrelate (MDEV-31229)
let $query=
select * from t1 where a in (select a from t2 where (t1.b, t1.c)=(t2.b, t2.c));
eval explain $query;
eval $query;
# Row in left_expr
let $query=
select * from t1 where (a, b) in (select a, b from t2 where t1.c=t2.c);
eval explain $query;
eval $query;
let $query=
select * from t1 where a in (select a from t2 where t1.b=t2.b and t2.c+t2.b < 5);
eval explain $query;
eval $query;
let $query=
select * from t1 where a + b in (select a * c from t2 where t1.b=t2.b and t2.c+t2.b < 9);
eval explain $query;
eval $query;
--echo # Still correlated after the transformation / no materialization
let $query=
select * from t1 where a in (select a from t2 where t1.b=t2.b and t1.c < 5);
eval explain $query;
eval $query;
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
let $query=
select * from t1 where a in (select a from t2 where t1.a = t2.b and t2.c+t1.a < 9);
eval explain $query;
eval $query;
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
--echo # No transformation because of applicable conditions in subquery
let $query=
select * from t1 where a in (select a from t2 where t2.c+t1.a < 9);
eval explain $query;
eval $query;
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
drop table ten, t1, t2;
--echo # group by and having checks in the transformer; also not in
create table t1 (a1 int not null, b1 char(8) not null);
create table t2 (a2 int not null, b2 char(8) not null);
insert into t1 values (0, '2 - 00');
insert into t1 values (1, '2 - 01');
insert into t1 values (2, '2 - 02');
insert into t2 values (1, '2 - 01');
insert into t2 values (1, '2 - 01');
insert into t2 values (2, '2 - 02');
insert into t2 values (2, '2 - 02');
insert into t2 values (3, '2 - 03');
# skip on group by
let $query=
select * from t1 where a1 in (select count(*) from t2 where b1 = b2 group by b2);
eval explain $query;
eval $query;
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
# skip having
let $query=
select * from t2 where a2 in (select a1 from t1 where b1 = b2 having a1 > 0);
eval explain $query;
eval $query;
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
# not in
let $query=
select * from t1 where a1 not in (select a2 from t2 where b1 = b2);
eval explain $query;
eval $query;
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
drop table t1, t2;
--echo # check for aggregate function in the select items in the subquery; test adapted from main.delete_use_source_engines
create table t1 (c1 integer, c2 integer, c3 integer);
insert into t1(c1,c2,c3)
values (1,1,1),(1,2,2),(1,3,3),
(2,1,4),(2,2,5),(2,3,6),
(2,4,7),(2,5,8);
insert into t1 select c1+10,c2,c3+10 from t1;
insert into t1 select c1+20,c2+1,c3+20 from t1;
create view v1 as select * from t1 where c2=2;
let $c=
t1.c2 in ( select max(a.c2) from v1 a where a.c1 = t1.c1);
eval create table tmp as select * from t1 where $c;
drop table t1, tmp;
drop view v1;
--echo # check for subselect in left_expr; adapted from main.ps
create table t1 (a int, b int, c int);
create table t2 (x int, y int, z int);
create table t3 as select * from t1;
insert into t1 values (1,2,3),(4,5,6),(100,200,300),(400,500,600);
insert into t2 values (1,2,3),(7,8,9),(100,200,300),(400,500,600);
insert into t3 values (1,2,3),(11,12,13),(100,0,0),(400,500,600);
# scalar subselect - ok
let $query=
select * from t1 where (select a from t3 where t3.c=t1.c) in (select x from t2 where t1.c= t2.z);
eval explain $query;
eval $query;
# a row containing a subselect - ok
let $query=
select * from t1 where ((select a from t3 where t3.c=t1.c),b) in (select x, y from t2 where t1.c= t2.z);
eval explain $query;
eval $query;
# a single non-scalar subselect - skip transformation
let $query=
select * from t1 where (select a,b from t3 where t3.c=t1.c) in (select x,y from t2 where t1.c= t2.z);
eval explain $query;
eval $query;
drop table t1, t2, t3;
--echo # check that subselect is not a part of a union
# union
create table t1 (a1 char(8), b1 char(8));
create table t2 (a2 char(8), b2 char(8));
create table t3 (c1 char(8), c2 char(8));
insert into t1 values ('1 - 00', '2 - 00');
insert into t1 values ('1 - 01', '2 - 01');
insert into t1 values ('1 - 02', '2 - 02');
insert into t2 values ('1 - 01', '2 - 01');
insert into t2 values ('1 - 01', '2 - 01');
insert into t2 values ('1 - 02', '2 - 02');
insert into t2 values ('1 - 02', '2 - 02');
insert into t2 values ('1 - 03', '2 - 03');
insert into t3 values ('1 - 01', '2 - 01');
insert into t3 values ('1 - 01', '2 - 01');
insert into t3 values ('1 - 03', '2 - 03');
select * from t1 where a1 in
((select a2 from t2 where b1 = b2) union
(select c2 from t3 where a1 = c1));
drop table t1, t2, t3;
--echo # all / any
create table t1 (a1 int, b1 int);
create table t2 (a2 int, b2 int);
insert into t1 values (0, 0);
insert into t1 values (1, 1);
insert into t1 values (3, 2);
insert into t2 values (1, 0);
insert into t2 values (1, 1);
insert into t2 values (2, 2);
insert into t2 values (3, 3);
insert into t2 values (3, 3);
# transformation applied because `= any` is synonym to `in`
let $query=
select * from t1 where a1 = any (select a2 from t2 where b1 = b2);
eval explain $query;
eval $query;
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
# transformation applied because `<> all` is synonym to `not in`
let $query=
select * from t1 where a1 <> all (select a2 from t2 where b1 = b2);
eval explain $query;
eval $query;
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
--echo # no transformation applied when no synonyms applied to any / all
select * from t1 where a1 >= all (select a2 from t2 where b1 = b2);
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
select * from t1 where a1 <> any (select a2 from t2 where b1 = b2);
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
drop table t1, t2;
--echo # fix NOT IN with null values
create table t1 (a1 int, b1 int);
create table t2 (a2 int, b2 int);
insert into t1 values (0, null), (1, 1);
insert into t2 values (0, 1), (1, null);
--echo # returns (0, null), (1, 1)
select * from t1 where not a1 in (select a2 from t2 where b1 = b2);
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
--echo # returns empty
select * from t1 where not (a1, b1) in (select a2, b2 from t2);
--echo # returns (0, null), (1, 1)
select * from t1 where not (b1 is not null and (a1, b1) in (select a2, b2 from t2 where b2 is not null));
drop table t1, t2;
--echo # skip transformation when neither toplevel IN nor toplevel NOT IN; testcase adapated from main.subslect4
CREATE TABLE t1 ( a INT, b INT );
INSERT INTO t1 VALUES ( 1, NULL ), ( 2, NULL );
CREATE TABLE t2 ( c INT, d INT );
INSERT INTO t2 VALUES ( NULL, 3 ), ( NULL, 4 );
# not top level, upper_not is not top level
SELECT * FROM t1 WHERE a NOT IN ( SELECT c FROM t2 where b = d ) IS NULL;
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
# not top level, upper_not is null
SELECT * FROM t1 WHERE a IN ( SELECT c FROM t2 where b = d ) IS NULL;
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
drop table t1, t2;
--echo # 2nd ps execution / why we need to backup and restore the query arena; test also in main.subselect_sj2_mat
CREATE TABLE t1 ( c varchar(1));
INSERT INTO t1 VALUES ('r');
CREATE TABLE t2 ( a integer, b varchar(1), c varchar(1));
INSERT INTO t2 VALUES (1,'r','r');
CREATE OR REPLACE VIEW v1 AS SELECT * FROM t1;
PREPARE st2 FROM 'SELECT * FROM t2 WHERE a IN (SELECT a FROM v1 WHERE v1.c = t2.c)';
EXECUTE st2;
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
EXECUTE st2;
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
drop table t1, t2;
drop view v1;
--echo # 2nd ps execution / why we skip the transformation if we are in a ps execution and eligible equalities intersects with the free list; test also in main.subselect4
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (4),(6);
CREATE TABLE t2 (b INT);
INSERT INTO t2 VALUES (1),(8);
PREPARE st5 FROM "
SELECT * FROM t2
HAVING 0 IN (
SELECT a FROM t1
WHERE a IN (
SELECT a FROM t1
WHERE b = a
)
)
";
EXECUTE st5;
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
EXECUTE st5;
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
drop table t1, t2;
--echo # test case where the in subselect is wrapped in an Item_in_optimizer / the necessity to update the Item_in_optimizer; test also in main.subselect4
CREATE TABLE t1 (pk INT NOT NULL, i INT NOT NULL);
INSERT INTO t1 VALUES (0,10), (1,20), (2,30), (3,40);
CREATE TABLE t2a (pk INT NOT NULL, i INT NOT NULL, PRIMARY KEY(i,pk));
INSERT INTO t2a VALUES (0,0), (1,1), (2,2), (3,3);
let $query=
SELECT * FROM t1 WHERE (NULL, 1) NOT IN (SELECT t2a.i, t2a.pk FROM t2a WHERE t2a.pk = t1.pk);
eval EXPLAIN $query;
eval $query;
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') AS JS
from information_schema.OPTIMIZER_TRACE;
drop table t1, t2a;
--echo # misc cases
# would-be empty leaf_tables if not for prior optimization, adapted from similar case for exists2in in main.subselect4
CREATE TABLE t2 (pk INT PRIMARY KEY, b INT);
INSERT INTO t2 VALUES (1,1),(2,7);
SELECT * FROM t2 AS alias1, t2 AS alias2
WHERE alias1.pk in ( SELECT 1 ) AND (alias2.pk = alias1.b )
ORDER BY alias1.b;
drop table t2;
# limit is not supported in IN subquery, so we don't have to worry about it
create table t1 (a1 char(8), b1 char(8));
create table t2 (a2 char(8), b2 char(8));
insert into t1 values ('1 - 00', '2 - 00');
insert into t1 values ('1 - 01', '2 - 01');
insert into t1 values ('1 - 02', '2 - 02');
insert into t2 values ('1 - 01', '2 - 01');
insert into t2 values ('1 - 01', '2 - 01');
insert into t2 values ('1 - 02', '2 - 02');
insert into t2 values ('1 - 03', '2 - 02');
insert into t2 values ('1 - 03', '2 - 03');
--error ER_NOT_SUPPORTED_YET
select * from t1 where a1 in (select a2 from t2 where b1 = b2 order by b2 desc limit 1, 2);
drop table t1, t2;
--echo # outer_exp has subquery
create table t1 (a1 int, b1 int);
create table t2 (a2 int, b2 int);
insert into t1 values (0, 0);
insert into t1 values (1, 1);
insert into t1 values (2, 2);
insert into t2 values (1, 0);
insert into t2 values (1, 1);
insert into t2 values (2, 2);
insert into t2 values (3, 2);
insert into t2 values (3, 3);
--error ER_SUBQUERY_NO_1_ROW
select * from t1 where a1 in
(select a2 from t2 where
a1 + (select b2 from t2) = b2);
let $query=
select * from t1 where a1 in
(select a2 from t2 where
(select a1 + b2 from t2 order by b2 limit 1) = a2);
eval explain $query;
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
eval $query;
drop table t1, t2;
--echo # outer_exp has fulltext function
create table t1 (a1 int, b1 int);
create table t2 (a2 int, b2 text, fulltext(b2));
insert into t1 values (0, 0);
insert into t1 values (1, 1);
insert into t1 values (2, 0);
insert into t2 values (1, 'MariaDB overview');
insert into t2 values (1, 'https://mariadb.com/');
insert into t2 values (2, 'Foreign keys');
insert into t2 values (3, 'Indexes');
insert into t2 values (3, 'Triggers');
let $query=
select * from t1 where a1 in
(select a2 from t2 where
(select b1 + count(*) from t2 where
match(b2) against('mariadb')) = a2);
# with ps-protocol the count(0) which is an Item_aggregate_ref is in
# the runtime arena causing skipping the decorrelation
--disable_ps_protocol
eval explain $query;
--enable_ps_protocol
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
eval $query;
drop table t1, t2;
--echo # type mismatch leading to no materialization after transformation
create table t1 (a1 int, b1 int);
create table t2 (a2 int);
insert into t1 values (0, 0);
insert into t1 values (1, 1);
insert into t1 values (2, 2);
insert into t2 values (1);
insert into t2 values (1);
insert into t2 values (2);
insert into t2 values (3);
insert into t2 values (3);
alter table t2 add b2 varchar(32);
let $query=
select * from t1 where a1 in (select 1 from t2 where b1 = b2);
eval explain $query;
eval $query;
select
json_detailed(json_extract(trace, '$**.join_optimization.steps[*].transformation')) as JS
from information_schema.OPTIMIZER_TRACE;
drop table t1, t2;
--echo # non-semijoin materialization
create table ten(a int);
insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table one_h(a int);
insert into one_h select A.a + B.a* 10 from ten A, ten B;
create table ten_k(a int primary key);
insert into ten_k select A.a + B.a* 100 from one_h A, one_h B;
create table t1 (a int, b int, c int );
insert into t1 select a, a, a from one_h;
create table t2 (a int, b int, c int );
insert into t2 select a,a,a from ten_k;
explain select * from t1 where 1 in (select 1 from t2 where t2.a=t1.a and t2.b=t1.b) or t1.c<333;
select
json_extract(trace, '$**.join_optimization.steps[*].transformation.to') as JS
from information_schema.OPTIMIZER_TRACE;
drop table ten, one_h, ten_k, t1, t2;
--echo #
--echo #
--echo #
create table t1 ( a int, b int, c int);
insert into t1 select seq, seq, seq from seq_1_to_10;
create table t2 ( x int, y int, z int);
insert into t2 select seq, seq, seq from seq_1_to_10;
insert into t1 values
( NULL , 12 , 12 ),
( 12 , NULL , 12 ),
( NULL , 13 , 13 ),
( 13 , NULL , 13 ),
( 21 , 21 , 21 ),
( 22 , 22 , 22 ),
( 12 , 12 , 12 ),
( 22 , NULL , 22 ),
( NULL , 21 , 21 ),
( 23 , NULL , 23 ),
( NULL , 23 , 23 );
create table one(w int);
insert into one values (1);
alter table t2 add key(x);
alter table t2 add key(y);
set @tmp=@@optimizer_switch, optimizer_switch='materialization=off';
--echo # This will not show full-scan-on-null-key:
--source include/explain-no-costs.inc
explain format=json
select * from t1
where t1.a not in (select t2.x from one,t2 ignore index(x) where t1.b=t2.y and t2.z=33);
--echo # This will show full-scan-on-null-key:
--source include/explain-no-costs.inc
explain format=json
select * from t1
where t1.a not in (select t2.x from one,t2 ignore index(y) where t1.b=t2.y and t2.z=33);
drop table one,t1,t2;
......@@ -454,7 +454,7 @@ WHERE t2.c = v1.c AND t2.c = v1.b AND v1.b = t3.c);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 1
2 DEPENDENT SUBQUERY <derived3> ref key1 key1 8 const,const 0 Using where
2 DEPENDENT SUBQUERY <derived3> ref key0 key0 8 const,const 0 Using where
3 DERIVED t1 ALL NULL NULL NULL NULL 3 Using where
SELECT * FROM t3
WHERE t3.b IN (SELECT v1.b FROM v1, t2
......@@ -476,7 +476,7 @@ EXPLAIN
SELECT * FROM t1 WHERE t1.b IN (SELECT v2.a FROM v2 WHERE v2.b = t1.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY <derived3> ref key0 key0 5 test.t1.a 1 Using where
2 DEPENDENT SUBQUERY <derived3> index_subquery key0 key0 10 func,func 1 Using where
3 DERIVED t2 ALL NULL NULL NULL NULL 2
SELECT * FROM t1 WHERE t1.b IN (SELECT v2.a FROM v2 WHERE v2.b = t1.a);
a b
......
......@@ -387,10 +387,10 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
6 MATERIALIZED t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
4 MATERIALIZED t3b ALL NULL NULL NULL NULL 4 100.00 Using where
3 DEPENDENT SUBQUERY t3a ALL NULL NULL NULL NULL 4 100.00 Using where
3 MATERIALIZED t3a ALL NULL NULL NULL NULL 4 100.00
Warnings:
Note 1276 Field or reference 'test.t1.a1' of SELECT #3 was resolved in SELECT #1
Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where (<expr_cache><`test`.`t2`.`b2`,`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t2`.`b2`,<exists>(/* select#3 */ select `test`.`t3a`.`c2` from `test`.`t3` `t3a` where `test`.`t3a`.`c1` = `test`.`t1`.`a1` and <cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (/* select#4 */ select `test`.`t3b`.`c2` from `test`.`t3` `t3b` where `test`.`t3b`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`))))) and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#5 */ select `test`.`t3c`.`c1`,`test`.`t3c`.`c2` from `test`.`t3` `t3c` where <expr_cache><`test`.`t3c`.`c1`,`test`.`t3c`.`c2`>(<in_optimizer>((`test`.`t3c`.`c1`,`test`.`t3c`.`c2`),(`test`.`t3c`.`c1`,`test`.`t3c`.`c2`) in ( <materialize> (/* select#6 */ select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3c`.`c1` in <temporary table> on distinct_key where `test`.`t3c`.`c1` = `<subquery6>`.`b1` and `test`.`t3c`.`c2` = `<subquery6>`.`b2`)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery5>`.`c1` and `test`.`t1`.`a2` = `<subquery5>`.`c2`))))
Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where (<expr_cache><`test`.`t2`.`b2`,`test`.`t1`.`a1`>(<in_optimizer>((`test`.`t2`.`b2`,`test`.`t1`.`a1`),(`test`.`t2`.`b2`,`test`.`t1`.`a1`) in ( <materialize> (/* select#3 */ select `test`.`t3a`.`c2`,`test`.`t3a`.`c1` from `test`.`t3` `t3a` where 1 ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery3>`.`c2` and `test`.`t1`.`a1` = `<subquery3>`.`c1`)))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (/* select#4 */ select `test`.`t3b`.`c2` from `test`.`t3` `t3b` where `test`.`t3b`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`))))) and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#5 */ select `test`.`t3c`.`c1`,`test`.`t3c`.`c2` from `test`.`t3` `t3c` where <expr_cache><`test`.`t3c`.`c1`,`test`.`t3c`.`c2`>(<in_optimizer>((`test`.`t3c`.`c1`,`test`.`t3c`.`c2`),(`test`.`t3c`.`c1`,`test`.`t3c`.`c2`) in ( <materialize> (/* select#6 */ select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3c`.`c1` in <temporary table> on distinct_key where `test`.`t3c`.`c1` = `<subquery6>`.`b1` and `test`.`t3c`.`c2` = `<subquery6>`.`b2`)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery5>`.`c1` and `test`.`t1`.`a2` = `<subquery5>`.`c2`))))
select * from t1
where (a1, a2) in (select b1, b2 from t2
where b2 in (select c2 from t3 t3a where c1 = a1) or
......@@ -520,11 +520,11 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
6 DEPENDENT SUBQUERY t2i index_subquery it2i1,it2i2,it2i3 it2i3 18 func,func 1 100.00 Using index; Using where
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
4 MATERIALIZED t3b ALL NULL NULL NULL NULL 4 100.00 Using where
3 DEPENDENT SUBQUERY t3a ALL NULL NULL NULL NULL 4 100.00 Using where
3 MATERIALIZED t3a ALL NULL NULL NULL NULL 4 100.00
Warnings:
Note 1276 Field or reference 'test.t1.a1' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'test.t1.a2' of SELECT #6 was resolved in SELECT #1
Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where (<expr_cache><`test`.`t2`.`b2`,`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t2`.`b2`,<exists>(/* select#3 */ select `test`.`t3a`.`c2` from `test`.`t3` `t3a` where `test`.`t3a`.`c1` = `test`.`t1`.`a1` and <cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (/* select#4 */ select `test`.`t3b`.`c2` from `test`.`t3` `t3b` where `test`.`t3b`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`))))) and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#5 */ select `test`.`t3c`.`c1`,`test`.`t3c`.`c2` from `test`.`t3` `t3c` where <expr_cache><`test`.`t3c`.`c1`,`test`.`t3c`.`c2`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t3c`.`c1`,`test`.`t3c`.`c2`),<exists>(<index_lookup>(<cache>(`test`.`t3c`.`c1`) in t2i on it2i3 where (`test`.`t2i`.`b2` > '0' or `test`.`t2i`.`b2` = `test`.`t1`.`a2`) and <cache>(`test`.`t3c`.`c1`) = `test`.`t2i`.`b1` and <cache>(`test`.`t3c`.`c2`) = `test`.`t2i`.`b2`)))) and <cache>(`test`.`t1`.`a1`) = `test`.`t3c`.`c1` and <cache>(`test`.`t1`.`a2`) = `test`.`t3c`.`c2`)))
Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where (<expr_cache><`test`.`t2`.`b2`,`test`.`t1`.`a1`>(<in_optimizer>((`test`.`t2`.`b2`,`test`.`t1`.`a1`),(`test`.`t2`.`b2`,`test`.`t1`.`a1`) in ( <materialize> (/* select#3 */ select `test`.`t3a`.`c2`,`test`.`t3a`.`c1` from `test`.`t3` `t3a` where 1 ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery3>`.`c2` and `test`.`t1`.`a1` = `<subquery3>`.`c1`)))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (/* select#4 */ select `test`.`t3b`.`c2` from `test`.`t3` `t3b` where `test`.`t3b`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`))))) and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#5 */ select `test`.`t3c`.`c1`,`test`.`t3c`.`c2` from `test`.`t3` `t3c` where <expr_cache><`test`.`t3c`.`c1`,`test`.`t3c`.`c2`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t3c`.`c1`,`test`.`t3c`.`c2`),<exists>(<index_lookup>(<cache>(`test`.`t3c`.`c1`) in t2i on it2i3 where (`test`.`t2i`.`b2` > '0' or `test`.`t2i`.`b2` = `test`.`t1`.`a2`) and <cache>(`test`.`t3c`.`c1`) = `test`.`t2i`.`b1` and <cache>(`test`.`t3c`.`c2`) = `test`.`t2i`.`b2`)))) and <cache>(`test`.`t1`.`a1`) = `test`.`t3c`.`c1` and <cache>(`test`.`t1`.`a2`) = `test`.`t3c`.`c2`)))
explain extended
select * from t1 where (a1, a2) in (select '1 - 01', '2 - 01');
id select_type table type possible_keys key key_len ref rows filtered Extra
......
......@@ -446,8 +446,8 @@ SELECT i2 FROM t2 RIGHT JOIN t3 ON (c3 = c2) WHERE pk3 = i1
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 system NULL NULL NULL NULL 1
2 DEPENDENT SUBQUERY t3 const PRIMARY PRIMARY 4 const 1
2 DEPENDENT SUBQUERY t2 index i2 i2 11 NULL 2 Using where; Using index
2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY PRIMARY 4 func 1
2 DEPENDENT SUBQUERY t2 index NULL i2 11 NULL 2 Using where; Using index; Using join buffer (flat, BNL join)
DROP TABLE t1,t2,t3;
#
# MDEV-7599: in-to-exists chosen after min/max optimization
......
......@@ -466,7 +466,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ref a a 5 test.t0.a 1 100.00 Using where; FirstMatch(t2)
Warnings:
Note 1276 Field or reference 'test.t0.a' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t0`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) join `test`.`t0` where `test`.`t2`.`a` = `test`.`t0`.`a` and `test`.`t1`.`a` = `test`.`t0`.`a` and `test`.`t1`.`b` = `test`.`t2`.`b`
Note 1003 select `test`.`t0`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) join `test`.`t0` where `test`.`t1`.`b` = `test`.`t2`.`b` and `test`.`t2`.`a` = `test`.`t0`.`a` and `test`.`t1`.`a` = `test`.`t0`.`a`
select * from t0
where t0.a in ( select t1.a from t1,t2 where t2.a=t0.a and
t1.b=t2.b);
......
......@@ -472,7 +472,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ref a a 5 test.t0.a 1 100.00 Using where; FirstMatch(t2); Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan
Warnings:
Note 1276 Field or reference 'test.t0.a' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t0`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) join `test`.`t0` where `test`.`t2`.`a` = `test`.`t0`.`a` and `test`.`t1`.`a` = `test`.`t0`.`a` and `test`.`t1`.`b` = `test`.`t2`.`b`
Note 1003 select `test`.`t0`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) join `test`.`t0` where `test`.`t1`.`b` = `test`.`t2`.`b` and `test`.`t2`.`a` = `test`.`t0`.`a` and `test`.`t1`.`a` = `test`.`t0`.`a`
select * from t0
where t0.a in ( select t1.a from t1,t2 where t2.a=t0.a and
t1.b=t2.b);
......
......@@ -468,7 +468,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ref a a 5 test.t0.a 1 100.00 Using where; FirstMatch(t2)
Warnings:
Note 1276 Field or reference 'test.t0.a' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t0`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) join `test`.`t0` where `test`.`t2`.`a` = `test`.`t0`.`a` and `test`.`t1`.`a` = `test`.`t0`.`a` and `test`.`t1`.`b` = `test`.`t2`.`b`
Note 1003 select `test`.`t0`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) join `test`.`t0` where `test`.`t1`.`b` = `test`.`t2`.`b` and `test`.`t2`.`a` = `test`.`t0`.`a` and `test`.`t1`.`a` = `test`.`t0`.`a`
select * from t0
where t0.a in ( select t1.a from t1,t2 where t2.a=t0.a and
t1.b=t2.b);
......
......@@ -504,11 +504,13 @@ test.t1 analyze status OK
explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
affected rows: 32
info: Rows matched: 32 Changed: 32 Warnings: 0
......@@ -1777,11 +1779,13 @@ test.t1 analyze status OK
explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
affected rows: 32
info: Rows matched: 32 Changed: 32 Warnings: 0
......@@ -3051,11 +3055,13 @@ test.t1 analyze status OK
explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
affected rows: 32
info: Rows matched: 32 Changed: 32 Warnings: 0
......@@ -4324,11 +4330,13 @@ test.t1 analyze status OK
explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
affected rows: 32
info: Rows matched: 32 Changed: 32 Warnings: 0
......@@ -5598,11 +5606,13 @@ test.t1 analyze status OK
explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
affected rows: 32
info: Rows matched: 32 Changed: 32 Warnings: 0
......@@ -6871,11 +6881,13 @@ test.t1 analyze status OK
explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
affected rows: 32
info: Rows matched: 32 Changed: 32 Warnings: 0
......@@ -8145,11 +8157,13 @@ test.t1 analyze note The storage engine for the table doesn't support analyze
explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
affected rows: 32
info: Rows matched: 32 Changed: 32 Warnings: 0
......@@ -9410,11 +9424,13 @@ test.t1 analyze note The storage engine for the table doesn't support analyze
explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 32
1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
2 MATERIALIZED a ALL NULL NULL NULL NULL 32
update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1);
affected rows: 32
info: Rows matched: 32 Changed: 32 Warnings: 0
......
......@@ -43,6 +43,7 @@
#include "sql_cte.h"
#include "sql_test.h"
#include "opt_trace.h"
#include "opt_subselect.h"
double get_post_group_estimate(JOIN* join, double join_op_rows);
......@@ -1630,7 +1631,8 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp,
is_jtbm_const_tab(FALSE), is_flattenable_semijoin(FALSE),
is_registered_semijoin(FALSE),
upper_item(0),
converted_from_in_predicate(FALSE)
converted_from_in_predicate(FALSE),
not_nulls_after(-1)
{
DBUG_ENTER("Item_in_subselect::Item_in_subselect");
DBUG_PRINT("info", ("in_strategy: %u", (uint)in_strategy));
......@@ -2705,7 +2707,10 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
ref_pointer_array[i],
no_matter_name,
list_ref));
if (!is_top_level_item() && select_lex->ref_pointer_array[i]->maybe_null())
bool do_null_handling= (not_nulls_after == -1 ||
(int)i <= not_nulls_after);
if (do_null_handling && !is_top_level_item() &&
select_lex->ref_pointer_array[i]->maybe_null())
{
Item *having_col_item=
new (thd->mem_root)
......@@ -2737,7 +2742,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
}
*having_item= and_items(thd, *having_item, having_col_item);
}
if (!is_top_level_item() && left_expr->element_index(i)->maybe_null() &&
if (do_null_handling && !is_top_level_item() && left_expr->element_index(i)->maybe_null() &&
get_cond_guard(i))
{
if (!(item= new (thd->mem_root)
......@@ -3025,14 +3030,6 @@ static bool check_equality_for_exist2in(Item_func *func,
return FALSE;
}
typedef struct st_eq_field_outer
{
Item **eq_ref;
Item_ident *local_field;
Item *outer_exp;
} EQ_FIELD_OUTER;
/**
Check if 'conds' is a set of AND-ed outer_expr=inner_table.col equalities
......@@ -3099,6 +3096,439 @@ static bool find_inner_outer_equalities(Item **conds,
return TRUE;
}
/* Check whether item tree intersects with the free list */
static bool intersects_free_list(Item *item, THD *thd)
{
for (const Item *to_find= thd->free_list; to_find; to_find= to_find->next)
if (item->walk(&Item::find_item_processor, 1, (void *) to_find))
return true;
return false;
}
/*
Prepare exists2in / decorrelation transformation
Pick out the equalities, prevent 2nd ps execution segfault, check for
correlation, etc.
@param thd The connection
@param eqs OUT The decorrelate-able equalities
@param will_be_correlated OUT Whether the resulting IN subquery will
still be correlated
@retval FALSE ok
@retval TRUE error
*/
bool Item_exists_subselect::exists2in_prepare(
THD *thd, Dynamic_array<EQ_FIELD_OUTER> &eqs, bool *will_be_correlated)
{
SELECT_LEX *first_select= unit->first_select();
DBUG_ENTER("exists2in_prepare");
DBUG_ASSERT(substype() == EXISTS_SUBS || substype() == IN_SUBS);
/* Iterate over the conditions and find decorrelatable equalities */
if (find_inner_outer_equalities(&first_select->join->conds, eqs))
DBUG_RETURN(TRUE);
DBUG_ASSERT(eqs.elements() != 0);
/*
If we are in a ps/sp execution, check for and skip on
intersection with the temporary free list to avoid 2nd ps execution
segfault
*/
if (!thd->stmt_arena->is_conventional())
{
for (uint i= 0; i < (uint) eqs.elements(); i++)
{
if (intersects_free_list(*eqs.at(i).eq_ref, thd))
DBUG_RETURN(TRUE);
}
}
/* Determine whether the result will be correlated */
{
List<Item> unused;
Item::Collect_deps_prm prm= {&unused, // parameters
first_select->nest_level_base, // nest_level_base
0, // count
first_select->nest_level, // nest_level
FALSE // collect
};
walk(&Item::collect_outer_ref_processor, TRUE, &prm);
DBUG_ASSERT(prm.count > 0);
DBUG_ASSERT(prm.count >= (uint)eqs.elements());
*will_be_correlated= prm.count > (uint)eqs.elements();
if (substype() == EXISTS_SUBS && upper_not && *will_be_correlated)
DBUG_RETURN(TRUE);
}
/*
Check that there are enough slots in
`first_select->ref_pointer_array` for the local fields
*/
if ((uint)eqs.elements() > (first_select->item_list.elements +
first_select->select_n_reserved))
DBUG_RETURN(TRUE);
DBUG_RETURN(FALSE);
}
/*
@brief
Move the items around for the exists2in / decorrelate-in transformation
For exists2in, replace the inner select items with local fields; for
decorrelate-in, add them to the inner select items. For both move
the outer expressions to the left expr in the IN subquery.
@detail
Example of conversion for EXISTS:
EXISTS (SELECT smth FROM t WHERE subq_where AND t.col=outer_col)
->
left_expr_ref=t.col
EXISTS (SELECT t.col FROM t WHERE subq_where AND "1")
Example of conversion for IN:
outer_expr IN (SELECT inner_expr
FROM t
WHERE subq_where AND t.col=outer_col)
->
left_expr_ref=t.col
outer_expr IN (SELECT inner_expr, t.col -- <-- Note this
FROM t WHERE subq_where AND "1")
The "1" is in quotes just to emphasize it.
In case of NULL-aware execution, instead of "1" we get "t.col IS NOT NULL".
@param thd The connection
@param eqs The decorrelatable equalities
@param left_exp_ref OUT The left expr for the resulting IN subquery
@retval FALSE ok
@retval TRUE error
*/
bool Item_exists_subselect::exists2in_create_or_update_in(
THD *thd, const Dynamic_array<EQ_FIELD_OUTER> &eqs, Item** left_exp_ref)
{
SELECT_LEX *first_select= unit->first_select();
List_iterator<Item> it;
List<Item> outer;
uint offset= 0;
Item_in_subselect *in_subs= NULL;
DBUG_ENTER("Item_exists_subselect::exists2in_create_or_update_in");
DBUG_ASSERT(substype() == EXISTS_SUBS || substype() == IN_SUBS);
/* Construct the items for left_expr */
if (substype() == EXISTS_SUBS)
{
/* For EXISTS, remove redundant inner select items */
while (first_select->item_list.elements > (uint)eqs.elements())
{
first_select->item_list.pop();
first_select->join->all_fields.elements--;
}
it.init(first_select->item_list);
}
else
{
/*
For IN, copy existing left expr items, and point the iterator
at the end of the inner select item list so that nothing gets
overwritten
*/
it.init(first_select->item_list);
DBUG_ASSERT(substype() == IN_SUBS);
in_subs= (Item_in_subselect*) this;
offset= first_select->item_list.elements;
in_subs->not_nulls_after= offset - 1;
if (in_subs->left_expr->type() == Item::ROW_ITEM)
{
for (uint i= 0; i < in_subs->left_expr->cols(); i++, it++)
outer.push_back(in_subs->left_expr->element_index(i));
}
else
{
outer.push_back(in_subs->left_expr);
it++;
}
DBUG_ASSERT(outer.elements == first_select->item_list.elements);
List_iterator<Item> it(outer);
Item *item;
while ((item= it++))
{
item->fix_after_pullout(unit->outer_select(), it.ref(), FALSE);
item->update_used_tables();
}
}
/* Move items to outer and select item list */
for (uint i= 0; i < (uint)eqs.elements(); i++)
{
Item *item= it++;
Item **eq_ref= eqs.at(i).eq_ref;
Item_ident *local_field= eqs.at(i).local_field;
Item *outer_exp= eqs.at(i).outer_exp;
/* Replace or add items to the inner select item list */
if (item)
it.replace(local_field);
else
{
first_select->item_list.push_back(local_field, thd->mem_root);
if (substype() == EXISTS_SUBS)
first_select->join->all_fields.elements++;
}
first_select->ref_pointer_array[offset + i]= (Item *) local_field;
/* Replace the equalities with 1 or local_field IS NOT NULL */
if (!upper_not || !local_field->maybe_null())
*eq_ref= new (thd->mem_root) Item_int(thd, 1);
else
{
*eq_ref= new (thd->mem_root)
Item_func_isnotnull(thd,
new (thd->mem_root)
Item_field(thd,
((Item_field *)
(local_field->real_item()))->context,
((Item_field *)
(local_field->real_item()))->field));
if ((*eq_ref)->fix_fields(thd, (Item **) eq_ref))
DBUG_RETURN(TRUE);
}
outer_exp->fix_after_pullout(unit->outer_select(), &outer_exp, FALSE);
outer_exp->update_used_tables();
/* Add the outer_exp to the left expr list */
outer.push_back(outer_exp, thd->mem_root);
}
/* Update the left expr */
if (outer.elements == 1)
*left_exp_ref= outer.head();
else
if (!(*left_exp_ref= new (thd->mem_root) Item_row(thd, outer)))
DBUG_RETURN(TRUE);
if ((*left_exp_ref)->fix_fields_if_needed(thd, left_exp_ref))
DBUG_RETURN(TRUE);
DBUG_RETURN(FALSE);
}
/*
@brief
AND the IN subquery with IS NOT NULLs if upper_not
Due to the three-value logic, we need to AND the IN subquery with
outer_expr IS NOT NULL so that the exists2in / decorrelate-in
transformation is correct, i.e. new IN subquery evals to the same
value as the as the old EXISTS/IN subquery.
@detail
Example transformation, offset=2:
NOT ( (orig_expr1, orig_expr2, added_expr1, added_expr2) IN
(SELECT ... FROM ...))
->
NOT (added_expr1 IS NOT NULL AND
added_expr2 IS NOT NULL AND
(orig_expr1, ..(same as before).. ) IN (SELECT ... FROM ...)
)
@param offset The offset in the left expr coming from the new item
@param left_exp_ref The reference pointer to the left expr
@retval FALSE ok
@retval TRUE error
*/
bool Item_exists_subselect::exists2in_and_is_not_nulls(uint offset,
Item **left_exp_ref)
{
DBUG_ENTER("Item_exists_subselect::exists2in_and_is_not_nulls");
DBUG_ASSERT(substype() == EXISTS_SUBS || substype() == IN_SUBS);
Item *left_exp= *left_exp_ref;
if (upper_not)
{
/* optimizer == 0 implies `this` is an Item_in_subselect */
Item *exp= optimizer ? (Item *) optimizer : (Item *) this;
List<Item> *and_list= new (thd->mem_root) List<Item>;
if (!and_list)
DBUG_RETURN(TRUE);
if (left_exp->type() != ROW_ITEM)
{
if (left_exp->maybe_null())
{
and_list->
push_front(new (thd->mem_root)
Item_func_isnotnull(thd,
new (thd->mem_root)
Item_direct_ref(thd,
&unit->outer_select()->context,
left_exp_ref,
no_matter_name,
exists_outer_expr_name)),
thd->mem_root);
}
}
else
{
for (uint i= offset; i < left_exp->cols(); i++)
{
if (left_exp->element_index(i)->maybe_null())
{
and_list->
push_front(new (thd->mem_root)
Item_func_isnotnull(thd,
new (thd->mem_root)
Item_direct_ref(thd,
&unit->outer_select()->context,
left_exp->addr(i),
no_matter_name,
exists_outer_expr_name)),
thd->mem_root);
}
}
}
if (and_list->elements > 1)
{
and_list->push_front(exp, thd->mem_root);
exp= new (thd->mem_root) Item_cond_and(thd, *and_list);
}
/*
If we do not single out this case, and merge it with the >1
case, we would get an infinite loop in resolving
Item_direct_view_ref::real_item() like in MDEV-3881 when
left_exp has scalar type
*/
else if (and_list->elements == 1)
exp= new (thd->mem_root) Item_cond_and(thd, and_list->head(), exp);
upper_not->arguments()[0]= exp;
if (exp->fix_fields_if_needed(thd, upper_not->arguments()))
DBUG_RETURN(TRUE);
}
DBUG_RETURN(FALSE);
}
/*
De-correlate where conditions in an IN subquery
Similar to `Item_exists_subselect::exists2in_processor()`, it checks
for equalities in the form of outer_exp = inner_field in the where
condition, and move the outer_exp to left_expr, and inner_field to
the select item list in the IN subquery
@param opt_arg a cast to a THD*, the connection
@retval FALSE ok
@retval TRUE error
*/
bool Item_in_subselect::exists2in_processor(void *opt_arg)
{
THD *thd= (THD *) opt_arg;
SELECT_LEX *first_select= unit->first_select();
JOIN *join= first_select->join;
bool will_be_correlated;
Dynamic_array<EQ_FIELD_OUTER> eqs(PSI_INSTRUMENT_MEM, 5, 5);
Query_arena *arena= NULL, backup;
int res= FALSE;
const uint offset= first_select->item_list.elements;
DBUG_ENTER("Item_in_subselect::exists2in_processor");
/*
Skip the transformation if it is not needed or would not help
(1) optimizer flag exists_to_in is off
(2) skip if the subquery is not toplevel IN nor toplevel NOT IN
(3) skip if the subquery is a part of a union
(4) skip if the subquery has group by
(5) skip if the subquery has aggregation in the select
(6) skip if the subquery has having
(7) skip if the subquery does not have where conditions
(8) skip if the left expr is a single nonscalar subselect
*/
if (!optimizer_flag(thd, OPTIMIZER_SWITCH_EXISTS_TO_IN) || /* (1) */
!(is_top_level_item() ||
(upper_not && upper_not->is_top_level_item())) || /* (2) */
first_select->is_part_of_union() || /* (3) */
first_select->group_list.elements || /* (4) */
first_select->with_sum_func || /* (5) */
join->having || /* (6) */
!join->conds || /* (7) */
(left_expr->type() == Item::SUBSELECT_ITEM &&
!left_expr->type_handler()->is_scalar_type())) /* (8) */
DBUG_RETURN(FALSE);
if (exists2in_prepare(thd, eqs, &will_be_correlated))
DBUG_RETURN(FALSE);
/* Switch to the permanent arena if we are in a ps/sp execution */
arena= thd->activate_stmt_arena_if_needed(&backup);
if (exists2in_create_or_update_in(thd, eqs, &left_expr))
{
res= TRUE;
goto out;
}
left_expr_orig= left_expr;
is_correlated= will_be_correlated;
/* Update any Item_in_optimizer wrapper if exists */
if (optimizer)
{
optimizer->reset_cache();
if (optimizer->fix_left(thd))
{
res= TRUE;
goto out;
}
}
if (exists2in_and_is_not_nulls(offset, &left_expr))
{
res= TRUE;
goto out;
}
{
OPT_TRACE_TRANSFORM(thd, trace_wrapper, trace_transform,
get_select_lex()->select_number, "IN (SELECT)",
"decorrelation");
trace_transform.add("is_correlated", (is_correlated ? true : false));
}
/*
If not having materialization as a strategy and it is not a
semijoin thus will not have a chance of adding materialization later
in `check_and_do_in_subquery_rewrites()`, try to add materialization
again
*/
if (!test_strategy(SUBS_MATERIALIZATION) && !is_registered_semijoin)
{
if (is_materialization_applicable(thd, this, first_select))
add_strategy(SUBS_MATERIALIZATION);
}
out:
/* Switch back to the runtime arena */
if (arena)
thd->restore_active_arena(arena, &backup);
DBUG_RETURN(res);
}
/**
Converts EXISTS subquery to IN subquery if it is possible and has sense
......@@ -3112,13 +3542,9 @@ bool Item_exists_subselect::exists2in_processor(void *opt_arg)
THD *thd= (THD *)opt_arg;
SELECT_LEX *first_select=unit->first_select(), *save_select;
JOIN *join= first_select->join;
Item **eq_ref= NULL;
Item_ident *local_field= NULL;
Item *outer_exp= NULL;
Item *left_exp= NULL; Item_in_subselect *in_subs;
Query_arena *arena= NULL, backup;
int res= FALSE;
List<Item> outer;
Dynamic_array<EQ_FIELD_OUTER> eqs(PSI_INSTRUMENT_MEM, 5, 5);
bool will_be_correlated;
DBUG_ENTER("Item_exists_subselect::exists2in_processor");
......@@ -3163,99 +3589,19 @@ bool Item_exists_subselect::exists2in_processor(void *opt_arg)
DBUG_ASSERT(first_select->group_list.elements == 0 &&
first_select->having == NULL);
if (find_inner_outer_equalities(&join->conds, eqs))
DBUG_RETURN(FALSE);
DBUG_ASSERT(eqs.elements() != 0);
save_select= thd->lex->current_select;
thd->lex->current_select= first_select;
/* check that the subquery has only dependencies we are going pull out */
{
List<Item> unused;
Collect_deps_prm prm= {&unused, // parameters
unit->first_select()->nest_level_base, // nest_level_base
0, // count
unit->first_select()->nest_level, // nest_level
FALSE // collect
};
walk(&Item::collect_outer_ref_processor, TRUE, &prm);
DBUG_ASSERT(prm.count > 0);
DBUG_ASSERT(prm.count >= (uint)eqs.elements());
will_be_correlated= prm.count > (uint)eqs.elements();
if (upper_not && will_be_correlated)
goto out;
}
if ((uint)eqs.elements() > (first_select->item_list.elements +
first_select->select_n_reserved))
goto out;
if (exists2in_prepare(thd, eqs, &will_be_correlated))
DBUG_RETURN(FALSE);
arena= thd->activate_stmt_arena_if_needed(&backup);
while (first_select->item_list.elements > (uint)eqs.elements())
{
first_select->item_list.pop();
first_select->join->all_fields.elements--;
}
{
List_iterator<Item> it(first_select->item_list);
for (uint i= 0; i < (uint)eqs.elements(); i++)
{
Item *item= it++;
eq_ref= eqs.at(i).eq_ref;
local_field= eqs.at(i).local_field;
outer_exp= eqs.at(i).outer_exp;
/* Add the field to the SELECT_LIST */
if (item)
it.replace(local_field);
else
{
first_select->item_list.push_back(local_field, thd->mem_root);
first_select->join->all_fields.elements++;
}
first_select->ref_pointer_array[i]= (Item *)local_field;
/* remove the parts from condition */
if (!upper_not || !local_field->maybe_null())
*eq_ref= new (thd->mem_root) Item_int(thd, 1);
else
{
*eq_ref= new (thd->mem_root)
Item_func_isnotnull(thd,
new (thd->mem_root)
Item_field(thd,
((Item_field*)(local_field->
real_item()))->context,
((Item_field*)(local_field->
real_item()))->field));
if((*eq_ref)->fix_fields(thd, (Item **)eq_ref))
if (exists2in_create_or_update_in(thd, eqs, &left_exp))
{
res= TRUE;
goto out;
}
}
outer_exp->fix_after_pullout(unit->outer_select(), &outer_exp, FALSE);
outer_exp->update_used_tables();
outer.push_back(outer_exp, thd->mem_root);
}
}
join->conds->update_used_tables();
/* make IN SUBQUERY and put outer_exp as left part */
if (eqs.elements() == 1)
left_exp= outer_exp;
else
{
if (!(left_exp= new (thd->mem_root) Item_row(thd, outer)))
{
res= TRUE;
goto out;
}
}
/* make EXISTS->IN permanet (see Item_subselect::init()) */
set_exists_transformed();
......@@ -3360,64 +3706,11 @@ bool Item_exists_subselect::exists2in_processor(void *opt_arg)
first_select->fix_prepare_information(thd, &join->conds, &join->having);
if (upper_not)
{
Item *exp;
if (eqs.elements() == 1)
{
exp= (optimizer->arguments()[0]->maybe_null() ?
(Item*) new (thd->mem_root)
Item_cond_and(thd,
new (thd->mem_root)
Item_func_isnotnull(thd,
new (thd->mem_root)
Item_direct_ref(thd,
&unit->outer_select()->context,
optimizer->arguments(),
no_matter_name,
exists_outer_expr_name)),
optimizer) :
(Item *)optimizer);
}
else
{
List<Item> *and_list= new (thd->mem_root) List<Item>;
if (!and_list)
if (exists2in_and_is_not_nulls(0, optimizer->arguments()))
{
res= TRUE;
goto out;
}
for (size_t i= 0; i < eqs.elements(); i++)
{
if (optimizer->arguments()[0]->maybe_null())
{
and_list->
push_front(new (thd->mem_root)
Item_func_isnotnull(thd,
new (thd->mem_root)
Item_direct_ref(thd,
&unit->outer_select()->context,
optimizer->arguments()[0]->addr((int)i),
no_matter_name,
exists_outer_expr_name)),
thd->mem_root);
}
}
if (and_list->elements > 0)
{
and_list->push_front(optimizer, thd->mem_root);
exp= new (thd->mem_root) Item_cond_and(thd, *and_list);
}
else
exp= optimizer;
}
upper_not->arguments()[0]= exp;
if (exp->fix_fields_if_needed(thd, upper_not->arguments()))
{
res= TRUE;
goto out;
}
}
out:
thd->lex->current_select= save_select;
......
......@@ -365,6 +365,13 @@ class Item_maxmin_subselect :public Item_singlerow_subselect
void no_rows_in_result() override;
};
typedef struct st_eq_field_outer
{
Item **eq_ref;
Item_ident *local_field;
Item *outer_exp;
} EQ_FIELD_OUTER;
/* exists subselect */
class Item_exists_subselect :public Item_subselect
......@@ -375,7 +382,12 @@ class Item_exists_subselect :public Item_subselect
void init_length_and_dec();
bool select_prepare_to_be_in();
bool exists2in_prepare(THD *thd, Dynamic_array<EQ_FIELD_OUTER> &eqs,
bool *will_be_correlated);
bool exists2in_create_or_update_in(THD *thd,
const Dynamic_array<EQ_FIELD_OUTER> &eqs,
Item** left_exp_ref);
bool exists2in_and_is_not_nulls(uint offset, Item **left_exp_ref);
public:
/*
Used by subquery optimizations to keep track about in which clause this
......@@ -617,13 +629,22 @@ class Item_in_subselect :public Item_exists_subselect
*/
bool converted_from_in_predicate;
/*
-1 means "do nothing"
Other value means that we can assume that left_expr->element_index(i)
cannot be NULL (because decorrelation code has added IS NOT NULL before
the subquery predicate).
*/
int not_nulls_after;
Item_in_subselect(THD *thd_arg, Item * left_expr, st_select_lex *select_lex);
Item_in_subselect(THD *thd_arg):
Item_exists_subselect(thd_arg), left_expr_cache(0), first_execution(TRUE),
in_strategy(SUBS_NOT_TRANSFORMED),
pushed_cond_guards(NULL), func(NULL), do_not_convert_to_sj(FALSE),
is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE), upper_item(0),
converted_from_in_predicate(FALSE) {}
converted_from_in_predicate(FALSE),
not_nulls_after(-1) {}
void cleanup() override;
subs_type substype() override { return IN_SUBS; }
void reset() override
......@@ -757,10 +778,7 @@ class Item_in_subselect :public Item_exists_subselect
Item_subselect::walk(processor, walk_subquery, arg);
}
bool exists2in_processor(void *opt_arg __attribute__((unused))) override
{
return 0;
};
bool exists2in_processor(void *opt_arg) override;
bool pushdown_cond_for_in_subquery(THD *thd, Item *cond);
......@@ -804,6 +822,7 @@ class Item_allany_subselect :public Item_in_subselect
bool is_maxmin_applicable(JOIN *join);
bool transform_into_max_min(JOIN *join);
void no_rows_in_result();
bool exists2in_processor(void *arg) override { return FALSE; }
};
......
......@@ -431,3 +431,6 @@ void get_delayed_table_estimates(TABLE *table,
enum_nested_loop_state join_tab_execution_startup(JOIN_TAB *tab);
bool is_materialization_applicable(THD *thd, Item_in_subselect *in_subs,
st_select_lex *child_select);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment