diff options
author | Igor Babaev <igor@askmonty.org> | 2011-11-21 09:06:35 -0800 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2011-11-21 09:06:35 -0800 |
commit | b2e5a3f603a1b8d06af9ec6579749de836bd8f47 (patch) | |
tree | 41494af268a8f9b045d3fd88ccae49b20e01b4f4 | |
parent | 0693f4d9168eeee399f9d636c9ba81981e484daf (diff) | |
download | mariadb-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.result | 4 | ||||
-rw-r--r-- | mysql-test/r/subselect_sj.result | 33 | ||||
-rw-r--r-- | mysql-test/r/subselect_sj_jcl6.result | 33 | ||||
-rw-r--r-- | mysql-test/t/subselect_sj.test | 30 | ||||
-rw-r--r-- | sql/opt_subselect.h | 2 |
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 */ |