mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
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.
This commit is contained in:
@@ -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 t3 ALL NULL NULL NULL NULL 7
|
||||||
1 PRIMARY <derived2> ref key0 key0 18 federated.t3.name 2
|
1 PRIMARY <derived2> ref key0 key0 18 federated.t3.name 2
|
||||||
2 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL
|
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
|
ANALYZE FORMAT=JSON
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM federated.t3, (SELECT t1.name FROM federated.t1
|
FROM federated.t3, (SELECT t1.name FROM federated.t1
|
||||||
@@ -251,25 +250,7 @@ ANALYZE
|
|||||||
"select_id": 2,
|
"select_id": 2,
|
||||||
"table": {
|
"table": {
|
||||||
"message": "Pushed derived"
|
"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
|
@var
|
||||||
xxx
|
xxx
|
||||||
select name into outfile 'tmp.txt' from federated.t1;
|
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;
|
DROP TABLE federated.t1, federated.t2, federated.t3, federated.t4;
|
||||||
connection slave;
|
connection slave;
|
||||||
DROP TABLE federated.t1, federated.t2;
|
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')`;
|
let $path=`select concat(@@datadir, 'test/tmp.txt')`;
|
||||||
remove_file $path;
|
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;
|
DROP TABLE federated.t1, federated.t2, federated.t3, federated.t4;
|
||||||
|
|
||||||
connection slave;
|
connection slave;
|
||||||
|
@@ -26840,24 +26840,33 @@ int JOIN::save_explain_data_intern(Explain_query *output,
|
|||||||
output->add_node(xpl_sel);
|
output->add_node(xpl_sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SELECT_LEX_UNIT *tmp_unit= join->select_lex->first_inner_unit();
|
/*
|
||||||
tmp_unit;
|
Don't try to add query plans for child selects if this select was pushed
|
||||||
tmp_unit= tmp_unit->next_unit())
|
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)
|
||||||
{
|
{
|
||||||
/*
|
for (SELECT_LEX_UNIT *tmp_unit= join->select_lex->first_inner_unit();
|
||||||
Display subqueries only if
|
tmp_unit;
|
||||||
(1) they are not parts of ON clauses that were eliminated by table
|
tmp_unit= tmp_unit->next_unit())
|
||||||
elimination.
|
{
|
||||||
(2) they are not merged derived tables
|
/*
|
||||||
(3) they are not hanging CTEs (they are needed for execution)
|
Display subqueries only if
|
||||||
*/
|
(1) they are not parts of ON clauses that were eliminated by table
|
||||||
if (!(tmp_unit->item && tmp_unit->item->eliminated) && // (1)
|
elimination.
|
||||||
(!tmp_unit->derived ||
|
(2) they are not merged derived tables
|
||||||
tmp_unit->derived->is_materialized_derived()) && // (2)
|
(3) they are not hanging CTEs (they are needed for execution)
|
||||||
!(tmp_unit->with_element &&
|
*/
|
||||||
(!tmp_unit->derived || !tmp_unit->derived->derived_result))) // (3)
|
if (!(tmp_unit->item && tmp_unit->item->eliminated) && // (1)
|
||||||
{
|
(!tmp_unit->derived ||
|
||||||
explain->add_child(tmp_unit->first_select()->select_number);
|
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;
|
THD *thd=join->thd;
|
||||||
select_result *result=join->result;
|
select_result *result=join->result;
|
||||||
DBUG_ENTER("select_describe");
|
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 */
|
/* Update the QPF with latest values of using_temporary, using_filesort */
|
||||||
for (SELECT_LEX_UNIT *unit= join->select_lex->first_inner_unit();
|
for (SELECT_LEX_UNIT *unit= join->select_lex->first_inner_unit();
|
||||||
unit;
|
unit;
|
||||||
|
Reference in New Issue
Block a user