From acc161d3633c9d655389622c5758832f1dd4bc78 Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Fri, 8 Apr 2011 02:12:03 +0400 Subject: [PATCH] BUG#752992: Wrong results for a subquery with 'semijoin=on' - Let advance_sj_state() save the value of JOIN::cur_dups_producing_tables in POSITION::prefix_dups_producing_tables, and restore_sj_state() restore it. --- mysql-test/r/subselect.result | 22 ++++++++++++++++++++++ mysql-test/r/subselect3.result | 6 +++--- mysql-test/r/subselect3_jcl6.result | 6 +++--- mysql-test/r/subselect_no_mat.result | 22 ++++++++++++++++++++++ mysql-test/r/subselect_no_opts.result | 22 ++++++++++++++++++++++ mysql-test/r/subselect_no_semijoin.result | 22 ++++++++++++++++++++++ mysql-test/t/subselect.test | 17 +++++++++++++++++ mysql-test/t/subselect3.test | 4 ++-- sql/opt_subselect.cc | 3 +++ sql/sql_select.h | 2 ++ 10 files changed, 118 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index fd67750c5a0..53f38141f66 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -5046,3 +5046,25 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where 2 DEPENDENT SUBQUERY t2 ref idx idx 5 test.t1.a 2 Using index DROP TABLE t1,t2; +# +# BUG#752992: Wrong results for a subquery with 'semijoin=on' +# +CREATE TABLE t1 (pk INTEGER PRIMARY KEY, i INTEGER NOT NULL); +INSERT INTO t1 VALUES (11,0); +INSERT INTO t1 VALUES (12,5); +INSERT INTO t1 VALUES (15,0); +CREATE TABLE t2 (pk INTEGER PRIMARY KEY, i INTEGER NOT NULL); +INSERT INTO t2 VALUES (11,1); +INSERT INTO t2 VALUES (12,2); +INSERT INTO t2 VALUES (15,4); +EXPLAIN SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON 1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 3 Start temporary +1 PRIMARY t2 index NULL PRIMARY 4 NULL 3 Using index; Using join buffer (flat, BNL join) +1 PRIMARY it eq_ref PRIMARY PRIMARY 4 test.t1.pk 1 Using index; End temporary +SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON 1); +pk i +11 0 +12 5 +15 0 +DROP table t1,t2; diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result index 896607f54db..3d7cbdd9ff7 100644 --- a/mysql-test/r/subselect3.result +++ b/mysql-test/r/subselect3.result @@ -1142,15 +1142,15 @@ create table t1 (a int) as select * from t0 where a < 5; set @save_max_heap_table_size=@@max_heap_table_size; set @@optimizer_switch='firstmatch=off,materialization=off'; set @@max_heap_table_size= 16384; -explain select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E); +explain select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E where a+1 < 10000 + A.a + B.a +C.a+D.a); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY E ALL NULL NULL NULL NULL 5 Start temporary 1 PRIMARY A ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join) 1 PRIMARY B ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join) -1 PRIMARY C ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join) +1 PRIMARY C ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join) 1 PRIMARY D ALL NULL NULL NULL NULL 10 Using where; End temporary; Using join buffer (flat, BNL join) flush status; -select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E); +select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E where a+1 < 10000 + A.a + B.a +C.a+D.a); count(*) 5000 show status like 'Created_tmp_disk_tables'; diff --git a/mysql-test/r/subselect3_jcl6.result b/mysql-test/r/subselect3_jcl6.result index a41d0dfe4b9..b8a30ce1722 100644 --- a/mysql-test/r/subselect3_jcl6.result +++ b/mysql-test/r/subselect3_jcl6.result @@ -1149,15 +1149,15 @@ create table t1 (a int) as select * from t0 where a < 5; set @save_max_heap_table_size=@@max_heap_table_size; set @@optimizer_switch='firstmatch=off,materialization=off'; set @@max_heap_table_size= 16384; -explain select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E); +explain select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E where a+1 < 10000 + A.a + B.a +C.a+D.a); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY E ALL NULL NULL NULL NULL 5 Using where; Start temporary 1 PRIMARY A ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join) 1 PRIMARY B ALL NULL NULL NULL NULL 10 Using join buffer (incremental, BNL join) -1 PRIMARY C ALL NULL NULL NULL NULL 10 Using join buffer (incremental, BNL join) +1 PRIMARY C ALL NULL NULL NULL NULL 10 Using where; Using join buffer (incremental, BNL join) 1 PRIMARY D hash_ALL NULL #hash#$hj 5 test.E.a 10 Using where; End temporary; Using join buffer (incremental, BNLH join) flush status; -select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E); +select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E where a+1 < 10000 + A.a + B.a +C.a+D.a); count(*) 5000 show status like 'Created_tmp_disk_tables'; diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result index 0c837a5a90a..7ab96bad552 100644 --- a/mysql-test/r/subselect_no_mat.result +++ b/mysql-test/r/subselect_no_mat.result @@ -5048,6 +5048,28 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where 2 DEPENDENT SUBQUERY t2 ref idx idx 5 test.t1.a 2 Using index DROP TABLE t1,t2; +# +# BUG#752992: Wrong results for a subquery with 'semijoin=on' +# +CREATE TABLE t1 (pk INTEGER PRIMARY KEY, i INTEGER NOT NULL); +INSERT INTO t1 VALUES (11,0); +INSERT INTO t1 VALUES (12,5); +INSERT INTO t1 VALUES (15,0); +CREATE TABLE t2 (pk INTEGER PRIMARY KEY, i INTEGER NOT NULL); +INSERT INTO t2 VALUES (11,1); +INSERT INTO t2 VALUES (12,2); +INSERT INTO t2 VALUES (15,4); +EXPLAIN SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON 1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 3 Start temporary +1 PRIMARY t2 index NULL PRIMARY 4 NULL 3 Using index; Using join buffer (flat, BNL join) +1 PRIMARY it eq_ref PRIMARY PRIMARY 4 test.t1.pk 1 Using index; End temporary +SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON 1); +pk i +11 0 +12 5 +15 0 +DROP table t1,t2; set optimizer_switch=default; select @@optimizer_switch like '%materialization=on%'; @@optimizer_switch like '%materialization=on%' diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result index 8af0ffc3a88..6f923c0e626 100644 --- a/mysql-test/r/subselect_no_opts.result +++ b/mysql-test/r/subselect_no_opts.result @@ -5045,4 +5045,26 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where 2 DEPENDENT SUBQUERY t2 ref idx idx 5 test.t1.a 2 Using index DROP TABLE t1,t2; +# +# BUG#752992: Wrong results for a subquery with 'semijoin=on' +# +CREATE TABLE t1 (pk INTEGER PRIMARY KEY, i INTEGER NOT NULL); +INSERT INTO t1 VALUES (11,0); +INSERT INTO t1 VALUES (12,5); +INSERT INTO t1 VALUES (15,0); +CREATE TABLE t2 (pk INTEGER PRIMARY KEY, i INTEGER NOT NULL); +INSERT INTO t2 VALUES (11,1); +INSERT INTO t2 VALUES (12,2); +INSERT INTO t2 VALUES (15,4); +EXPLAIN SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON 1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where +2 DEPENDENT SUBQUERY t2 index NULL PRIMARY 4 NULL 3 Using index +2 DEPENDENT SUBQUERY it eq_ref PRIMARY PRIMARY 4 func 1 Using index +SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON 1); +pk i +11 0 +12 5 +15 0 +DROP table t1,t2; set optimizer_switch=default; diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result index a0524812da5..889735b1dc2 100644 --- a/mysql-test/r/subselect_no_semijoin.result +++ b/mysql-test/r/subselect_no_semijoin.result @@ -5045,4 +5045,26 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where 2 DEPENDENT SUBQUERY t2 ref idx idx 5 test.t1.a 2 Using index DROP TABLE t1,t2; +# +# BUG#752992: Wrong results for a subquery with 'semijoin=on' +# +CREATE TABLE t1 (pk INTEGER PRIMARY KEY, i INTEGER NOT NULL); +INSERT INTO t1 VALUES (11,0); +INSERT INTO t1 VALUES (12,5); +INSERT INTO t1 VALUES (15,0); +CREATE TABLE t2 (pk INTEGER PRIMARY KEY, i INTEGER NOT NULL); +INSERT INTO t2 VALUES (11,1); +INSERT INTO t2 VALUES (12,2); +INSERT INTO t2 VALUES (15,4); +EXPLAIN SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON 1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where +2 SUBQUERY t2 index NULL PRIMARY 4 NULL 3 Using index +2 SUBQUERY it index NULL PRIMARY 4 NULL 3 Using index; Using join buffer (flat, BNL join) +SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON 1); +pk i +11 0 +12 5 +15 0 +DROP table t1,t2; set optimizer_switch=default; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 965dfc6072e..2015ab83513 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -4316,3 +4316,20 @@ SELECT * FROM t1 WHERE EXISTS (SELECT a FROM t2 WHERE t2.a = t1.a); DROP TABLE t1,t2; + +--echo # +--echo # BUG#752992: Wrong results for a subquery with 'semijoin=on' +--echo # +CREATE TABLE t1 (pk INTEGER PRIMARY KEY, i INTEGER NOT NULL); +INSERT INTO t1 VALUES (11,0); +INSERT INTO t1 VALUES (12,5); +INSERT INTO t1 VALUES (15,0); +CREATE TABLE t2 (pk INTEGER PRIMARY KEY, i INTEGER NOT NULL); +INSERT INTO t2 VALUES (11,1); +INSERT INTO t2 VALUES (12,2); +INSERT INTO t2 VALUES (15,4); + +EXPLAIN SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON 1); +SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON 1); + +DROP table t1,t2; diff --git a/mysql-test/t/subselect3.test b/mysql-test/t/subselect3.test index 2a5aa1c5429..dc625239e84 100644 --- a/mysql-test/t/subselect3.test +++ b/mysql-test/t/subselect3.test @@ -949,9 +949,9 @@ set @save_max_heap_table_size=@@max_heap_table_size; set @@optimizer_switch='firstmatch=off,materialization=off'; set @@max_heap_table_size= 16384; -explain select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E); +explain select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E where a+1 < 10000 + A.a + B.a +C.a+D.a); flush status; -select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E); +select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E where a+1 < 10000 + A.a + B.a +C.a+D.a); show status like 'Created_tmp_disk_tables'; set @save_max_heap_table_size=@@max_heap_table_size; set @@optimizer_switch=@save_optimizer_switch; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 319704a6e8f..75ff73b81b1 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1861,6 +1861,7 @@ void advance_sj_state(JOIN *join, table_map remaining_tables, } } } + pos->prefix_dups_producing_tables= join->cur_dups_producing_tables; } @@ -1882,6 +1883,8 @@ void restore_prev_sj_state(const table_map remaining_tables, tab->join->cur_sj_inner_tables &= ~emb_sj_nest->sj_inner_tables; } } + POSITION *pos= tab->join->positions + idx; + tab->join->cur_dups_producing_tables= pos->prefix_dups_producing_tables; } diff --git a/sql/sql_select.h b/sql/sql_select.h index b08fa7ff0e6..f0eda9671cb 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -573,6 +573,8 @@ typedef struct st_position semi-join's ON expression so we can correctly account for fanout. */ table_map sjm_scan_need_tables; + + table_map prefix_dups_producing_tables; } POSITION;