summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2017-05-16 08:24:42 -0700
committerIgor Babaev <igor@askmonty.org>2017-05-16 08:25:32 -0700
commit934b8312817d4e8e0387fae0bd9cca3ffafbc7de (patch)
treefc345e6a7eba88deccc425cac4dda35030f33d2a
parent2e1428c0b552f2c80aa4b27edaaab8bde8966b22 (diff)
downloadmariadb-git-934b8312817d4e8e0387fae0bd9cca3ffafbc7de.tar.gz
Fixed the bug mdev-7791.
When an IN subquery predicate was converted to a semi-join that were materialized and the result of the materialization happened to be the last in the execution plan then any conjunctive condition with RAND() turned out to be lost. Fixed by attaching this condition to the last top base table.
-rw-r--r--mysql-test/r/subselect_sj2_mat.result23
-rw-r--r--mysql-test/t/subselect_sj2_mat.test20
-rw-r--r--sql/sql_select.cc18
3 files changed, 56 insertions, 5 deletions
diff --git a/mysql-test/r/subselect_sj2_mat.result b/mysql-test/r/subselect_sj2_mat.result
index 4e75aee24a2..202e6cc4b9e 100644
--- a/mysql-test/r/subselect_sj2_mat.result
+++ b/mysql-test/r/subselect_sj2_mat.result
@@ -1556,3 +1556,26 @@ i1
DROP TABLE t1,t2,t3;
set join_cache_level= @save_join_cache_level;
set optimizer_switch=@save_optimizer_switch;
+#
+# mdev-7791: materialization of a semi-join subquery +
+# RAND() in WHERE
+# (materialized table is accessed last)
+#
+set @save_optimizer_switch=@@optimizer_switch;
+set optimizer_switch='materialization=on';
+create table t1(i int);
+insert into t1 values (1), (2), (3), (7), (9), (10);
+create table t2(i int);
+insert into t2 values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+select * from t1 where (rand() < 0) and i in (select i from t2);
+i
+explain extended
+select * from t1 where (rand() < 0) and i in (select i from t2);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 10 100.00
+Warnings:
+Note 1003 select `test`.`t1`.`i` AS `i` from `test`.`t1` semi join (`test`.`t2`) where ((rand() < 0))
+drop table t1,t2;
+set optimizer_switch=@save_optimizer_switch;
diff --git a/mysql-test/t/subselect_sj2_mat.test b/mysql-test/t/subselect_sj2_mat.test
index 61d9b09edff..0f2892ae2dc 100644
--- a/mysql-test/t/subselect_sj2_mat.test
+++ b/mysql-test/t/subselect_sj2_mat.test
@@ -263,3 +263,23 @@ DROP TABLE t1,t2,t3;
set join_cache_level= @save_join_cache_level;
set optimizer_switch=@save_optimizer_switch;
+--echo #
+--echo # mdev-7791: materialization of a semi-join subquery +
+--echo # RAND() in WHERE
+--echo # (materialized table is accessed last)
+--echo #
+
+set @save_optimizer_switch=@@optimizer_switch;
+set optimizer_switch='materialization=on';
+
+create table t1(i int);
+insert into t1 values (1), (2), (3), (7), (9), (10);
+create table t2(i int);
+insert into t2 values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+
+select * from t1 where (rand() < 0) and i in (select i from t2);
+explain extended
+select * from t1 where (rand() < 0) and i in (select i from t2);
+
+drop table t1,t2;
+set optimizer_switch=@save_optimizer_switch;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 09e6ece7807..bad57aeac87 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -8761,12 +8761,20 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
/*
Step #2: Extract WHERE/ON parts
*/
+ uint i;
+ for (i= join->top_join_tab_count - 1; i >= join->const_tables; i--)
+ {
+ if (!join->join_tab[i].bush_children)
+ break;
+ }
+ uint last_top_base_tab_idx= i;
+
table_map save_used_tables= 0;
used_tables=((select->const_tables=join->const_table_map) |
OUTER_REF_TABLE_BIT | RAND_TABLE_BIT);
JOIN_TAB *tab;
table_map current_map;
- uint i= join->const_tables;
+ i= join->const_tables;
for (tab= first_depth_first_tab(join); tab;
tab= next_depth_first_tab(join, tab), i++)
{
@@ -8804,7 +8812,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
Following force including random expression in last table condition.
It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5
*/
- if (tab == join->join_tab + join->top_join_tab_count - 1)
+ if (tab == join->join_tab + last_top_base_tab_idx)
current_map|= RAND_TABLE_BIT;
used_tables|=current_map;
@@ -8843,10 +8851,10 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
save_used_tables= 0;
}
else
- {
- tmp= make_cond_for_table(thd, cond, used_tables, current_map, i,
+ {
+ tmp= make_cond_for_table(thd, cond, used_tables, current_map, i,
FALSE, FALSE);
- }
+ }
/* Add conditions added by add_not_null_conds(). */
if (tab->select_cond)
add_cond_and_fix(thd, &tmp, tab->select_cond);