mirror of
				https://github.com/MariaDB/server.git
				synced 2025-10-31 15:50:51 +03:00 
			
		
		
		
	Objects of the classes Item_func_is_not_null_test and Item_func_trig_cond must be transparent for the method Item::split_sum_func2 as these classes are pure helpers. It means that the method Item::split_sum_func2 should look at those objects as at pure wrappers. mysql-test/r/subselect3.result: Added a test case for bug #24420. mysql-test/t/subselect3.test: Added a test case for bug #24420.
		
			
				
	
	
		
			492 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			492 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| --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:
 | |
| # PARAM      subquery result  
 | |
| #   1   ->   {(1), (NULL)}    matching + NULL
 | |
| #   2   ->   {(3)}            non-matching
 | |
| #   3   ->   {(3), (NULL)}    non-matching + NULL
 | |
| #   4   ->   {}               empty set
 | |
| 
 | |
| 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) Z 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) Z 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);
 | |
| select a, oref, a in (
 | |
|   select max(ie) from t1 where oref=t2.oref group by grp union
 | |
|   select max(ie) from t1 where oref=t2.oref group by grp
 | |
|   ) Z from t2;
 | |
| 
 | |
| # 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;
 | |
| 
 | |
| 
 | |
| #
 | |
| # BUG#24085: Wrong query result for "NULL IN (SELECT ... UNION SELECT ...)"
 | |
| #
 | |
| 
 | |
| # case 1: NULL IN (SELECT not_null_val FROM ...) w/o HAVING/GROUP-BY/etc
 | |
| create table t1 (a int NOT NULL, b int NOT NULL, 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;
 | |
| 
 | |
| --echo This must show a trig_cond:
 | |
| 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;
 | |
| 
 | |
| 
 | |
| # case 2: NULL IN (SELECT not_null_val FROM) where SELECT has GROUP BY
 | |
| create table t1 (oref int, grp int);
 | |
| insert into t1 (oref, grp) values
 | |
|  (1, 1),
 | |
|  (1, 1);
 | |
| 
 | |
| # Ok, for  
 | |
| #   select count(*) from t1 group by grp having grp=PARAM
 | |
| # we'll have:
 | |
| #  PARAM    subuqery result
 | |
| #    1  ->    {(2)}   
 | |
| #    2  ->    {} - empty set
 | |
| create table t2 (oref int, a int);
 | |
| insert into t2 values 
 | |
|   (1, NULL),
 | |
|   (2, NULL);
 | |
| 
 | |
| select a, oref, 
 | |
|        a in (select count(*) from t1 group by grp having grp=t2.oref) Z from t2;
 | |
| 
 | |
| --echo This must show a trig_cond:
 | |
| explain extended
 | |
| select a, oref, 
 | |
|        a in (select count(*) from t1 group by grp having grp=t2.oref) Z from t2;
 | |
| 
 | |
| drop table t1, t2;
 | |
| 
 | |
| 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 union select a from
 | |
| t1 where t1.b = t2.b) Z from t2 ;
 | |
| select a,b, a in (select a from t1 where t1.b = t2.b) Z from t2 ;
 | |
| drop table t1, t2;
 | |
| 
 | |
| 
 | |
| #
 | |
| # BUG#24127: Incorrect results of row-based subqueries with NULLs on the left side.
 | |
| #
 | |
| create table t3 (a int);
 | |
| insert into t3 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
 | |
| create table t2 (a int, b int, oref int);
 | |
| insert into t2 values (NULL,1, 100), (NULL,2, 100);
 | |
| 
 | |
| create table t1 (a int, b int, c int, key(a,b));
 | |
| insert into t1 select 2*A, 2*A, 100 from t3;
 | |
| 
 | |
| # First test index subquery engine
 | |
| explain extended select a,b, oref, (a,b) in (select a,b from t1 where c=t2.oref) Z from t2;
 | |
| select a,b, oref, (a,b) in (select a,b from t1 where c=t2.oref) Z from t2;
 | |
| 
 | |
| # Then check that we do turn off 'ref' scans in the subquery
 | |
| create table t4 (x int);
 | |
| insert into t4 select A.a + 10*B.a from t1 A, t1 B;
 | |
| explain extended 
 | |
|   select a,b, oref, 
 | |
|          (a,b) in (select a,b from t1,t4 where c=t2.oref) Z 
 | |
|   from t2;
 | |
| select a,b, oref, 
 | |
|        (a,b) in (select a,b from t1,t4 where c=t2.oref) Z 
 | |
| from t2;
 | |
| 
 | |
| drop table t1,t2,t3,t4;
 | |
| 
 | |
| # More tests for tricky multi-column cases, where some of pushed-down
 | |
| # equalities are used for index lookups and some arent.
 | |
| create table t1 (oref char(4), grp int, ie1 int, ie2 int);
 | |
| insert into t1 (oref, grp, ie1, ie2) values
 | |
|  ('aa', 10, 2, 1),
 | |
|  ('aa', 10, 1, 1),
 | |
|  ('aa', 20, 2, 1),
 | |
|  ('bb', 10, 3, 1),
 | |
|  ('cc', 10, 4, 2),
 | |
|  ('cc', 20, 3, 2),
 | |
|  
 | |
|  ('ee', 10, 2, 1),
 | |
|  ('ee', 10, 1, 2),
 | |
|  
 | |
|  ('ff', 20, 2, 2),
 | |
|  ('ff', 20, 1, 2);
 | |
| create table t2 (oref char(4), a int, b int);
 | |
| insert into t2 values 
 | |
|   ('ee', NULL, 1),
 | |
|   ('bb', 2, 1),
 | |
|   ('ff', 2, 2),
 | |
|   ('cc', 3, NULL),
 | |
|   ('bb', NULL, NULL),
 | |
|   ('aa', 1, 1),
 | |
|   ('dd', 1, NULL);
 | |
| alter table t1 add index idx(ie1,ie2);
 | |
| 
 | |
| --cc 3 NULL NULL
 | |
| select oref, a, b, (a,b) in (select ie1,ie2 from t1 where oref=t2.oref) Z from t2 where a=3 and b is null ;
 | |
| insert into t2 values ('new1', 10,10);
 | |
| insert into t1 values ('new1', 1234, 10, NULL); 
 | |
| -- new1, 10, 10, NULL,
 | |
| select oref, a, b, (a,b) in (select ie1,ie2 from t1 where oref=t2.oref) Z from t2 where a=10 and b=10; 
 | |
| explain extended
 | |
| select oref, a, b, (a,b) in (select ie1,ie2 from t1 where oref=t2.oref) Z from t2 where a=10 and b=10; 
 | |
| drop table t1, t2;
 | |
| 
 | |
| # Now test different column types:
 | |
| create table t1 (oref char(4), grp int, ie int);
 | |
| insert into t1 (oref, grp, ie) values
 | |
|  ('aa', 10, 2),
 | |
|  ('aa', 10, 1),
 | |
|  ('aa', 20, NULL),
 | |
| 
 | |
|  ('bb', 10, 3),
 | |
| 
 | |
|  ('cc', 10, 4),
 | |
|  ('cc', 20, NULL),
 | |
|  
 | |
|  ('ee', 10, NULL),
 | |
|  ('ee', 10, NULL),
 | |
|  
 | |
|  ('ff', 20, 2),
 | |
|  ('ff', 20, 1);
 | |
| 
 | |
| create table t2 (oref char(4), a int);
 | |
| insert into t2 values 
 | |
|   ('ee', NULL),
 | |
|   ('bb', 2),
 | |
|   ('ff', 2),
 | |
|   ('cc', 3),
 | |
|   ('aa', 1),
 | |
|   ('dd', NULL),
 | |
|   ('bb', NULL);
 | |
| 
 | |
| select oref, a, a in (select ie from t1 where oref=t2.oref) Z from t2;
 | |
| 
 | |
| select oref, a from t2 where a in (select ie from t1 where oref=t2.oref); 
 | |
| 
 | |
| select oref, a from t2 where a not in (select ie from t1 where oref=t2.oref);
 | |
| 
 | |
| 
 | |
| select oref, a, a in (select min(ie) from t1 where oref=t2.oref group by grp) Z from t2;
 | |
| 
 | |
| select oref, a from t2 where 
 | |
|   a in (select min(ie) from t1 where oref=t2.oref group by grp);
 | |
|   
 | |
| select oref, a from t2 where 
 | |
|   a not in (select min(ie) from t1 where oref=t2.oref group by grp);
 | |
| 
 | |
| #
 | |
| update t1 set ie=3 where oref='ff' and ie=1;
 | |
| 
 | |
| select oref, a, a in (select min(ie) from t1 where oref=t2.oref group by
 | |
| grp) Z from t2;
 | |
| 
 | |
| 
 | |
| select oref, a from t2 where a in (select min(ie) from t1 where
 | |
| oref=t2.oref group by grp);
 | |
| 
 | |
| select oref, a from t2 where a not in (select min(ie) from t1 where
 | |
| oref=t2.oref group by grp);
 | |
| 
 | |
| select oref, a, a in (select min(ie) from t1 where oref=t2.oref group by
 | |
| grp having min(ie) > 1) Z from t2;
 | |
| 
 | |
| select oref, a from t2 where a in (select min(ie) from t1 where
 | |
| oref=t2.oref group by grp having min(ie) > 1);
 | |
|   
 | |
| select oref, a from t2 where a not in (select min(ie) from t1 where
 | |
| oref=t2.oref group by grp having min(ie) > 1);
 | |
| 
 | |
| #
 | |
| alter table t1 add index idx(ie);
 | |
| 
 | |
| explain select oref, a, a in (select ie from t1 where oref=t2.oref) Z from t2;
 | |
| 
 | |
| select oref, a, a in (select ie from t1 where oref=t2.oref) Z from t2;
 | |
| 
 | |
| select oref, a from t2 where a in (select ie from t1 where oref=t2.oref); 
 | |
| 
 | |
| select oref, a from t2 where a not in (select ie from t1 where oref=t2.oref);
 | |
| 
 | |
| 
 | |
| alter table t1 drop index idx;
 | |
| alter table t1 add index idx(oref,ie);
 | |
| 
 | |
| explain select oref, a, a in (select ie from t1 where oref=t2.oref) Z from t2;
 | |
| 
 | |
| select oref, a, a in (select ie from t1 where oref=t2.oref) Z from t2;
 | |
| 
 | |
| select oref, a from t2 where a in (select ie from t1 where oref=t2.oref); 
 | |
| 
 | |
| select oref, a from t2 where a not in (select ie from t1 where oref=t2.oref);
 | |
| 
 | |
| explain 
 | |
| select oref, a, 
 | |
|        a in (select min(ie) from t1 where oref=t2.oref 
 | |
|              group by grp having min(ie) > 1) Z 
 | |
| from t2;
 | |
| 
 | |
| select oref, a, 
 | |
|        a in (select min(ie) from t1 where oref=t2.oref 
 | |
|              group by grp having min(ie) > 1) Z 
 | |
| from t2;
 | |
| 
 | |
| select oref, a from t2 where a in (select min(ie) from t1 where oref=t2.oref 
 | |
|                                    group by grp having min(ie) > 1);
 | |
|   
 | |
| select oref, a from t2 where a not in (select min(ie) from t1 where oref=t2.oref 
 | |
|                                        group by grp having min(ie) > 1);
 | |
| 
 | |
| drop table t1,t2;
 | |
| 
 | |
| create table t1 (oref char(4), grp int, ie1 int, ie2 int);
 | |
| insert into t1 (oref, grp, ie1, ie2) values
 | |
|  ('aa', 10, 2, 1),
 | |
|  ('aa', 10, 1, 1),
 | |
|  ('aa', 20, 2, 1),
 | |
| 
 | |
|  ('bb', 10, 3, 1),
 | |
| 
 | |
|  ('cc', 10, 4, 2),
 | |
|  ('cc', 20, 3, 2),
 | |
|  
 | |
|  ('ee', 10, 2, 1),
 | |
|  ('ee', 10, 1, 2),
 | |
|  
 | |
|  ('ff', 20, 2, 2),
 | |
|  ('ff', 20, 1, 2);
 | |
| 
 | |
| create table t2 (oref char(4), a int, b int);
 | |
| insert into t2 values 
 | |
|   ('ee', NULL, 1),
 | |
|   ('bb', 2, 1),
 | |
|   ('ff', 2, 2),
 | |
|   ('cc', 3, NULL),
 | |
|   ('bb', NULL, NULL),
 | |
|   ('aa', 1, 1),
 | |
|   ('dd', 1, NULL);
 | |
| 
 | |
| select oref, a, b, (a,b) in (select ie1,ie2 from t1 where oref=t2.oref) Z from t2;
 | |
| 
 | |
| select oref, a, b from t2 where (a,b) in (select ie1,ie2 from t1 where oref=t2.oref); 
 | |
| 
 | |
| select oref, a, b from t2 where (a,b) not in (select ie1,ie2 from t1 where oref=t2.oref);
 | |
| 
 | |
| select oref, a, b, 
 | |
|              (a,b) in (select min(ie1),max(ie2) from t1 
 | |
|                        where oref=t2.oref group by grp) Z 
 | |
| from t2;
 | |
| 
 | |
| select oref, a, b from t2 where 
 | |
|   (a,b) in (select min(ie1), max(ie2) from t1 where oref=t2.oref group by grp);
 | |
|   
 | |
| select oref, a, b from t2 where
 | |
|   (a,b) not in (select min(ie1), max(ie2) from t1 where oref=t2.oref group by grp);
 | |
| 
 | |
| alter table t1 add index idx(ie1,ie2);
 | |
| 
 | |
| explain select oref, a, b, (a,b) in (select ie1,ie2 from t1 where oref=t2.oref) Z from t2;
 | |
| 
 | |
| select oref, a, b, (a,b) in (select ie1,ie2 from t1 where oref=t2.oref) Z from t2;
 | |
| 
 | |
| select oref, a, b from t2 where (a,b) in (select ie1,ie2 from t1 where oref=t2.oref); 
 | |
| 
 | |
| select oref, a, b from t2 where (a,b) not in (select ie1,ie2 from t1 where oref=t2.oref);
 | |
| 
 | |
| explain extended 
 | |
| select oref, a, b, (a,b) in (select ie1,ie2 from t1 where oref=t2.oref) Z from t2;
 | |
| 
 | |
| drop table t1,t2;
 | |
| 
 | |
| create table t1 (oref char(4), grp int, ie int primary key);
 | |
| insert into t1 (oref, grp, ie) values
 | |
|  ('aa', 10, 2),
 | |
|  ('aa', 10, 1),
 | |
| 
 | |
|  ('bb', 10, 3),
 | |
| 
 | |
|  ('cc', 10, 4),
 | |
|  ('cc', 20, 5),
 | |
|  ('cc', 10, 6);
 | |
|  
 | |
| create table t2 (oref char(4), a int);
 | |
| insert into t2 values 
 | |
|   ('ee', NULL),
 | |
|   ('bb', 2),
 | |
|   ('cc', 5),
 | |
|   ('cc', 2),
 | |
|   ('cc', NULL),
 | |
|   ('aa', 1),
 | |
|   ('bb', NULL);
 | |
| 
 | |
| explain select oref, a, a in (select ie from t1 where oref=t2.oref) Z from t2;
 | |
| 
 | |
| select oref, a, a in (select ie from t1 where oref=t2.oref) Z from t2;
 | |
| 
 | |
| select oref, a from t2 where a in (select ie from t1 where oref=t2.oref);
 | |
| 
 | |
| select oref, a from t2 where a not in (select ie from t1 where oref=t2.oref);
 | |
| 
 | |
| explain 
 | |
| select oref, a, a in (select min(ie) from t1 where oref=t2.oref group by grp) Z from t2;
 | |
| 
 | |
| select oref, a, a in (select min(ie) from t1 where oref=t2.oref group by grp) Z from t2;
 | |
| 
 | |
| drop table t1,t2;
 | |
| 
 | |
| #
 | |
| # BUG#24420: row-based IN suqueries with aggregation when the left operand
 | |
| #            of the subquery predicate may contain NULL values
 | |
| #
 | |
| 
 | |
| create table t1 (a int, b int);
 | |
| insert into t1 values (0,0), (2,2), (3,3);
 | |
| create table t2 (a int, b int);
 | |
| insert into t2 values (1,1), (3,3);
 | |
| 
 | |
| select a, b, (a,b) in (select a, min(b) from t2 group by a) Z from t1;
 | |
| 
 | |
| insert into t2 values (NULL,4);
 | |
| select a, b, (a,b) in (select a, min(b) from t2 group by a) Z from t1;
 | |
| 
 | |
| drop table t1,t2;
 | |
| 
 |