diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 3b18a4d0262..85519828b14 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -7204,3 +7204,17 @@ f1 f2 f3 DROP TABLE t1, t2; SET NAMES default; End of 10.1 tests +# +# MDEV-12564: IN TO EXISTS transformation for rows after +# conversion an outer join to inner join +# +CREATE TABLE t ( +pk int PRIMARY KEY, i int NOT NULL, c varchar(8), KEY(c) +) ENGINE=MyISAM; +INSERT INTO t VALUES (1,10,'foo'),(2,20,'bar'); +SELECT * FROM t t1 RIGHT JOIN t t2 ON (t2.pk = t1.pk) +WHERE (t2.i, t2.pk) NOT IN ( SELECT t3.i, t3.i FROM t t3, t t4 ) AND t1.c = 'foo'; +pk i c pk i c +1 10 foo 1 10 foo +DROP TABLE t; +End of 10.2 tests diff --git a/mysql-test/r/subselect_no_exists_to_in.result b/mysql-test/r/subselect_no_exists_to_in.result index ecefc0b8883..deffc030d6b 100644 --- a/mysql-test/r/subselect_no_exists_to_in.result +++ b/mysql-test/r/subselect_no_exists_to_in.result @@ -7204,6 +7204,20 @@ f1 f2 f3 DROP TABLE t1, t2; SET NAMES default; End of 10.1 tests +# +# MDEV-12564: IN TO EXISTS transformation for rows after +# conversion an outer join to inner join +# +CREATE TABLE t ( +pk int PRIMARY KEY, i int NOT NULL, c varchar(8), KEY(c) +) ENGINE=MyISAM; +INSERT INTO t VALUES (1,10,'foo'),(2,20,'bar'); +SELECT * FROM t t1 RIGHT JOIN t t2 ON (t2.pk = t1.pk) +WHERE (t2.i, t2.pk) NOT IN ( SELECT t3.i, t3.i FROM t t3, t t4 ) AND t1.c = 'foo'; +pk i c pk i c +1 10 foo 1 10 foo +DROP TABLE t; +End of 10.2 tests set optimizer_switch=default; select @@optimizer_switch like '%exists_to_in=off%'; @@optimizer_switch like '%exists_to_in=off%' diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result index 49a60546b78..202faf7f522 100644 --- a/mysql-test/r/subselect_no_mat.result +++ b/mysql-test/r/subselect_no_mat.result @@ -7197,6 +7197,20 @@ f1 f2 f3 DROP TABLE t1, t2; SET NAMES default; End of 10.1 tests +# +# MDEV-12564: IN TO EXISTS transformation for rows after +# conversion an outer join to inner join +# +CREATE TABLE t ( +pk int PRIMARY KEY, i int NOT NULL, c varchar(8), KEY(c) +) ENGINE=MyISAM; +INSERT INTO t VALUES (1,10,'foo'),(2,20,'bar'); +SELECT * FROM t t1 RIGHT JOIN t t2 ON (t2.pk = t1.pk) +WHERE (t2.i, t2.pk) NOT IN ( SELECT t3.i, t3.i FROM t t3, t t4 ) AND t1.c = 'foo'; +pk i c pk i c +1 10 foo 1 10 foo +DROP TABLE t; +End of 10.2 tests 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 304a427df6b..294107ef69e 100644 --- a/mysql-test/r/subselect_no_opts.result +++ b/mysql-test/r/subselect_no_opts.result @@ -7195,4 +7195,18 @@ f1 f2 f3 DROP TABLE t1, t2; SET NAMES default; End of 10.1 tests +# +# MDEV-12564: IN TO EXISTS transformation for rows after +# conversion an outer join to inner join +# +CREATE TABLE t ( +pk int PRIMARY KEY, i int NOT NULL, c varchar(8), KEY(c) +) ENGINE=MyISAM; +INSERT INTO t VALUES (1,10,'foo'),(2,20,'bar'); +SELECT * FROM t t1 RIGHT JOIN t t2 ON (t2.pk = t1.pk) +WHERE (t2.i, t2.pk) NOT IN ( SELECT t3.i, t3.i FROM t t3, t t4 ) AND t1.c = 'foo'; +pk i c pk i c +1 10 foo 1 10 foo +DROP TABLE t; +End of 10.2 tests set @optimizer_switch_for_subselect_test=null; diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result index c045be5197c..b9c06cae5bd 100644 --- a/mysql-test/r/subselect_no_scache.result +++ b/mysql-test/r/subselect_no_scache.result @@ -7210,6 +7210,20 @@ f1 f2 f3 DROP TABLE t1, t2; SET NAMES default; End of 10.1 tests +# +# MDEV-12564: IN TO EXISTS transformation for rows after +# conversion an outer join to inner join +# +CREATE TABLE t ( +pk int PRIMARY KEY, i int NOT NULL, c varchar(8), KEY(c) +) ENGINE=MyISAM; +INSERT INTO t VALUES (1,10,'foo'),(2,20,'bar'); +SELECT * FROM t t1 RIGHT JOIN t t2 ON (t2.pk = t1.pk) +WHERE (t2.i, t2.pk) NOT IN ( SELECT t3.i, t3.i FROM t t3, t t4 ) AND t1.c = 'foo'; +pk i c pk i c +1 10 foo 1 10 foo +DROP TABLE t; +End of 10.2 tests set optimizer_switch=default; select @@optimizer_switch like '%subquery_cache=on%'; @@optimizer_switch like '%subquery_cache=on%' diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result index 3440ecbc6c1..e90d70fcc49 100644 --- a/mysql-test/r/subselect_no_semijoin.result +++ b/mysql-test/r/subselect_no_semijoin.result @@ -7195,5 +7195,19 @@ f1 f2 f3 DROP TABLE t1, t2; SET NAMES default; End of 10.1 tests +# +# MDEV-12564: IN TO EXISTS transformation for rows after +# conversion an outer join to inner join +# +CREATE TABLE t ( +pk int PRIMARY KEY, i int NOT NULL, c varchar(8), KEY(c) +) ENGINE=MyISAM; +INSERT INTO t VALUES (1,10,'foo'),(2,20,'bar'); +SELECT * FROM t t1 RIGHT JOIN t t2 ON (t2.pk = t1.pk) +WHERE (t2.i, t2.pk) NOT IN ( SELECT t3.i, t3.i FROM t t3, t t4 ) AND t1.c = 'foo'; +pk i c pk i c +1 10 foo 1 10 foo +DROP TABLE t; +End of 10.2 tests set @optimizer_switch_for_subselect_test=null; set @join_cache_level_for_subselect_test=NULL; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index f2e0adf9d53..282013222de 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -6056,3 +6056,20 @@ DROP TABLE t1, t2; SET NAMES default; --echo End of 10.1 tests + +--echo # +--echo # MDEV-12564: IN TO EXISTS transformation for rows after +--echo # conversion an outer join to inner join +--echo # + +CREATE TABLE t ( +pk int PRIMARY KEY, i int NOT NULL, c varchar(8), KEY(c) +) ENGINE=MyISAM; +INSERT INTO t VALUES (1,10,'foo'),(2,20,'bar'); + +SELECT * FROM t t1 RIGHT JOIN t t2 ON (t2.pk = t1.pk) + WHERE (t2.i, t2.pk) NOT IN ( SELECT t3.i, t3.i FROM t t3, t t4 ) AND t1.c = 'foo'; + +DROP TABLE t; + +--echo End of 10.2 tests diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index d144dddf764..5f15e386b8d 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -2388,7 +2388,8 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, (char *)"")); Item *col_item= new (thd->mem_root) Item_cond_or(thd, item_eq, item_isnull); - if (!abort_on_null && left_expr->element_index(i)->maybe_null) + if (!abort_on_null && left_expr->element_index(i)->maybe_null && + get_cond_guard(i)) { disable_cond_guard_for_const_null_left_expr(i); if (!(col_item= new (thd->mem_root) @@ -2406,7 +2407,8 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, ref_pointer_array[i], (char *)"", (char *)"")); - if (!abort_on_null && left_expr->element_index(i)->maybe_null) + if (!abort_on_null && left_expr->element_index(i)->maybe_null && + get_cond_guard(i) ) { disable_cond_guard_for_const_null_left_expr(i); if (!(item_nnull_test= @@ -2467,7 +2469,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, (char *)"", (char *)"")); item= new (thd->mem_root) Item_cond_or(thd, item, item_isnull); - if (left_expr->element_index(i)->maybe_null) + if (left_expr->element_index(i)->maybe_null && get_cond_guard(i)) { disable_cond_guard_for_const_null_left_expr(i); if (!(item= new (thd->mem_root) @@ -2479,7 +2481,8 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, } *having_item= and_items(thd, *having_item, having_col_item); } - if (!abort_on_null && left_expr->element_index(i)->maybe_null) + if (!abort_on_null && left_expr->element_index(i)->maybe_null && + get_cond_guard(i)) { if (!(item= new (thd->mem_root) Item_func_trig_cond(thd, item, get_cond_guard(i))))