summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgkodinov/kgeorge@magare.gmz <>2007-05-04 10:48:51 +0300
committergkodinov/kgeorge@magare.gmz <>2007-05-04 10:48:51 +0300
commit6badb08ce30c7b96714e7df91b8d7cf008a7bbb9 (patch)
tree063e8080c776ed341a337770fb33a4588175b108
parentb77a85ef22f2b728d185e5e0b0e9d1d5ff5bb940 (diff)
downloadmariadb-git-6badb08ce30c7b96714e7df91b8d7cf008a7bbb9.tar.gz
Bug #27807.
Non-correlated scalar subqueries may get executed in EXPLAIN at the optimization phase if they are part of a right hand sargable expression. If the scalar subquery uses a temp table to materialize its results it will replace the subquery structure from the parser with a simple select from the materialization table. As a result the EXPLAIN will crash as the temporary materialization table is not to be shown in EXPLAIN at all. Fixed by preserving the original query structure right after calling optimize() for scalar subqueries with temp tables executed during EXPLAIN.
-rw-r--r--mysql-test/r/subselect.result8
-rw-r--r--mysql-test/t/subselect.test10
-rw-r--r--sql/item_subselect.cc15
-rw-r--r--sql/sql_select.cc36
-rw-r--r--sql/sql_select.h1
5 files changed, 62 insertions, 8 deletions
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 94075df57b4..2b16242fac2 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -4012,3 +4012,11 @@ WHERE (SELECT COUNT(t0.b) FROM t1 t WHERE t.b>20) GROUP BY a;
ERROR HY000: Invalid use of group function
SET @@sql_mode=default;
DROP TABLE t1;
+CREATE TABLE t1 (a int, b int, KEY (a));
+INSERT INTO t1 VALUES (1,1),(2,1);
+EXPLAIN SELECT 1 FROM t1 WHERE a = (SELECT COUNT(*) FROM t1 GROUP BY b);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ref a a 5 const 1 Using where; Using index
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort
+DROP TABLE t1;
+End of 5.0 tests.
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 482b3e883e6..123a1ef3282 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -2845,3 +2845,13 @@ SELECT a FROM t1 t0
SET @@sql_mode=default;
DROP TABLE t1;
+
+#
+# Bug #27807: Server crash when executing subquery with EXPLAIN
+#
+CREATE TABLE t1 (a int, b int, KEY (a));
+INSERT INTO t1 VALUES (1,1),(2,1);
+EXPLAIN SELECT 1 FROM t1 WHERE a = (SELECT COUNT(*) FROM t1 GROUP BY b);
+DROP TABLE t1;
+
+--echo End of 5.0 tests.
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index b3744d6eb96..a4d07e08473 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1774,6 +1774,21 @@ int subselect_single_select_engine::exec()
thd->lex->current_select= save_select;
DBUG_RETURN(join->error ? join->error : 1);
}
+ if (!select_lex->uncacheable && thd->lex->describe &&
+ !(join->select_options & SELECT_DESCRIBE) &&
+ join->need_tmp && item->const_item())
+ {
+ /*
+ Force join->join_tmp creation, because this subquery will be replaced
+ by a simple select from the materialization temp table by optimize()
+ called by EXPLAIN and we need to preserve the initial query structure
+ so we can display it.
+ */
+ select_lex->uncacheable|= UNCACHEABLE_EXPLAIN;
+ select_lex->master_unit()->uncacheable|= UNCACHEABLE_EXPLAIN;
+ if (join->init_save_join_tab())
+ DBUG_RETURN(1);
+ }
if (item->engine_changed)
{
DBUG_RETURN(1);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 9b27daabc0e..499fed58c4b 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1426,14 +1426,13 @@ JOIN::optimize()
}
}
- if (select_lex->uncacheable && !is_top_level_join())
- {
- /* If this join belongs to an uncacheable subquery */
- if (!(tmp_join= (JOIN*)thd->alloc(sizeof(JOIN))))
- DBUG_RETURN(-1);
- error= 0; // Ensure that tmp_join.error= 0
- restore_tmp();
- }
+ /*
+ If this join belongs to an uncacheable subquery save
+ the original join
+ */
+ if (select_lex->uncacheable && !is_top_level_join() &&
+ init_save_join_tab())
+ DBUG_RETURN(-1);
}
error= 0;
@@ -1495,6 +1494,27 @@ JOIN::reinit()
DBUG_RETURN(0);
}
+/**
+ @brief Save the original join layout
+
+ @details Saves the original join layout so it can be reused in
+ re-execution and for EXPLAIN.
+
+ @return Operation status
+ @retval 0 success.
+ @retval 1 error occurred.
+*/
+
+bool
+JOIN::init_save_join_tab()
+{
+ if (!(tmp_join= (JOIN*)thd->alloc(sizeof(JOIN))))
+ return 1;
+ error= 0; // Ensure that tmp_join.error= 0
+ restore_tmp();
+ return 0;
+}
+
bool
JOIN::save_join_tab()
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 9aa6fc1cfcd..5081366c10b 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -434,6 +434,7 @@ public:
void cleanup(bool full);
void clear();
bool save_join_tab();
+ bool init_save_join_tab();
bool send_row_on_empty_set()
{
return (do_send_rows && tmp_table_param.sum_func_count != 0 &&