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.
parent b77a85ef
...@@ -4012,3 +4012,11 @@ WHERE (SELECT COUNT(t0.b) FROM t1 t WHERE t.b>20) GROUP BY a; ...@@ -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 ERROR HY000: Invalid use of group function
SET @@sql_mode=default; SET @@sql_mode=default;
DROP TABLE t1; 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.
...@@ -2845,3 +2845,13 @@ SELECT a FROM t1 t0 ...@@ -2845,3 +2845,13 @@ SELECT a FROM t1 t0
SET @@sql_mode=default; SET @@sql_mode=default;
DROP TABLE t1; 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.
...@@ -1774,6 +1774,21 @@ int subselect_single_select_engine::exec() ...@@ -1774,6 +1774,21 @@ int subselect_single_select_engine::exec()
thd->lex->current_select= save_select; thd->lex->current_select= save_select;
DBUG_RETURN(join->error ? join->error : 1); 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) if (item->engine_changed)
{ {
DBUG_RETURN(1); DBUG_RETURN(1);
......
...@@ -1426,14 +1426,13 @@ JOIN::optimize() ...@@ -1426,14 +1426,13 @@ JOIN::optimize()
} }
} }
if (select_lex->uncacheable && !is_top_level_join()) /*
{ If this join belongs to an uncacheable subquery save
/* If this join belongs to an uncacheable subquery */ the original join
if (!(tmp_join= (JOIN*)thd->alloc(sizeof(JOIN)))) */
if (select_lex->uncacheable && !is_top_level_join() &&
init_save_join_tab())
DBUG_RETURN(-1); DBUG_RETURN(-1);
error= 0; // Ensure that tmp_join.error= 0
restore_tmp();
}
} }
error= 0; error= 0;
...@@ -1495,6 +1494,27 @@ JOIN::reinit() ...@@ -1495,6 +1494,27 @@ JOIN::reinit()
DBUG_RETURN(0); 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 bool
JOIN::save_join_tab() JOIN::save_join_tab()
......
...@@ -434,6 +434,7 @@ public: ...@@ -434,6 +434,7 @@ public:
void cleanup(bool full); void cleanup(bool full);
void clear(); void clear();
bool save_join_tab(); bool save_join_tab();
bool init_save_join_tab();
bool send_row_on_empty_set() bool send_row_on_empty_set()
{ {
return (do_send_rows && tmp_table_param.sum_func_count != 0 && return (do_send_rows && tmp_table_param.sum_func_count != 0 &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment