diff options
-rw-r--r-- | mysql-test/r/subselect2.result | 19 | ||||
-rw-r--r-- | mysql-test/t/subselect2.test | 19 | ||||
-rw-r--r-- | sql/sql_select.cc | 32 |
3 files changed, 66 insertions, 4 deletions
diff --git a/mysql-test/r/subselect2.result b/mysql-test/r/subselect2.result index 41c445329cb..a7689c37a0a 100644 --- a/mysql-test/r/subselect2.result +++ b/mysql-test/r/subselect2.result @@ -179,4 +179,23 @@ pk a b SET optimizer_switch=@tmp_optimizer_switch; DROP VIEW v1; DROP TABLE t1,t2,t3; +# +# MDEV-567: Wrong result from a query with correlated subquery if ICP is allowed +# +CREATE TABLE t1 (a int, b int, INDEX idx(a)); +INSERT INTO t1 VALUES (9,0), (7,1), (1,9), (7,3), (2,1); +CREATE TABLE t2 (a int, b int, INDEX idx(a)); +INSERT INTO t2 VALUES (2,1), (6,4), (7,6), (9,4); +CREATE TABLE t3 (a int, b int); +INSERT INTO t3 VALUES (1,0), (1,1), (1,3); +SELECT * FROM t3 +WHERE a = (SELECT COUNT(DISTINCT t2.b) FROM t1, t2 +WHERE t1.a = t2.a AND t2.a BETWEEN 7 AND 9 +AND t3.b = t1.b +GROUP BY t1.b); +a b +1 0 +1 1 +1 3 +DROP TABLE t1, t2, t3; set optimizer_switch=@subselect2_test_tmp; diff --git a/mysql-test/t/subselect2.test b/mysql-test/t/subselect2.test index 8d2939bdb53..75cf842fbdb 100644 --- a/mysql-test/t/subselect2.test +++ b/mysql-test/t/subselect2.test @@ -203,5 +203,24 @@ SET optimizer_switch=@tmp_optimizer_switch; DROP VIEW v1; DROP TABLE t1,t2,t3; +--echo # +--echo # MDEV-567: Wrong result from a query with correlated subquery if ICP is allowed +--echo # +CREATE TABLE t1 (a int, b int, INDEX idx(a)); +INSERT INTO t1 VALUES (9,0), (7,1), (1,9), (7,3), (2,1); + +CREATE TABLE t2 (a int, b int, INDEX idx(a)); +INSERT INTO t2 VALUES (2,1), (6,4), (7,6), (9,4); + +CREATE TABLE t3 (a int, b int); +INSERT INTO t3 VALUES (1,0), (1,1), (1,3); + +SELECT * FROM t3 + WHERE a = (SELECT COUNT(DISTINCT t2.b) FROM t1, t2 + WHERE t1.a = t2.a AND t2.a BETWEEN 7 AND 9 + AND t3.b = t1.b + GROUP BY t1.b); +DROP TABLE t1, t2, t3; + set optimizer_switch=@subselect2_test_tmp; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 5f2e97d57c1..438cec61c6d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -18687,6 +18687,14 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, /* Currently ORDER BY ... LIMIT is not supported in subqueries. */ DBUG_ASSERT(join->group_list || !join->is_in_subquery()); + /* + If we have a select->quick object that is created outside of + create_sort_index() and this is part of a subquery that + potentially can be executed multiple times then we should not + delete the quick object on exit from this function. + */ + bool keep_quick= select && select->quick && join->join_tab_save; + /* When there is SQL_BIG_RESULT do not sort using index for GROUP BY, and thus force sorting on disk unless a group min-max optimization @@ -18738,6 +18746,7 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, get_quick_select_for_ref(thd, table, &tab->ref, tab->found_records)))) goto err; + DBUG_ASSERT(!keep_quick); } } @@ -18769,10 +18778,25 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, tablesort_result_cache= table->sort.io_cache; table->sort.io_cache= NULL; - - select->cleanup(); // filesort did select - table->quick_keys.clear_all(); // as far as we cleanup select->quick - table->intersect_keys.clear_all(); + /* + If a quick object was created outside of create_sort_index() + that might be reused, then do not call select->cleanup() since + it will delete the quick object. + */ + if (!keep_quick) + { + select->cleanup(); + /* + The select object should now be ready for the next use. If it + is re-used then there exists a backup copy of this join tab + which has the pointer to it. The join tab will be restored in + JOIN::reset(). So here we just delete the pointer to it. + */ + tab->select= NULL; + // If we deleted the quick select object we need to clear quick_keys + table->quick_keys.clear_all(); + } + // Restore the output resultset table->sort.io_cache= tablesort_result_cache; } tab->set_select_cond(NULL, __LINE__); |