Commit b4abe7c9 authored by Sergei Petrunia's avatar Sergei Petrunia

MDEV-22993: Crash on EXPLAIN with PUSHED DOWN SELECT and subquery

- select_describe() should not attempt to produce query plans
  for subqueries if the query is handled by a Select Handler.

- JOIN::save_explain_data_intern should not add links to Explain_select
  for children selects if:
  1. The whole query is handled by the Select Handler, or
  2. this select (and so its children) is handled by Derived Handler.
parent b80b5239
......@@ -209,7 +209,6 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 7
1 PRIMARY <derived2> ref key0 key0 18 federated.t3.name 2
2 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL
3 MATERIALIZED t2 ALL NULL NULL NULL NULL 7 Using temporary
ANALYZE FORMAT=JSON
SELECT *
FROM federated.t3, (SELECT t1.name FROM federated.t1
......@@ -251,25 +250,7 @@ ANALYZE
"select_id": 2,
"table": {
"message": "Pushed derived"
},
"subqueries": [
{
"query_block": {
"select_id": 3,
"temporary_table": {
"table": {
"table_name": "t2",
"access_type": "ALL",
"r_loops": 0,
"rows": 7,
"r_rows": null,
"filtered": 100,
"r_filtered": null
}
}
}
}
]
}
}
}
}
......@@ -319,6 +300,78 @@ select @var;
@var
xxx
select name into outfile 'tmp.txt' from federated.t1;
#
# MDEV-22993: Crash on EXPLAIN with PUSHED DOWN SELECT and subquery
#
explain
select * from federated.t1
where name in (select name from federated.t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PUSHED SELECT NULL NULL NULL NULL NULL NULL NULL NULL
explain format=json
select * from federated.t1
where name in (select name from federated.t2);
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"message": "Pushed select"
}
}
}
#
# MDEV-22993, testcase #2: EXPLAIN output doesn't make sense when
# derived table pushdown is used.
#
create table t5 (a int) engine=myisam;
insert into t5 values (1),(2);
# Must not show lines with id=3
explain
select * from t5,
(select id from federated.t1
where name in (select name from federated.t2) or name like 'foo%') as TQ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t5 ALL NULL NULL NULL NULL 2
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
2 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL
# Must not show elements with select_id=3
explain format=json
select * from t5,
(select id from federated.t1
where name in (select name from federated.t2) or name like 'foo%') as TQ;
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "t5",
"access_type": "ALL",
"rows": 2,
"filtered": 100
},
"block-nl-join": {
"table": {
"table_name": "<derived2>",
"access_type": "ALL",
"rows": 5,
"filtered": 100
},
"buffer_type": "flat",
"buffer_size": "65",
"join_type": "BNL",
"materialized": {
"query_block": {
"select_id": 2,
"table": {
"message": "Pushed derived"
}
}
}
}
}
}
drop table t5;
DROP TABLE federated.t1, federated.t2, federated.t3, federated.t4;
connection slave;
DROP TABLE federated.t1, federated.t2;
......
......@@ -167,6 +167,40 @@ select name into outfile 'tmp.txt' from federated.t1;
let $path=`select concat(@@datadir, 'test/tmp.txt')`;
remove_file $path;
--echo #
--echo # MDEV-22993: Crash on EXPLAIN with PUSHED DOWN SELECT and subquery
--echo #
explain
select * from federated.t1
where name in (select name from federated.t2);
explain format=json
select * from federated.t1
where name in (select name from federated.t2);
--echo #
--echo # MDEV-22993, testcase #2: EXPLAIN output doesn't make sense when
--echo # derived table pushdown is used.
--echo #
create table t5 (a int) engine=myisam;
insert into t5 values (1),(2);
--echo # Must not show lines with id=3
explain
select * from t5,
(select id from federated.t1
where name in (select name from federated.t2) or name like 'foo%') as TQ;
--echo # Must not show elements with select_id=3
explain format=json
select * from t5,
(select id from federated.t1
where name in (select name from federated.t2) or name like 'foo%') as TQ;
drop table t5;
DROP TABLE federated.t1, federated.t2, federated.t3, federated.t4;
connection slave;
......
......@@ -26840,24 +26840,33 @@ int JOIN::save_explain_data_intern(Explain_query *output,
output->add_node(xpl_sel);
}
for (SELECT_LEX_UNIT *tmp_unit= join->select_lex->first_inner_unit();
tmp_unit;
tmp_unit= tmp_unit->next_unit())
/*
Don't try to add query plans for child selects if this select was pushed
down into a Smart Storage Engine:
- the entire statement was pushed down ("PUSHED SELECT"), or
- this derived table was pushed down ("PUSHED DERIVED")
*/
if (!select_lex->pushdown_select && select_lex->type != pushed_derived_text)
{
/*
Display subqueries only if
(1) they are not parts of ON clauses that were eliminated by table
elimination.
(2) they are not merged derived tables
(3) they are not hanging CTEs (they are needed for execution)
*/
if (!(tmp_unit->item && tmp_unit->item->eliminated) && // (1)
(!tmp_unit->derived ||
tmp_unit->derived->is_materialized_derived()) && // (2)
!(tmp_unit->with_element &&
(!tmp_unit->derived || !tmp_unit->derived->derived_result))) // (3)
{
explain->add_child(tmp_unit->first_select()->select_number);
for (SELECT_LEX_UNIT *tmp_unit= join->select_lex->first_inner_unit();
tmp_unit;
tmp_unit= tmp_unit->next_unit())
{
/*
Display subqueries only if
(1) they are not parts of ON clauses that were eliminated by table
elimination.
(2) they are not merged derived tables
(3) they are not hanging CTEs (they are needed for execution)
*/
if (!(tmp_unit->item && tmp_unit->item->eliminated) && // (1)
(!tmp_unit->derived ||
tmp_unit->derived->is_materialized_derived()) && // (2)
!(tmp_unit->with_element &&
(!tmp_unit->derived || !tmp_unit->derived->derived_result))) // (3)
{
explain->add_child(tmp_unit->first_select()->select_number);
}
}
}
......@@ -26890,7 +26899,16 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
THD *thd=join->thd;
select_result *result=join->result;
DBUG_ENTER("select_describe");
if (join->select_lex->pushdown_select)
{
/*
The whole statement was pushed down to a Smart Storage Engine. Do not
attempt to produce a query plan locally.
*/
DBUG_VOID_RETURN;
}
/* Update the QPF with latest values of using_temporary, using_filesort */
for (SELECT_LEX_UNIT *unit= join->select_lex->first_inner_unit();
unit;
......
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