summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2011-11-21 09:06:35 -0800
committerIgor Babaev <igor@askmonty.org>2011-11-21 09:06:35 -0800
commitb2e5a3f603a1b8d06af9ec6579749de836bd8f47 (patch)
tree41494af268a8f9b045d3fd88ccae49b20e01b4f4
parent0693f4d9168eeee399f9d636c9ba81981e484daf (diff)
downloadmariadb-git-b2e5a3f603a1b8d06af9ec6579749de836bd8f47.tar.gz
Fixed LP bug #887496.
This bug in the function Loose_scan_opt::check_ref_access_part1 could lead to choosing an invalid execution plan employing a loose scan access to a semi-join table even in the cases when such access could not be used at all. This could result in wrong answers for some queries with IN subqueries.
-rw-r--r--mysql-test/r/subselect_mat_cost_bugs.result4
-rw-r--r--mysql-test/r/subselect_sj.result33
-rw-r--r--mysql-test/r/subselect_sj_jcl6.result33
-rw-r--r--mysql-test/t/subselect_sj.test30
-rw-r--r--sql/opt_subselect.h2
5 files changed, 99 insertions, 3 deletions
diff --git a/mysql-test/r/subselect_mat_cost_bugs.result b/mysql-test/r/subselect_mat_cost_bugs.result
index 62038178012..1ae88ad5bce 100644
--- a/mysql-test/r/subselect_mat_cost_bugs.result
+++ b/mysql-test/r/subselect_mat_cost_bugs.result
@@ -346,8 +346,8 @@ WHERE t4.a >= t3.b
AND a = SOME (SELECT b FROM t5));
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 t5 index c c 10 NULL 2 Using where; Using index; LooseScan
-2 DEPENDENT SUBQUERY t4 eq_ref PRIMARY PRIMARY 4 test.t5.b 1 Using index condition; Using where
+2 DEPENDENT SUBQUERY t5 index c c 10 NULL 2 Using where; Using index; Start temporary
+2 DEPENDENT SUBQUERY t4 eq_ref PRIMARY PRIMARY 4 test.t5.b 1 Using index condition; Using where; End temporary
SELECT *
FROM t3
WHERE t3.b > ALL (
diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result
index c372d0fe0bf..25dd3cfc092 100644
--- a/mysql-test/r/subselect_sj.result
+++ b/mysql-test/r/subselect_sj.result
@@ -2050,4 +2050,37 @@ a
3
set optimizer_switch= @tmp_otimizer_switch;
drop table t1,t2;
+#
+# Bug #887496: semijoin with IN equality for the second part of an index
+#
+CREATE TABLE t1 (a int);
+INSERT INTO t1 VALUES (9), (0), (8), (5);
+CREATE TABLE t2 (a int, b varchar(1), INDEX idx (b,a));
+INSERT INTO t2 VALUES (5,'r'), (5,'z');
+CREATE TABLE t3 (a int, b varchar(1), INDEX idx (b,a));
+INSERT INTO t3 VALUES (5,'r'), (5,'z');
+set @tmp_otimizer_switch= @@optimizer_switch;
+SET SESSION optimizer_switch='semijoin=on,firstmatch=on';
+SET SESSION optimizer_switch='loosescan=off';
+EXPLAIN
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 index idx idx 9 NULL 2 Using where; Using index; Start temporary
+1 PRIMARY t3 ref idx idx 4 test.t2.b 1 Using index
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; End temporary; Using join buffer (flat, BNL join)
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+a
+5
+SET SESSION optimizer_switch='loosescan=on';
+EXPLAIN
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 index idx idx 9 NULL 2 Using where; Using index; Start temporary
+1 PRIMARY t3 ref idx idx 4 test.t2.b 1 Using index
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; End temporary; Using join buffer (flat, BNL join)
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+a
+5
+set optimizer_switch= @tmp_otimizer_switch;
+DROP TABLE t1,t2,t3;
set optimizer_switch=@subselect_sj_tmp;
diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result
index 6c4f5d30ade..73dcdaf37d0 100644
--- a/mysql-test/r/subselect_sj_jcl6.result
+++ b/mysql-test/r/subselect_sj_jcl6.result
@@ -2061,6 +2061,39 @@ a
3
set optimizer_switch= @tmp_otimizer_switch;
drop table t1,t2;
+#
+# Bug #887496: semijoin with IN equality for the second part of an index
+#
+CREATE TABLE t1 (a int);
+INSERT INTO t1 VALUES (9), (0), (8), (5);
+CREATE TABLE t2 (a int, b varchar(1), INDEX idx (b,a));
+INSERT INTO t2 VALUES (5,'r'), (5,'z');
+CREATE TABLE t3 (a int, b varchar(1), INDEX idx (b,a));
+INSERT INTO t3 VALUES (5,'r'), (5,'z');
+set @tmp_otimizer_switch= @@optimizer_switch;
+SET SESSION optimizer_switch='semijoin=on,firstmatch=on';
+SET SESSION optimizer_switch='loosescan=off';
+EXPLAIN
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 index idx idx 9 NULL 2 Using where; Using index; Start temporary
+1 PRIMARY t3 ref idx idx 4 test.t2.b 1 Using index
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; End temporary; Using join buffer (flat, BNL join)
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+a
+5
+SET SESSION optimizer_switch='loosescan=on';
+EXPLAIN
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 index idx idx 9 NULL 2 Using where; Using index; Start temporary
+1 PRIMARY t3 ref idx idx 4 test.t2.b 1 Using index
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; End temporary; Using join buffer (flat, BNL join)
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+a
+5
+set optimizer_switch= @tmp_otimizer_switch;
+DROP TABLE t1,t2,t3;
set optimizer_switch=@subselect_sj_tmp;
#
# BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off
diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test
index 740289ffcc8..5ae968742aa 100644
--- a/mysql-test/t/subselect_sj.test
+++ b/mysql-test/t/subselect_sj.test
@@ -1880,5 +1880,35 @@ set optimizer_switch= @tmp_otimizer_switch;
drop table t1,t2;
+--echo #
+--echo # Bug #887496: semijoin with IN equality for the second part of an index
+--echo #
+
+CREATE TABLE t1 (a int);
+INSERT INTO t1 VALUES (9), (0), (8), (5);
+
+CREATE TABLE t2 (a int, b varchar(1), INDEX idx (b,a));
+INSERT INTO t2 VALUES (5,'r'), (5,'z');
+
+CREATE TABLE t3 (a int, b varchar(1), INDEX idx (b,a));
+INSERT INTO t3 VALUES (5,'r'), (5,'z');
+
+set @tmp_otimizer_switch= @@optimizer_switch;
+SET SESSION optimizer_switch='semijoin=on,firstmatch=on';
+
+SET SESSION optimizer_switch='loosescan=off';
+EXPLAIN
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+
+SET SESSION optimizer_switch='loosescan=on';
+EXPLAIN
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+
+set optimizer_switch= @tmp_otimizer_switch;
+
+DROP TABLE t1,t2,t3;
+
# The following command must be the last one the file
set optimizer_switch=@subselect_sj_tmp;
diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h
index 571fcbaa935..823b09a1f73 100644
--- a/sql/opt_subselect.h
+++ b/sql/opt_subselect.h
@@ -170,7 +170,7 @@ public:
PREV_BITS(ulonglong, s->emb_sj_nest->sj_in_exprs) && // (2)
(PREV_BITS(key_part_map, max_loose_keypart+1) & // (3)
(found_part | loose_scan_keyparts)) == // (3)
- (found_part | loose_scan_keyparts) && // (3)
+ PREV_BITS(key_part_map, max_loose_keypart+1) && // (3)
!key_uses_partial_cols(s->table, key))
{
/* Ok, can use the strategy */