summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2013-11-13 07:40:46 +0400
committerSergey Petrunya <psergey@askmonty.org>2013-11-13 07:40:46 +0400
commit229aa1d4bfe32cc77d6e87dcdd31eecf78b4c9e2 (patch)
tree86b1b035f5281bb0d946275276e616cafd4dc666
parentea78785b8b6a27ed0d8e71e64d058e331f08ed36 (diff)
downloadmariadb-git-229aa1d4bfe32cc77d6e87dcdd31eecf78b4c9e2.tar.gz
MDEV-5056: Wrong result (extra rows) with materialization+semijoin, IN subqueries
Apply fix suggested by Igor: - When eliminate_item_equal() generates pair-wise equalities from a multi-equality, do generate a "bridge" equality between the first field inside SJM nest and the field that's first in the overall multi-equality.
-rw-r--r--mysql-test/r/subselect_mat.result21
-rw-r--r--mysql-test/r/subselect_sj_mat.result21
-rw-r--r--mysql-test/t/subselect_sj_mat.test26
-rw-r--r--sql/sql_select.cc6
4 files changed, 72 insertions, 2 deletions
diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result
index e1c9df3b00b..62ec0955e88 100644
--- a/mysql-test/r/subselect_mat.result
+++ b/mysql-test/r/subselect_mat.result
@@ -2038,6 +2038,27 @@ SELECT * FROM t1 WHERE 8 IN (SELECT MIN(pk) FROM t1) AND (pk = a OR pk = b);
pk a b
DROP TABLE t1;
# End of 5.3 tests
+#
+# MDEV-5056: Wrong result (extra rows) with materialization+semijoin, IN subqueries
+#
+set @tmp_mdev5056=@@join_cache_level;
+SET join_cache_level = 2;
+CREATE TABLE t1 ( c1 VARCHAR(2), c2 VARCHAR(2), INDEX(c1) ) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+('JP','OM'),('VA','JP'),('CA','ML'),('ML','EG'),('DK','CA'),
+('DK','QA'),('YE','PL'),('TR','ZW'),('DK','SK'),('SK','DK'),
+('RO','ML'),('ML','BG'),('BG','ZW'),('ZW','GE'),('GE','JP'),
+('PL','EG'),('QA','YE'),('WF','DK'),('DK','JP'),('EG','OM');
+CREATE TABLE t2 ( c3 VARCHAR(2), c4 VARCHAR(2) ) ENGINE=MyISAM;
+INSERT INTO t2 VALUES ('CA','ML'),('IN','HU'),('HU','IN');
+SELECT * FROM t1 AS alias1, t1 AS alias2
+WHERE ( alias2.c2, alias1.c1 ) IN ( SELECT c4, c3 FROM t2 ) AND alias1.c1 IN ( SELECT c2 FROM t1 );
+c1 c2 c1 c2
+CA ML CA ML
+CA ML RO ML
+DROP TABLE t1,t2;
+set join_cache_level=@tmp_mdev5056;
+# End of 5.5 tests
set @subselect_mat_test_optimizer_switch_value=null;
set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';
set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on';
diff --git a/mysql-test/r/subselect_sj_mat.result b/mysql-test/r/subselect_sj_mat.result
index bcdd82b790c..38ab07882de 100644
--- a/mysql-test/r/subselect_sj_mat.result
+++ b/mysql-test/r/subselect_sj_mat.result
@@ -2078,3 +2078,24 @@ SELECT * FROM t1 WHERE 8 IN (SELECT MIN(pk) FROM t1) AND (pk = a OR pk = b);
pk a b
DROP TABLE t1;
# End of 5.3 tests
+#
+# MDEV-5056: Wrong result (extra rows) with materialization+semijoin, IN subqueries
+#
+set @tmp_mdev5056=@@join_cache_level;
+SET join_cache_level = 2;
+CREATE TABLE t1 ( c1 VARCHAR(2), c2 VARCHAR(2), INDEX(c1) ) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+('JP','OM'),('VA','JP'),('CA','ML'),('ML','EG'),('DK','CA'),
+('DK','QA'),('YE','PL'),('TR','ZW'),('DK','SK'),('SK','DK'),
+('RO','ML'),('ML','BG'),('BG','ZW'),('ZW','GE'),('GE','JP'),
+('PL','EG'),('QA','YE'),('WF','DK'),('DK','JP'),('EG','OM');
+CREATE TABLE t2 ( c3 VARCHAR(2), c4 VARCHAR(2) ) ENGINE=MyISAM;
+INSERT INTO t2 VALUES ('CA','ML'),('IN','HU'),('HU','IN');
+SELECT * FROM t1 AS alias1, t1 AS alias2
+WHERE ( alias2.c2, alias1.c1 ) IN ( SELECT c4, c3 FROM t2 ) AND alias1.c1 IN ( SELECT c2 FROM t1 );
+c1 c2 c1 c2
+CA ML CA ML
+CA ML RO ML
+DROP TABLE t1,t2;
+set join_cache_level=@tmp_mdev5056;
+# End of 5.5 tests
diff --git a/mysql-test/t/subselect_sj_mat.test b/mysql-test/t/subselect_sj_mat.test
index e9226b8884f..58831c4ffb3 100644
--- a/mysql-test/t/subselect_sj_mat.test
+++ b/mysql-test/t/subselect_sj_mat.test
@@ -1726,3 +1726,29 @@ SELECT * FROM t1 WHERE 8 IN (SELECT MIN(pk) FROM t1) AND (pk = a OR pk = b);
DROP TABLE t1;
--echo # End of 5.3 tests
+
+
+--echo #
+--echo # MDEV-5056: Wrong result (extra rows) with materialization+semijoin, IN subqueries
+--echo #
+set @tmp_mdev5056=@@join_cache_level;
+SET join_cache_level = 2;
+
+CREATE TABLE t1 ( c1 VARCHAR(2), c2 VARCHAR(2), INDEX(c1) ) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+('JP','OM'),('VA','JP'),('CA','ML'),('ML','EG'),('DK','CA'),
+('DK','QA'),('YE','PL'),('TR','ZW'),('DK','SK'),('SK','DK'),
+('RO','ML'),('ML','BG'),('BG','ZW'),('ZW','GE'),('GE','JP'),
+('PL','EG'),('QA','YE'),('WF','DK'),('DK','JP'),('EG','OM');
+
+CREATE TABLE t2 ( c3 VARCHAR(2), c4 VARCHAR(2) ) ENGINE=MyISAM;
+INSERT INTO t2 VALUES ('CA','ML'),('IN','HU'),('HU','IN');
+
+SELECT * FROM t1 AS alias1, t1 AS alias2
+WHERE ( alias2.c2, alias1.c1 ) IN ( SELECT c4, c3 FROM t2 ) AND alias1.c1 IN ( SELECT c2 FROM t1 );
+
+DROP TABLE t1,t2;
+set join_cache_level=@tmp_mdev5056;
+
+--echo # End of 5.5 tests
+
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ad73faee553..cd81b41d0ec 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -12295,12 +12295,14 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
/*
If we're inside an SJM-nest (current_sjm!=NULL), and the multi-equality
doesn't include a constant, we should produce equality with the first
- of the equals in this SJM.
+ of the equal items in this SJM (except for the first element inside the
+ SJM. For that, we produce the equality with the "head" item).
In other cases, get the "head" item, which is either first of the
equals on top level, or the constant.
*/
- Item *head_item= (!item_const && current_sjm)? current_sjm_head: head;
+ Item *head_item= (!item_const && current_sjm &&
+ current_sjm_head != field_item) ? current_sjm_head: head;
Item *head_real_item= head_item->real_item();
if (head_real_item->type() == Item::FIELD_ITEM)
head_item= head_real_item;