Commit adce16f9 authored by unknown's avatar unknown

Fix LP BUG#718763

Analysis:
The reason for the crash was that the inner subquery was executed
via a scan on a final temporary table applied after all other
operations. This final operation is implemented by changing the
contents of the JOIN object of the subquery to represent a table
scan over the temp table. At the same time query optimization of
the outer subquery required evaluation of the inner subquery, which
happened before the actual EXPLAIN. The evaluation left the JOIN
object of the inner subquery in the changed state, where it represented
a table scan over a temp table, and EXPLAIN crashed because the temp
table is not associated with any table reference (TABLE_LIST object).
The reason the JOIN was not restored was because its saving/restoration
was controlled by the join->select_lex->uncacheable flag, which was
not set in the case of materialization.

Solution:
In the methods Item_in_subselect::[single | row]_value_transformer() set:
    select_lex->uncacheable|= UNCACHEABLE_EXPLAIN;
In addition, for symmetry, change:
    master_unit->uncacheable|= UNCACHEABLE_EXPLAIN;
instead of UNCACHEABLE_DEPENDENT because if a subquery was not
dependent initially, the changed methods do not change this
fact. The subquery may later become correlated if it is transformed
to an EXISTS query, but it may stay uncorrelated if executed via
materialization.
parent c6ba9598
......@@ -707,3 +707,42 @@ f4
f
d
drop table t1,t2;
#
# LP BUG#718763 Second crash in select_describe() and materialization
#
CREATE TABLE t1 ( f1 int(11), f3 int(11), f10 varchar(1), KEY (f3)) ;
INSERT INTO t1 VALUES ('28','6','m'),('29','4','c');
CREATE TABLE t2 (f11 varchar(1)) ;
INSERT INTO t2 VALUES ('f'),('d');
SET @old_optimizer_switch = @@session.optimizer_switch;
SET SESSION optimizer_switch = 'materialization=on';
EXPLAIN
SELECT * FROM t1
WHERE f3 = (
SELECT t1.f3 FROM t1
WHERE ( t1.f10 ) IN ( SELECT f11 FROM t2 GROUP BY f11 ));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where
3 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort
SELECT * FROM t1
WHERE f3 = (
SELECT t1.f3 FROM t1
WHERE ( t1.f10 ) IN ( SELECT f11 FROM t2 GROUP BY f11 ));
f1 f3 f10
EXPLAIN
SELECT * FROM t1
WHERE f3 = (
SELECT f3 FROM t1
WHERE ( f10, f10 ) IN ( SELECT f11, f11 FROM t2 GROUP BY f11 ));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where
3 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort
SELECT * FROM t1
WHERE f3 = (
SELECT f3 FROM t1
WHERE ( f10, f10 ) IN ( SELECT f11, f11 FROM t2 GROUP BY f11 ));
f1 f3 f10
SET SESSION optimizer_switch = @old_optimizer_switch;
drop table t1,t2;
......@@ -640,3 +640,38 @@ WHERE EXISTS (
drop table t1,t2;
--echo #
--echo # LP BUG#718763 Second crash in select_describe() and materialization
--echo #
CREATE TABLE t1 ( f1 int(11), f3 int(11), f10 varchar(1), KEY (f3)) ;
INSERT INTO t1 VALUES ('28','6','m'),('29','4','c');
CREATE TABLE t2 (f11 varchar(1)) ;
INSERT INTO t2 VALUES ('f'),('d');
SET @old_optimizer_switch = @@session.optimizer_switch;
SET SESSION optimizer_switch = 'materialization=on';
EXPLAIN
SELECT * FROM t1
WHERE f3 = (
SELECT t1.f3 FROM t1
WHERE ( t1.f10 ) IN ( SELECT f11 FROM t2 GROUP BY f11 ));
SELECT * FROM t1
WHERE f3 = (
SELECT t1.f3 FROM t1
WHERE ( t1.f10 ) IN ( SELECT f11 FROM t2 GROUP BY f11 ));
EXPLAIN
SELECT * FROM t1
WHERE f3 = (
SELECT f3 FROM t1
WHERE ( f10, f10 ) IN ( SELECT f11, f11 FROM t2 GROUP BY f11 ));
SELECT * FROM t1
WHERE f3 = (
SELECT f3 FROM t1
WHERE ( f10, f10 ) IN ( SELECT f11, f11 FROM t2 GROUP BY f11 ));
SET SESSION optimizer_switch = @old_optimizer_switch;
drop table t1,t2;
......@@ -1464,8 +1464,15 @@ Item_in_subselect::single_value_transformer(JOIN *join,
(char *)"<no matter>",
(char *)in_left_expr_name);
master_unit->uncacheable|= UNCACHEABLE_DEPENDENT;
//psergey: placed then removed: select_lex->uncacheable|= UNCACHEABLE_DEPENDENT;
/*
The uncacheable property controls a number of actions, e.g. whether to
save/restore (via init_save_join_tab/restore_tmp) the original JOIN for
plans with a temp table where the original JOIN was overriden by
make_simple_join. The UNCACHEABLE_EXPLAIN is ignored by EXPLAIN, thus
non-correlated subqueries will not appear as such to EXPLAIN.
*/
master_unit->uncacheable|= UNCACHEABLE_EXPLAIN;
select_lex->uncacheable|= UNCACHEABLE_EXPLAIN;
}
if (!abort_on_null && left_expr->maybe_null && !pushed_cond_guards)
......@@ -1529,6 +1536,9 @@ Item_in_subselect::single_value_in_to_exists_transformer(JOIN * join, Comp_creat
SELECT_LEX *select_lex= join->select_lex;
DBUG_ENTER("Item_in_subselect::single_value_in_to_exists_transformer");
/*
The IN=>EXISTS transformation makes non-correlated subqueries correlated.
*/
select_lex->uncacheable|= UNCACHEABLE_DEPENDENT;
if (join->having || select_lex->with_sum_func ||
select_lex->group_list.elements)
......@@ -1742,7 +1752,15 @@ Item_in_subselect::row_value_transformer(JOIN *join)
optimizer->keep_top_level_cache();
thd->lex->current_select= current;
master_unit->uncacheable|= UNCACHEABLE_DEPENDENT;
/*
The uncacheable property controls a number of actions, e.g. whether to
save/restore (via init_save_join_tab/restore_tmp) the original JOIN for
plans with a temp table where the original JOIN was overriden by
make_simple_join. The UNCACHEABLE_EXPLAIN is ignored by EXPLAIN, thus
non-correlated subqueries will not appear as such to EXPLAIN.
*/
master_unit->uncacheable|= UNCACHEABLE_EXPLAIN;
select_lex->uncacheable|= UNCACHEABLE_EXPLAIN;
if (!abort_on_null && left_expr->maybe_null && !pushed_cond_guards)
{
......@@ -1796,6 +1814,9 @@ Item_in_subselect::row_value_in_to_exists_transformer(JOIN * join)
DBUG_ENTER("Item_in_subselect::row_value_in_to_exists_transformer");
/*
The IN=>EXISTS transformation makes non-correlated subqueries correlated.
*/
select_lex->uncacheable|= UNCACHEABLE_DEPENDENT;
if (is_having_used)
{
......
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