Commit 5100b20b authored by Sergei Petrunia's avatar Sergei Petrunia

MDEV-26047: MariaDB server crash at Item_subselect::init_expr_cache_tracker

The cause of crash:
remove_redundant_subquery_clauses() removes redundant item expressions.
The primary goal of this is to remove the subquery items.
The removal process unlinks the subquery from SELECT_LEX tree, but does
not remove it from SELECT_LEX:::ref_pointer_array or from JOIN::all_fields.
Then, setup_subquery_caches() tries to wrap the subquery item in an
expression cache, which fails, the first reason for failure being that
the item doesn't have a query plan.

Solution: do not wrap eliminated items with expression cache.
(also added an assert to check that we do not attempt to execute them).

This may look like an incomplete fix: why don't we remove any mention
of eliminated item everywhere? The difficulties here are:
* items can be "un-removed" (see set_fake_select_as_master_processor)
* it's difficult to remove an element from ref_pointer_array: Item_ref
objects refer to elements of that array, so one can't shift elements in
it. Replacing eliminated subselect with a dummy Item doesn't look like a
good idea, either.
parent 9b2d3666
......@@ -629,3 +629,35 @@ a b
2019-03-10 02:55:05 2019-03-10 02:55:05
DROP TABLE t1,t2;
set character_set_connection=@save_character_set_connection;
#
# MDEV-26047: MariaDB server crash at Item_subselect::init_expr_cache_tracker
#
CREATE TABLE t1 (a int) engine=innodb;
SELECT 1 IN (
SELECT NULL
FROM t1
WHERE
a IS NOT NULL
GROUP BY
(SELECT NULL from dual WHERE a = 1)
);
1 IN (
SELECT NULL
FROM t1
WHERE
a IS NOT NULL
GROUP BY
(SELECT NULL from dual WHERE a = 1)
)
0
drop table t1;
# Testcase from MDEV-26164
create table t1(a int);
# Disable the warning as it includes current time and changes for every test run.
select 1 from t1 where not exists
(
select 1 from t1 where binary current_time()
group by (select a),(select 1)
);
1
drop table t1;
......@@ -627,3 +627,31 @@ SELECT * FROM t1 WHERE (SELECT 1,CONCAT(a) FROM t1) = (SELECT 1,CONCAT(a) FROM t
DROP TABLE t1,t2;
set character_set_connection=@save_character_set_connection;
--echo #
--echo # MDEV-26047: MariaDB server crash at Item_subselect::init_expr_cache_tracker
--echo #
CREATE TABLE t1 (a int) engine=innodb;
SELECT 1 IN (
SELECT NULL
FROM t1
WHERE
a IS NOT NULL
GROUP BY
(SELECT NULL from dual WHERE a = 1)
);
drop table t1;
--echo # Testcase from MDEV-26164
create table t1(a int);
--echo # Disable the warning as it includes current time and changes for every test run.
--disable_warnings
select 1 from t1 where not exists
(
select 1 from t1 where binary current_time()
group by (select a),(select 1)
);
--enable_warnings
drop table t1;
......@@ -752,6 +752,7 @@ bool Item_subselect::exec()
DBUG_ENTER("Item_subselect::exec");
DBUG_ASSERT(fixed);
DBUG_ASSERT(!eliminated);
/*
Do not execute subselect in case of a fatal error
......@@ -1313,6 +1314,16 @@ Item* Item_singlerow_subselect::expr_cache_insert_transformer(THD *tmp_thd,
DBUG_ASSERT(thd == tmp_thd);
/*
Do not create subquery cache if the subquery was eliminated.
The optimizer may eliminate subquery items (see
eliminate_subselect_processor). However it does not update
all query's data structures, so the eliminated item may be
still reachable.
*/
if (eliminated)
DBUG_RETURN(this);
if (expr_cache)
DBUG_RETURN(expr_cache);
......
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