summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/subselect2.result19
-rw-r--r--mysql-test/t/subselect2.test19
-rw-r--r--sql/sql_select.cc32
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__);