--disable_warnings drop table if exists t0, t1, t2, t3, t4; --enable_warnings # # 1. Subquery with GROUP/HAVING # create table t1 (oref int, grp int, ie int) ; insert into t1 (oref, grp, ie) values (1, 1, 1), (1, 1, 1), (1, 2, NULL), (2, 1, 3), (3, 1, 4), (3, 2, NULL); # Ok, for # select max(ie) from t1 where oref=PARAM group by grp # we'll have: # 1 -> (1, NULL) matching + NULL # 2 -> (3) non-matching # 3 -> (3, NULL) non-matching + NULL # 4 -> () nothing. create table t2 (oref int, a int); insert into t2 values (1, 1), (2, 2), (3, 3), (4, NULL), (2, NULL); # true, false, null, false, null select a, oref, a in (select max(ie) from t1 where oref=t2.oref group by grp) from t2; # This must have a trigcond explain extended select a, oref, a in (select max(ie) from t1 where oref=t2.oref group by grp) from t2; # This must not have a trigcond: explain extended select a, oref from t2 where a in (select max(ie) from t1 where oref=t2.oref group by grp); # Non-correlated subquery, 2 NULL evaluations create table t3 (a int); insert into t3 values (NULL), (NULL); flush status; select a in (select max(ie) from t1 where oref=4 group by grp) from t3; show status like 'Handler_read_rnd_next'; select ' ^ This must show 11' Z; # This must show trigcond: explain extended select a in (select max(ie) from t1 where oref=4 group by grp) from t3; drop table t1, t2, t3; # # 2. Subquery handled with 'index_subquery': # create table t1 (a int, oref int, key(a)); insert into t1 values (1, 1), (1, NULL), (2, 3), (2, NULL), (3, NULL); create table t2 (a int, oref int); insert into t2 values (1, 1), (2,2), (NULL, 3), (NULL, 4); select oref, a, a in (select a from t1 where oref=t2.oref) Z from t2; # The next explain shows "using index" but that is just incorrect display # (there is a bug filed about this). explain extended select oref, a, a in (select a from t1 where oref=t2.oref) Z from t2; flush status; select oref, a from t2 where a in (select a from t1 where oref=t2.oref); # This will only show access to t2: show status like '%Handler_read_rnd_next'; # Check that repeated NULL-scans are not cached (subq. is not correlated): delete from t2; insert into t2 values (NULL, 0),(NULL, 0), (NULL, 0), (NULL, 0); flush status; select oref, a, a in (select a from t1 where oref=t2.oref) Z from t2; show status like '%Handler_read%'; select 'No key lookups, seq reads: 29= 5 reads from t2 + 4 * 6 reads from t1.' Z; drop table t1, t2; # # 3. Subquery handled with 'unique_index_subquery': # create table t1 (a int, b int, primary key (a)); insert into t1 values (1,1), (3,1),(100,1); create table t2 (a int, b int); insert into t2 values (1,1),(2,1),(NULL,1),(NULL,0); select a,b, a in (select a from t1 where t1.b = t2.b) Z from t2 ; drop table t1, t2; # # 4. Subquery that is a join, with ref access # create table t1 (a int, b int, key(a)); insert into t1 values (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9); create table t2 like t1; insert into t2 select * from t1; update t2 set b=1; create table t3 (a int, oref int); insert into t3 values (1, 1), (NULL,1), (NULL,0); select a, oref, t3.a in (select t1.a from t1, t2 where t1.b=t2.a and t2.b=t3.oref) Z from t3; # This must have trigcond in WHERE and HAVING: explain extended select a, oref, t3.a in (select t1.a from t1, t2 where t1.b=t2.a and t2.b=t3.oref) Z from t3; drop table t1, t2, t3;