maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #02449
bzr commit into file:///home/tsk/mprog/src/5.3-mwl68-merge.base-mwl68/ branch (timour:2766)
#At file:///home/tsk/mprog/src/5.3-mwl68-merge.base-mwl68/ based on revid:timour@xxxxxxxxxxxx-20100309101406-xygkt2sgftvjvevg
2766 timour@xxxxxxxxxxxx 2010-03-09 [merge]
MWL#68 Subquery optimization: Efficient NOT IN execution with NULLs
Automerge with 5.3-subqueries
modified:
mysql-test/r/join_cache.result
mysql-test/r/subselect_sj.result
mysql-test/r/subselect_sj2.result
mysql-test/r/subselect_sj2_jcl6.result
mysql-test/r/subselect_sj_jcl6.result
mysql-test/suite/pbxt/r/group_min_max.result
mysql-test/suite/pbxt/r/subselect.result
mysql-test/t/join_cache.test
mysql-test/t/subselect_sj.test
mysql-test/t/subselect_sj2.test
mysql-test/t/subselect_sj_jcl6.test
sql/item.cc
sql/opt_subselect.cc
sql/sql_join_cache.cc
sql/sql_select.cc
sql/sql_select.h
=== modified file 'mysql-test/r/join_cache.result'
--- a/mysql-test/r/join_cache.result 2010-02-11 21:59:32 +0000
+++ b/mysql-test/r/join_cache.result 2010-03-06 19:14:55 +0000
@@ -4142,3 +4142,46 @@ c1 c2 c1 c2 LENGTH(t2.c1) LENGTH(t2.c2)
2 2 tt uu 2 2
set join_cache_level=default;
DROP TABLE t1,t2;
+#
+# Bug #51092: linked join buffer is used for a 3-way cross join query
+# that selects only records of the first table
+#
+create table t1 (a int, b int);
+insert into t1 values (1,1),(2,2);
+create table t2 (a int, b int);
+insert into t2 values (1,1),(2,2);
+create table t3 (a int, b int);
+insert into t3 values (1,1),(2,2);
+explain select t1.* from t1,t2,t3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Using join buffer
+1 SIMPLE t3 ALL NULL NULL NULL NULL 2 Using join buffer
+select t1.* from t1,t2,t3;
+a b
+1 1
+2 2
+1 1
+2 2
+1 1
+2 2
+1 1
+2 2
+set join_cache_level=2;
+explain select t1.* from t1,t2,t3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Using join buffer
+1 SIMPLE t3 ALL NULL NULL NULL NULL 2 Using join buffer
+select t1.* from t1,t2,t3;
+a b
+1 1
+2 2
+1 1
+2 2
+1 1
+2 2
+1 1
+2 2
+set join_cache_level=default;
+drop table t1,t2,t3;
=== modified file 'mysql-test/r/subselect_sj.result'
--- a/mysql-test/r/subselect_sj.result 2010-02-21 07:53:12 +0000
+++ b/mysql-test/r/subselect_sj.result 2010-02-24 11:33:42 +0000
@@ -824,3 +824,50 @@ a
3
2
drop table t1, t2, t3;
+#
+# Bug#49198 Wrong result for second call of procedure
+# with view in subselect.
+#
+CREATE TABLE t1 (t1field integer, primary key (t1field));
+CREATE TABLE t2 (t2field integer, primary key (t2field));
+CREATE TABLE t3 (t3field integer, primary key (t3field));
+CREATE VIEW v2 AS SELECT * FROM t2;
+CREATE VIEW v3 AS SELECT * FROM t3;
+INSERT INTO t1 VALUES(1),(2);
+INSERT INTO t2 VALUES(1),(2);
+INSERT INTO t3 VALUES(1),(2);
+PREPARE stmt FROM
+"
+SELECT t1field
+FROM t1
+WHERE t1field IN (SELECT * FROM v2);
+";
+EXECUTE stmt;
+t1field
+1
+2
+EXECUTE stmt;
+t1field
+1
+2
+PREPARE stmt FROM
+"
+EXPLAIN
+SELECT t1field
+FROM t1
+WHERE t1field IN (SELECT * FROM v2)
+ AND t1field IN (SELECT * FROM v3)
+";
+EXECUTE stmt;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 index PRIMARY PRIMARY 4 NULL 2 Using index
+1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t1.t1field 1 Using index
+1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t1.t1field 1 Using index
+EXECUTE stmt;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 2 Using index
+1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.t1field 1 Using index
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.t1field 1 Using index
+DROP TABLE t1, t2, t3;
+DROP VIEW v2, v3;
+# End of Bug#49198
=== modified file 'mysql-test/r/subselect_sj2.result'
--- a/mysql-test/r/subselect_sj2.result 2010-02-17 10:47:55 +0000
+++ b/mysql-test/r/subselect_sj2.result 2010-03-07 15:41:45 +0000
@@ -264,8 +264,8 @@ explain select *
from t0 where a in
(select t2.a+t3.a from t1 left join (t2 join t3) on t2.a=t1.a and t3.a=t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t0 ALL NULL NULL NULL NULL 10
-1 PRIMARY t1 index NULL a 5 NULL 10 Using index; Start temporary; Using join buffer
+1 PRIMARY t0 ALL NULL NULL NULL NULL 10 Start temporary
+1 PRIMARY t1 index NULL a 5 NULL 10 Using index; Using join buffer
1 PRIMARY t2 ref a a 5 test.t1.a 1 Using index
1 PRIMARY t3 ref a a 5 test.t1.a 1 Using where; Using index; End temporary
drop table t0, t1,t2,t3;
=== modified file 'mysql-test/r/subselect_sj2_jcl6.result'
--- a/mysql-test/r/subselect_sj2_jcl6.result 2010-02-17 10:47:55 +0000
+++ b/mysql-test/r/subselect_sj2_jcl6.result 2010-03-07 15:41:45 +0000
@@ -268,8 +268,8 @@ explain select *
from t0 where a in
(select t2.a+t3.a from t1 left join (t2 join t3) on t2.a=t1.a and t3.a=t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t0 ALL NULL NULL NULL NULL 10
-1 PRIMARY t1 index NULL a 5 NULL 10 Using index; Start temporary; Using join buffer
+1 PRIMARY t0 ALL NULL NULL NULL NULL 10 Start temporary
+1 PRIMARY t1 index NULL a 5 NULL 10 Using index; Using join buffer
1 PRIMARY t2 ref a a 5 test.t1.a 1 Using index
1 PRIMARY t3 ref a a 5 test.t1.a 1 Using where; Using index; End temporary
drop table t0, t1,t2,t3;
@@ -421,20 +421,23 @@ explain extended select * from t0
where t0.a in ( select t1.a from t1,t2 where t2.a=t0.a and
t1.b=t2.b);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t0 ALL NULL NULL NULL NULL 5 100.00
-1 PRIMARY t1 ref a a 5 test.t0.a 1 100.00 Start temporary; Using join buffer
+1 PRIMARY t0 ALL NULL NULL NULL NULL 5 100.00 Start temporary
+1 PRIMARY t1 ref a a 5 test.t0.a 1 100.00 Using join buffer
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t0.a 1 100.00 Using where; End temporary; Using join buffer
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`.`b` = `test`.`t1`.`b`) and (`test`.`t1`.`a` = `test`.`t0`.`a`) and (`test`.`t2`.`a` = `test`.`t0`.`a`))
update t1 set a=3, b=11 where a=4;
update t2 set b=11 where a=3;
-
+# Not anymore:
# The following query gives wrong result due to Bug#49129
select * from t0 where t0.a in
(select t1.a from t1, t2 where t2.a=t0.a and t1.b=t2.b);
a
0
+1
+2
+3
drop table t0, t1, t2;
CREATE TABLE t1 (
id int(11) NOT NULL,
@@ -713,9 +716,9 @@ c2 in (select 1 from t3, t2) and
c1 in (select convert(c6,char(1)) from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where
-1 PRIMARY t2 ALL NULL NULL NULL NULL 1
-1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where
-1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch(t2)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using join buffer
+1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where; Using join buffer
+1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch(t2); Using join buffer
drop table t2, t3;
set join_cache_level=default;
show variables like 'join_cache_level';
=== modified file 'mysql-test/r/subselect_sj_jcl6.result'
--- a/mysql-test/r/subselect_sj_jcl6.result 2010-02-21 07:53:12 +0000
+++ b/mysql-test/r/subselect_sj_jcl6.result 2010-03-07 15:41:45 +0000
@@ -374,8 +374,8 @@ WHERE PNUM IN
(SELECT PNUM FROM PROJ));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY STAFF ALL NULL NULL NULL NULL 5
-1 PRIMARY PROJ ALL NULL NULL NULL NULL 6
-1 PRIMARY WORKS ALL NULL NULL NULL NULL 12 Using where; FirstMatch(STAFF)
+1 PRIMARY PROJ ALL NULL NULL NULL NULL 6 Using join buffer
+1 PRIMARY WORKS ALL NULL NULL NULL NULL 12 Using where; FirstMatch(STAFF); Using join buffer
SELECT EMPNUM, EMPNAME
FROM STAFF
WHERE EMPNUM IN
@@ -828,6 +828,84 @@ a
3
2
drop table t1, t2, t3;
+#
+# Bug#49198 Wrong result for second call of procedure
+# with view in subselect.
+#
+CREATE TABLE t1 (t1field integer, primary key (t1field));
+CREATE TABLE t2 (t2field integer, primary key (t2field));
+CREATE TABLE t3 (t3field integer, primary key (t3field));
+CREATE VIEW v2 AS SELECT * FROM t2;
+CREATE VIEW v3 AS SELECT * FROM t3;
+INSERT INTO t1 VALUES(1),(2);
+INSERT INTO t2 VALUES(1),(2);
+INSERT INTO t3 VALUES(1),(2);
+PREPARE stmt FROM
+"
+SELECT t1field
+FROM t1
+WHERE t1field IN (SELECT * FROM v2);
+";
+EXECUTE stmt;
+t1field
+1
+2
+EXECUTE stmt;
+t1field
+1
+2
+PREPARE stmt FROM
+"
+EXPLAIN
+SELECT t1field
+FROM t1
+WHERE t1field IN (SELECT * FROM v2)
+ AND t1field IN (SELECT * FROM v3)
+";
+EXECUTE stmt;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 index PRIMARY PRIMARY 4 NULL 2 Using index
+1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t1.t1field 1 Using index
+1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t1.t1field 1 Using index
+EXECUTE stmt;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 2 Using index
+1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.t1field 1 Using index
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.t1field 1 Using index
+DROP TABLE t1, t2, t3;
+DROP VIEW v2, v3;
+# End of Bug#49198
+#
+# BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off
+#
+CREATE TABLE t0 (a INT);
+INSERT INTO t0 VALUES (0),(1),(2),(3),(4);
+CREATE TABLE t1 (a INT, b INT, KEY(a));
+INSERT INTO t1 SELECT a, a from t0;
+CREATE TABLE t2 (a INT, b INT, PRIMARY KEY(a));
+INSERT INTO t2 SELECT * FROM t1;
+UPDATE t1 SET a=3, b=11 WHERE a=4;
+UPDATE t2 SET b=11 WHERE a=3;
+set @save_optimizer_switch=@@optimizer_switch;
+set optimizer_switch='firstmatch=off';
+The following should use a join order of t0,t1,t2, with DuplicateElimination:
+explain
+SELECT * FROM t0 WHERE t0.a IN
+(SELECT t1.a FROM t1, t2 WHERE t2.a=t0.a AND t1.b=t2.b);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t0 ALL NULL NULL NULL NULL 5 Start temporary
+1 PRIMARY t1 ref a a 5 test.t0.a 1 Using join buffer
+1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t0.a 1 Using where; End temporary; Using join buffer
+SELECT * FROM t0 WHERE t0.a IN
+(SELECT t1.a FROM t1, t2 WHERE t2.a=t0.a AND t1.b=t2.b);
+a
+0
+1
+2
+3
+set optimizer_switch=@save_optimizer_switch;
+drop table t0, t1, t2;
+# End
set join_cache_level=default;
show variables like 'join_cache_level';
Variable_name Value
=== modified file 'mysql-test/suite/pbxt/r/group_min_max.result'
--- a/mysql-test/suite/pbxt/r/group_min_max.result 2009-08-17 15:57:58 +0000
+++ b/mysql-test/suite/pbxt/r/group_min_max.result 2010-02-23 09:22:02 +0000
@@ -2257,7 +2257,7 @@ EXPLAIN SELECT 1 FROM t1 AS t1_outer WHE
a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer index NULL a 10 NULL 15 Using where; Using index
-2 DEPENDENT SUBQUERY t1 index NULL a 10 NULL 1 Using index
+2 SUBQUERY t1 index NULL a 10 NULL 15 Using index
EXPLAIN SELECT 1 FROM t1 AS t1_outer GROUP BY a HAVING
a > (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
=== modified file 'mysql-test/suite/pbxt/r/subselect.result'
--- a/mysql-test/suite/pbxt/r/subselect.result 2009-12-16 09:28:51 +0000
+++ b/mysql-test/suite/pbxt/r/subselect.result 2010-02-23 09:22:02 +0000
@@ -1293,31 +1293,31 @@ a
4
explain extended select * from t2 where t2.a in (select a from t1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 100.00 Using where; Using index
-2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index
+1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 100.00 Using index
+1 PRIMARY t1 index PRIMARY PRIMARY 4 NULL 4 75.00 Using where; Using index; Using join buffer
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<primary_index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on PRIMARY)))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t2` where (`test`.`t1`.`a` = `test`.`t2`.`a`)
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
2
4
explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 100.00 Using where; Using index
-2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using where
+1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 100.00 Using index
+1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 4 75.00 Using where; Using join buffer
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<primary_index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on PRIMARY where ((`test`.`t1`.`b` <> 30) and (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`)))))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`a` = `test`.`t2`.`a`) and (`test`.`t1`.`b` <> 30))
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
a
2
3
explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 100.00 Using where; Using index
-2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 func 1 100.00
-2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 100.00 Using index
+1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 100.00 Using index
+1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 4 75.00 Using where; Using join buffer
+1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 100.00 Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(select 1 AS `Not_used` from `test`.`t1` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t1`.`b`) and (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`))))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t3` join `test`.`t2` where ((`test`.`t1`.`a` = `test`.`t2`.`a`) and (`test`.`t3`.`a` = `test`.`t1`.`b`))
drop table t1, t2, t3;
create table t1 (a int, b int, index a (a,b));
create table t2 (a int, index a (a));
@@ -1332,31 +1332,31 @@ a
4
explain extended select * from t2 where t2.a in (select a from t1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 index NULL a 5 NULL 4 100.00 Using where; Using index
-2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 1 100.00 Using index
+1 PRIMARY t2 index a a 5 NULL 4 100.00 Using index
+1 PRIMARY t1 ref a a 5 test.t2.a 1 100.00 Using index; FirstMatch(t2)
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a)))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) where (`test`.`t1`.`a` = `test`.`t2`.`a`)
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
2
4
explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 index NULL a 5 NULL 4 100.00 Using where; Using index
-2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 1 100.00 Using index; Using where
+1 PRIMARY t2 index a a 5 NULL 4 100.00 Using index
+1 PRIMARY t1 ref a a 5 test.t2.a 1 100.00 Using where; Using index; FirstMatch(t2)
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a where ((`test`.`t1`.`b` <> 30) and (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`)))))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) where ((`test`.`t1`.`a` = `test`.`t2`.`a`) and (`test`.`t1`.`b` <> 30))
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
a
2
3
explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 index NULL a 5 NULL 4 100.00 Using where; Using index
-2 DEPENDENT SUBQUERY t1 ref a a 5 func 1 100.00 Using index
-2 DEPENDENT SUBQUERY t3 ref a a 5 test.t1.b 1 100.00 Using index
+1 PRIMARY t2 index a a 5 NULL 4 100.00 Using index
+1 PRIMARY t1 ref a a 5 test.t2.a 1 100.00 Using index
+1 PRIMARY t3 ref a a 5 test.t1.b 1 100.00 Using index; FirstMatch(t2)
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(select 1 AS `Not_used` from `test`.`t1` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t1`.`b`) and (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`))))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1` join `test`.`t3`) where ((`test`.`t1`.`a` = `test`.`t2`.`a`) and (`test`.`t3`.`a` = `test`.`t1`.`b`))
insert into t1 values (3,31);
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
@@ -1369,10 +1369,10 @@ a
4
explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 index NULL a 5 NULL 4 100.00 Using where; Using index
-2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 1 100.00 Using index; Using where
+1 PRIMARY t2 index a a 5 NULL 4 100.00 Using index
+1 PRIMARY t1 ref a a 5 test.t2.a 1 100.00 Using where; Using index; FirstMatch(t2)
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a where ((`test`.`t1`.`b` <> 30) and (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`)))))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) where ((`test`.`t1`.`a` = `test`.`t2`.`a`) and (`test`.`t1`.`b` <> 30))
drop table t1, t2, t3;
create table t1 (a int, b int);
create table t2 (a int, b int);
@@ -2823,10 +2823,10 @@ Warnings:
Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where ((`test`.`t2`.`flag` = '0') and trigcond(((<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) or isnull(`test`.`t2`.`one`))) and trigcond(((<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`) or isnull(`test`.`t2`.`two`)))) having (trigcond(<is_not_null_test>(`test`.`t2`.`one`)) and trigcond(<is_not_null_test>(`test`.`t2`.`two`))))) AS `test` from `test`.`t1`
explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 9 100.00 Using where; FirstMatch(t1)
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where ((`test`.`t2`.`flag` = 'N') and (<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) and (<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`))))
+Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`two` = `test`.`t1`.`two`) and (`test`.`t2`.`one` = `test`.`t1`.`one`) and (`test`.`t2`.`flag` = 'N'))
explain extended SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = '0' group by one,two) as 'test' from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
@@ -3412,7 +3412,7 @@ EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
ALTER TABLE t1 ADD INDEX(a);
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
a b
@@ -3423,7 +3423,7 @@ EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
-2 DEPENDENT SUBQUERY t1 index NULL a 8 NULL 1 Using filesort
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
DROP TABLE t1;
create table t1( f1 int,f2 int);
insert into t1 values (1,1),(2,2);
@@ -4213,8 +4213,8 @@ CREATE INDEX I1 ON t1 (a);
CREATE INDEX I2 ON t1 (b);
EXPLAIN SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1);
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 t1 index_subquery I1 I1 2 func 1 Using index; Using where
+1 PRIMARY t1 index I1 I1 2 NULL 2 Using index; LooseScan
+1 PRIMARY t1 ref I2 I2 13 test.t1.a 1 Using where
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1);
a b
CREATE TABLE t2 (a VARCHAR(1), b VARCHAR(10));
@@ -4223,15 +4223,15 @@ CREATE INDEX I1 ON t2 (a);
CREATE INDEX I2 ON t2 (b);
EXPLAIN SELECT a,b FROM t2 WHERE b IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
-2 DEPENDENT SUBQUERY t2 index_subquery I1 I1 4 func 1 Using index; Using where
+1 PRIMARY t2 index I1 I1 4 NULL 2 Using index; LooseScan
+1 PRIMARY t2 ref I2 I2 13 test.t2.a 1 Using where
SELECT a,b FROM t2 WHERE b IN (SELECT a FROM t2);
a b
EXPLAIN
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1 WHERE LENGTH(a)<500);
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 t1 index_subquery I1 I1 2 func 1 Using index; Using where
+1 PRIMARY t1 index I1 I1 2 NULL 2 Using where; Using index; LooseScan
+1 PRIMARY t1 ref I2 I2 13 test.t1.a 1 Using where
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1 WHERE LENGTH(a)<500);
a b
DROP TABLE t1,t2;
=== modified file 'mysql-test/t/join_cache.test'
--- a/mysql-test/t/join_cache.test 2009-12-21 02:26:15 +0000
+++ b/mysql-test/t/join_cache.test 2010-03-06 19:14:55 +0000
@@ -1823,3 +1823,27 @@ SELECT t1.*, t2.*, LENGTH(t2.c1), LENGTH
set join_cache_level=default;
DROP TABLE t1,t2;
+
+--echo #
+--echo # Bug #51092: linked join buffer is used for a 3-way cross join query
+--echo # that selects only records of the first table
+--echo #
+
+create table t1 (a int, b int);
+insert into t1 values (1,1),(2,2);
+create table t2 (a int, b int);
+insert into t2 values (1,1),(2,2);
+create table t3 (a int, b int);
+insert into t3 values (1,1),(2,2);
+
+explain select t1.* from t1,t2,t3;
+select t1.* from t1,t2,t3;
+
+set join_cache_level=2;
+
+explain select t1.* from t1,t2,t3;
+select t1.* from t1,t2,t3;
+
+set join_cache_level=default;
+
+drop table t1,t2,t3;
=== modified file 'mysql-test/t/subselect_sj.test'
--- a/mysql-test/t/subselect_sj.test 2010-02-21 07:53:12 +0000
+++ b/mysql-test/t/subselect_sj.test 2010-02-24 11:33:42 +0000
@@ -728,3 +728,45 @@ where a in (select c from t2 where d >=
drop table t1, t2, t3;
+--echo #
+--echo # Bug#49198 Wrong result for second call of procedure
+--echo # with view in subselect.
+--echo #
+
+CREATE TABLE t1 (t1field integer, primary key (t1field));
+CREATE TABLE t2 (t2field integer, primary key (t2field));
+CREATE TABLE t3 (t3field integer, primary key (t3field));
+
+CREATE VIEW v2 AS SELECT * FROM t2;
+CREATE VIEW v3 AS SELECT * FROM t3;
+
+INSERT INTO t1 VALUES(1),(2);
+INSERT INTO t2 VALUES(1),(2);
+INSERT INTO t3 VALUES(1),(2);
+
+PREPARE stmt FROM
+"
+SELECT t1field
+FROM t1
+WHERE t1field IN (SELECT * FROM v2);
+";
+
+EXECUTE stmt;
+EXECUTE stmt;
+
+PREPARE stmt FROM
+"
+EXPLAIN
+SELECT t1field
+FROM t1
+WHERE t1field IN (SELECT * FROM v2)
+ AND t1field IN (SELECT * FROM v3)
+";
+
+EXECUTE stmt;
+EXECUTE stmt;
+
+DROP TABLE t1, t2, t3;
+DROP VIEW v2, v3;
+
+--echo # End of Bug#49198
=== modified file 'mysql-test/t/subselect_sj2.test'
--- a/mysql-test/t/subselect_sj2.test 2010-01-17 14:51:10 +0000
+++ b/mysql-test/t/subselect_sj2.test 2010-03-07 15:41:45 +0000
@@ -583,7 +583,7 @@ update t2 set b=11 where a=3;
if (`select @@join_cache_level=6`)
{
- --echo
+ --echo # Not anymore:
--echo # The following query gives wrong result due to Bug#49129
}
select * from t0 where t0.a in
=== modified file 'mysql-test/t/subselect_sj_jcl6.test'
--- a/mysql-test/t/subselect_sj_jcl6.test 2010-01-17 14:51:10 +0000
+++ b/mysql-test/t/subselect_sj_jcl6.test 2010-03-07 15:41:45 +0000
@@ -7,5 +7,33 @@ show variables like 'join_cache_level';
--source t/subselect_sj.test
+--echo #
+--echo # BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off
+--echo #
+CREATE TABLE t0 (a INT);
+INSERT INTO t0 VALUES (0),(1),(2),(3),(4);
+CREATE TABLE t1 (a INT, b INT, KEY(a));
+INSERT INTO t1 SELECT a, a from t0;
+CREATE TABLE t2 (a INT, b INT, PRIMARY KEY(a));
+INSERT INTO t2 SELECT * FROM t1;
+UPDATE t1 SET a=3, b=11 WHERE a=4;
+UPDATE t2 SET b=11 WHERE a=3;
+
+set @save_optimizer_switch=@@optimizer_switch;
+set optimizer_switch='firstmatch=off';
+
+--echo The following should use a join order of t0,t1,t2, with DuplicateElimination:
+explain
+SELECT * FROM t0 WHERE t0.a IN
+ (SELECT t1.a FROM t1, t2 WHERE t2.a=t0.a AND t1.b=t2.b);
+
+SELECT * FROM t0 WHERE t0.a IN
+ (SELECT t1.a FROM t1, t2 WHERE t2.a=t0.a AND t1.b=t2.b);
+
+set optimizer_switch=@save_optimizer_switch;
+drop table t0, t1, t2;
+
+--echo # End
+
set join_cache_level=default;
show variables like 'join_cache_level';
=== modified file 'sql/item.cc'
--- a/sql/item.cc 2010-02-21 06:32:23 +0000
+++ b/sql/item.cc 2010-02-24 11:33:42 +0000
@@ -6491,11 +6491,9 @@ void Item_outer_ref::fix_after_pullout(s
void Item_ref::fix_after_pullout(st_select_lex *new_parent, Item **refptr)
{
+ (*ref)->fix_after_pullout(new_parent, ref);
if (depended_from == new_parent)
- {
- (*ref)->fix_after_pullout(new_parent, ref);
depended_from= NULL;
- }
}
=== modified file 'sql/opt_subselect.cc'
--- a/sql/opt_subselect.cc 2010-02-19 21:55:57 +0000
+++ b/sql/opt_subselect.cc 2010-03-09 10:36:15 +0000
@@ -531,7 +531,6 @@ static bool replace_where_subcondition(J
*expr= new_cond;
if (do_fix_fields)
new_cond->fix_fields(join->thd, expr);
- join->select_lex->where= *expr;
return FALSE;
}
@@ -3031,10 +3030,24 @@ int setup_semijoin_dups_elimination(JOIN
forwards, but do not destroy other duplicate elimination methods.
*/
uint first_table= i;
+ uint join_cache_level= join->thd->variables.join_cache_level;
for (uint j= i; j < i + pos->n_sj_tables; j++)
{
- if (join->best_positions[j].use_join_buffer && j <= no_jbuf_after)
+ /*
+ When we'll properly take join buffering into account during
+ join optimization, the below check should be changed to
+ "if (join->best_positions[j].use_join_buffer &&
+ j <= no_jbuf_after)".
+ For now, use a rough criteria:
+ */
+ JOIN_TAB *js_tab=join->join_tab + j;
+ if (j != join->const_tables && js_tab->use_quick != 2 &&
+ j <= no_jbuf_after &&
+ ((js_tab->type == JT_ALL && join_cache_level != 0) ||
+ (join_cache_level > 4 && (tab->type == JT_REF ||
+ tab->type == JT_EQ_REF))))
{
+ /* Looks like we'll be using join buffer */
first_table= join->const_tables;
break;
}
@@ -3112,7 +3125,12 @@ int setup_semijoin_dups_elimination(JOIN
JOIN_TAB *j, *jump_to= tab-1;
for (j= tab; j != tab + pos->n_sj_tables; j++)
{
- if (!tab->emb_sj_nest)
+ /*
+ NOTE: this loop probably doesn't do the right thing for the case
+ where FirstMatch's duplicate-generating range is interleaved with
+ "unrelated" tables (as specified in WL#3750, section 2.2).
+ */
+ if (!j->emb_sj_nest)
jump_to= tab;
else
{
=== modified file 'sql/sql_join_cache.cc'
--- a/sql/sql_join_cache.cc 2010-02-15 21:53:06 +0000
+++ b/sql/sql_join_cache.cc 2010-03-07 15:41:45 +0000
@@ -31,6 +31,8 @@
#include "sql_select.h"
#include "opt_subselect.h"
+#define NO_MORE_RECORDS_IN_BUFFER (uint)(-1)
+
/*****************************************************************************
* Join cache module
@@ -407,8 +409,10 @@ void JOIN_CACHE::set_constants()
However at this moment we don't know whether we have referenced fields for
the cache or not. Later when a referenced field is registered for the cache
we adjust the value of the flag 'with_length'.
- */
- with_length= is_key_access() || with_match_flag;
+ */
+ with_length= is_key_access() ||
+ join_tab->is_inner_table_of_semi_join_with_first_match() ||
+ join_tab->is_inner_table_of_outer_join();
/*
At this moment we don't know yet the value of 'referenced_fields',
but in any case it can't be greater than the value of 'fields'.
@@ -604,7 +608,12 @@ int JOIN_CACHE_BKA::init()
copy_end= cache->field_descr+cache->fields;
for (copy= cache->field_descr+cache->flag_fields; copy < copy_end; copy++)
{
- if (copy->field->table == tab->table &&
+ /*
+ (1) - when we store rowids for DuplicateWeedout, they have
+ copy->field==NULL
+ */
+ if (copy->field && // (1)
+ copy->field->table == tab->table &&
bitmap_is_set(key_read_set, copy->field->field_index))
{
*copy_ptr++= copy;
@@ -1235,7 +1244,7 @@ bool JOIN_CACHE::get_record()
prev_rec_ptr= prev_cache->get_rec_ref(pos);
}
curr_rec_pos= pos;
- if (!(res= read_all_record_fields() == 0))
+ if (!(res= read_all_record_fields() == NO_MORE_RECORDS_IN_BUFFER))
{
pos+= referenced_fields*size_of_fld_ofs;
if (prev_cache)
@@ -1304,7 +1313,7 @@ bool JOIN_CACHE::get_match_flag_by_pos(u
uchar *prev_rec_ptr= prev_cache->get_rec_ref(rec_ptr);
return prev_cache->get_match_flag_by_pos(prev_rec_ptr);
}
- DBUG_ASSERT(1);
+ DBUG_ASSERT(0);
return FALSE;
}
@@ -1324,7 +1333,8 @@ bool JOIN_CACHE::get_match_flag_by_pos(u
read data.
RETURN
- length of the data read from the join buffer
+ (-1) - if there is no more records in the join buffer
+ length of the data read from the join buffer - otherwise
*/
uint JOIN_CACHE::read_all_record_fields()
@@ -1332,7 +1342,7 @@ uint JOIN_CACHE::read_all_record_fields(
uchar *init_pos= pos;
if (pos > last_rec_pos || !records)
- return 0;
+ return NO_MORE_RECORDS_IN_BUFFER;
/* First match flag, read null bitmaps and null_row flag for each table */
read_flag_fields();
@@ -1538,12 +1548,12 @@ bool JOIN_CACHE::read_referenced_field(C
bool JOIN_CACHE::skip_record_if_match()
{
- DBUG_ASSERT(with_match_flag && with_length);
+ DBUG_ASSERT(with_length);
uint offset= size_of_rec_len;
if (prev_cache)
offset+= prev_cache->get_size_of_rec_offset();
/* Check whether the match flag is on */
- if (test(*(pos+offset)))
+ if (get_match_flag_by_pos(pos+offset))
{
pos+= size_of_rec_len + get_rec_length(pos);
return TRUE;
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2010-02-19 21:55:57 +0000
+++ b/sql/sql_select.cc 2010-03-09 10:36:15 +0000
@@ -5635,7 +5635,11 @@ void calc_used_field_length(THD *thd, JO
uint blob_length=(uint) (join_tab->table->file->stats.mean_rec_length-
(join_tab->table->s->reclength-rec_length));
rec_length+=(uint) max(4,blob_length);
- }
+ }
+ /*
+ psergey-todo: why we don't count here rowid that we might need to store
+ when using DuplicateElimination?
+ */
join_tab->used_fields=fields;
join_tab->used_fieldlength=rec_length;
join_tab->used_blobs=blobs;
@@ -6355,10 +6359,17 @@ make_outerjoin_info(JOIN *join)
}
if (!tab->first_inner)
tab->first_inner= nested_join->first_nested;
+ if (tab->table->reginfo.not_exists_optimize)
+ tab->first_inner->table->reginfo.not_exists_optimize= 1;
if (++nested_join->counter < nested_join->n_tables)
break;
/* Table tab is the last inner table for nested join. */
nested_join->first_nested->last_inner= tab;
+ if (tab->first_inner->table->reginfo.not_exists_optimize)
+ {
+ for (JOIN_TAB *join_tab= tab->first_inner; join_tab <= tab; join_tab++)
+ join_tab->table->reginfo.not_exists_optimize= 1;
+ }
}
}
DBUG_VOID_RETURN;
@@ -7112,18 +7123,14 @@ uint check_join_cache_usage(JOIN_TAB *ta
if (tab->use_quick == 2)
goto no_join_cache;
/*
- Use join cache with FirstMatch semi-join strategy only when semi-join
- contains only one table.
- */
- if (tab->is_inner_table_of_semi_join_with_first_match() &&
- !tab->is_single_inner_of_semi_join_with_first_match())
- goto no_join_cache;
- /*
Non-linked join buffers can't guarantee one match
*/
- if (force_unlinked_cache &&
- (tab->is_inner_table_of_outer_join() &&
- !tab->is_single_inner_of_outer_join()))
+ if (force_unlinked_cache &&
+ (!tab->type == JT_ALL || cache_level <= 4) &&
+ ((tab->is_inner_table_of_semi_join_with_first_match() &&
+ !tab->is_single_inner_of_semi_join_with_first_match()) ||
+ (tab->is_inner_table_of_outer_join() &&
+ !tab->is_single_inner_of_outer_join())))
goto no_join_cache;
/*
=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h 2010-02-15 21:53:06 +0000
+++ b/sql/sql_select.h 2010-03-05 18:54:48 +0000
@@ -321,8 +321,8 @@ typedef struct st_join_table {
}
bool check_only_first_match()
{
- return last_sj_inner_tab == this ||
- (first_inner && first_inner->last_inner == this &&
+ return is_inner_table_of_semi_join_with_first_match() ||
+ (is_inner_table_of_outer_join() &&
table->reginfo.not_exists_optimize);
}
bool is_last_inner_table()
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: timour@xxxxxxxxxxxx-20100309103615-dzmm6xt7ye5xfs25
# target_branch: file:///home/tsk/mprog/src/5.3-mwl68-merge.base-\
# mwl68/
# testament_sha1: 0f4ddb7e490a4ea925fe2a336498bdf3beb76a71
# timestamp: 2010-03-09 12:36:23 +0200
# source_branch: file:///home/tsk/mprog/src/5.3-subqueries/
# base_revision_id: timour@xxxxxxxxxxxx-20100309101406-\
# xygkt2sgftvjvevg
#
# Begin bundle
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