From b850fc66ca72ed9b63cb8b899b64f8c555a525c7 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 7 Jun 2017 22:54:57 -0700 Subject: [PATCH] Fixed the bug mdev-12855. This is actually a legacy bug: SQL_SELECT::test_quick_select() was called with SQL_SELECT::head not set. It looks like that this problem can be reproduced only on queries with ORDER BY that use IN predicates converted to semi-joins. --- mysql-test/r/subselect_sj2_mat.result | 22 ++++++++++++++++++++++ mysql-test/t/subselect_sj2_mat.test | 20 ++++++++++++++++++++ sql/sql_select.cc | 5 ++++- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect_sj2_mat.result b/mysql-test/r/subselect_sj2_mat.result index 202e6cc4b9e..835742a3ff4 100644 --- a/mysql-test/r/subselect_sj2_mat.result +++ b/mysql-test/r/subselect_sj2_mat.result @@ -1579,3 +1579,25 @@ 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; +# +# mdev-12855: materialization of a semi-join subquery + ORDER BY +# +CREATE TABLE t1 (f1 varchar(8), KEY(f1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES ('qux'),('foo'); +CREATE TABLE t2 (f2 varchar(8)) ENGINE=InnoDB; +INSERT INTO t2 VALUES ('bar'),('foo'),('qux'); +SELECT f1 FROM t1 +WHERE f1 IN ( SELECT f2 FROM t2 WHERE f2 > 'bar' ) +HAVING f1 != 'foo' +ORDER BY f1; +f1 +qux +explain SELECT f1 FROM t1 +WHERE f1 IN ( SELECT f2 FROM t2 WHERE f2 > 'bar' ) +HAVING f1 != 'foo' +ORDER BY f1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index f1 f1 11 NULL 2 Using index +1 PRIMARY eq_ref distinct_key distinct_key 11 func 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where +DROP TABLE t1,t2; diff --git a/mysql-test/t/subselect_sj2_mat.test b/mysql-test/t/subselect_sj2_mat.test index 0f2892ae2dc..cfb6c8c2819 100644 --- a/mysql-test/t/subselect_sj2_mat.test +++ b/mysql-test/t/subselect_sj2_mat.test @@ -283,3 +283,23 @@ select * from t1 where (rand() < 0) and i in (select i from t2); drop table t1,t2; set optimizer_switch=@save_optimizer_switch; + +--echo # +--echo # mdev-12855: materialization of a semi-join subquery + ORDER BY +--echo # + +CREATE TABLE t1 (f1 varchar(8), KEY(f1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES ('qux'),('foo'); +CREATE TABLE t2 (f2 varchar(8)) ENGINE=InnoDB; +INSERT INTO t2 VALUES ('bar'),('foo'),('qux'); + +let $q= +SELECT f1 FROM t1 +WHERE f1 IN ( SELECT f2 FROM t2 WHERE f2 > 'bar' ) +HAVING f1 != 'foo' +ORDER BY f1; + +eval $q; +eval explain $q; + +DROP TABLE t1,t2; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f2be17f71d6..720c0a22681 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2759,8 +2759,11 @@ JOIN::exec() if (sort_table_cond) { if (!curr_table->select) + { if (!(curr_table->select= new SQL_SELECT)) DBUG_VOID_RETURN; + curr_table->select->head= curr_table->table; + } if (!curr_table->select->cond) curr_table->select->cond= sort_table_cond; else @@ -2846,7 +2849,7 @@ JOIN::exec() curr_join->select_limit, (select_options & OPTION_FOUND_ROWS ? HA_POS_ERROR : unit->select_limit_cnt), - curr_join->group_list ? TRUE : FALSE)) + curr_join->group_list ? FALSE : TRUE)) DBUG_VOID_RETURN; sortorder= curr_join->sortorder; if (curr_join->const_tables != curr_join->table_count &&