From f40f0ff679471948a6366ddfad9377b83abdf345 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 4 Oct 2011 23:57:46 +0300 Subject: [PATCH] Fix bug lp:856152 Analysis: The cause of the bug was that the method subselect_rowid_merge_engine::partial_match() was not designed for re-execution within the same query. Specifically, it didn't cleanup the bitmap of matching keys after completion. The test query requires double execution of the IN predicate because it first checks the predicate as a constant condition. The second execution during regular execution used the bitmap of matching keys produced by the first execution instead of starting with a clean one. Solution: Cleanup the bitmap of matching keys at the end of the partial matching procedure. --- mysql-test/r/subselect_partial_match.result | 24 +++++++++++++++++++++ mysql-test/t/subselect_partial_match.test | 20 +++++++++++++++++ sql/item_subselect.cc | 2 ++ 3 files changed, 46 insertions(+) diff --git a/mysql-test/r/subselect_partial_match.result b/mysql-test/r/subselect_partial_match.result index 85aa96df714..1b39381b42b 100644 --- a/mysql-test/r/subselect_partial_match.result +++ b/mysql-test/r/subselect_partial_match.result @@ -348,4 +348,28 @@ c 0 0 drop table t1, t2; +# +# LP BUG#856152 Wrong result with NOT IN subquery and partial_match_rowid_merge +# +CREATE TABLE t1 ( f1 integer NOT NULL , f2 integer) ; +INSERT INTO t1 VALUES (3,3),(48,NULL),(49,1); +CREATE TABLE t2 ( f3 int) ; +INSERT INTO t2 VALUES (5); +set @@optimizer_switch='in_to_exists=off,materialization=on,partial_match_rowid_merge=on,partial_match_table_scan=off'; +EXPLAIN SELECT * FROM t2 WHERE ( 3 , 1 ) NOT IN ( SELECT f1 , f2 FROM t1 ); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 system NULL NULL NULL NULL 1 +2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 +SELECT * FROM t2 WHERE ( 3 , 1 ) NOT IN ( SELECT f1 , f2 FROM t1 ); +f3 +5 +set @@optimizer_switch='in_to_exists=on,materialization=off'; +EXPLAIN SELECT * FROM t2 WHERE ( 3 , 1 ) NOT IN ( SELECT f1 , f2 FROM t1 ); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 system NULL NULL NULL NULL 1 +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where +SELECT * FROM t2 WHERE ( 3 , 1 ) NOT IN ( SELECT f1 , f2 FROM t1 ); +f3 +5 +drop table t1, t2; set @@optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/t/subselect_partial_match.test b/mysql-test/t/subselect_partial_match.test index 8d1fbd9b8d7..cb25656e4fc 100644 --- a/mysql-test/t/subselect_partial_match.test +++ b/mysql-test/t/subselect_partial_match.test @@ -354,4 +354,24 @@ SELECT * FROM t1 WHERE (6, 4 ) NOT IN (SELECT a, b FROM t2); drop table t1, t2; +--echo # +--echo # LP BUG#856152 Wrong result with NOT IN subquery and partial_match_rowid_merge +--echo # + +CREATE TABLE t1 ( f1 integer NOT NULL , f2 integer) ; +INSERT INTO t1 VALUES (3,3),(48,NULL),(49,1); + +CREATE TABLE t2 ( f3 int) ; +INSERT INTO t2 VALUES (5); + +set @@optimizer_switch='in_to_exists=off,materialization=on,partial_match_rowid_merge=on,partial_match_table_scan=off'; +EXPLAIN SELECT * FROM t2 WHERE ( 3 , 1 ) NOT IN ( SELECT f1 , f2 FROM t1 ); +SELECT * FROM t2 WHERE ( 3 , 1 ) NOT IN ( SELECT f1 , f2 FROM t1 ); + +set @@optimizer_switch='in_to_exists=on,materialization=off'; +EXPLAIN SELECT * FROM t2 WHERE ( 3 , 1 ) NOT IN ( SELECT f1 , f2 FROM t1 ); +SELECT * FROM t2 WHERE ( 3 , 1 ) NOT IN ( SELECT f1 , f2 FROM t1 ); + +drop table t1, t2; + set @@optimizer_switch=@save_optimizer_switch; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 324cdabf7f6..a20e4c4e708 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -5674,6 +5674,8 @@ bool subselect_rowid_merge_engine::partial_match() DBUG_ASSERT(FALSE); end: + if (!has_covering_null_columns) + bitmap_clear_all(&matching_keys); queue_remove_all(&pq); tmp_table->file->ha_rnd_end(); return res;