Commit 5eecea8c authored by Sergey Petrunya's avatar Sergey Petrunya

MDEV-324: SHOW EXPLAIN: Plan produced by SHOW EXPLAIN for a query with...

MDEV-324: SHOW EXPLAIN: Plan produced by SHOW EXPLAIN for a query with TEMPTABLE view loses 'DERIVED' line
- Make SHOW EXPLAIN code take into account that st_select_lex object without joins can be
  a full-featured SELECTs which were already executed and cleaned up.
parent 2c1e737c
...@@ -153,10 +153,7 @@ set @show_explain_probe_select_id=1; ...@@ -153,10 +153,7 @@ set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_end'; set debug_dbug='d,show_explain_probe_join_exec_end';
select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1; select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1;
show explain for $thr2; show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Query plan already deleted
Warnings:
Note 1003 select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1
a (select max(a) from t0 b where b.a+a.a<10) a (select max(a) from t0 b where b.a+a.a<10)
0 9 0 9
# Try to do SHOW EXPLAIN for a query that runs a SET command: # Try to do SHOW EXPLAIN for a query that runs a SET command:
...@@ -308,12 +305,10 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -308,12 +305,10 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join) 1 SIMPLE t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
set debug_dbug='d,show_explain_in_find_all_keys'; set debug_dbug='d,show_explain_in_find_all_keys';
SELECT alias.a FROM t2, ( SELECT * FROM t2 ) AS alias GROUP BY alias.a; SELECT alias.a FROM t2, ( SELECT * FROM t2 ) AS alias GROUP BY alias.a;
# FIXED by "conservative assumptions about when QEP is available" fix:
# NOTE: current code will not show "Using join buffer": # NOTE: current code will not show "Using join buffer":
show explain for $thr2; show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Query plan already deleted
Warnings:
Note 1003 SELECT alias.a FROM t2, ( SELECT * FROM t2 ) AS alias GROUP BY alias.a
a a
1 1
2 2
...@@ -366,10 +361,7 @@ set @show_explain_probe_select_id=2; ...@@ -366,10 +361,7 @@ set @show_explain_probe_select_id=2;
set debug_dbug='d,show_explain_probe_join_exec_end'; set debug_dbug='d,show_explain_probe_join_exec_end';
SELECT * FROM v1, t2; SELECT * FROM v1, t2;
show explain for $thr2; show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Not yet optimized
Warnings:
Note 1003 SELECT * FROM v1, t2
a b a b
8 4 8 4
8 5 8 5
...@@ -401,10 +393,7 @@ set @show_explain_probe_select_id=1; ...@@ -401,10 +393,7 @@ set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_end'; set debug_dbug='d,show_explain_probe_join_exec_end';
select * from t0 where 1>10; select * from t0 where 1>10;
show explain for $thr2; show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Query plan already deleted
Warnings:
Note 1003 select * from t0 where 1>10
a a
set debug_dbug=''; set debug_dbug='';
# #
...@@ -416,10 +405,7 @@ set @show_explain_probe_select_id=1; ...@@ -416,10 +405,7 @@ set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_end'; set debug_dbug='d,show_explain_probe_join_exec_end';
select * from t0,t3 where t3.a=112233; select * from t0,t3 where t3.a=112233;
show explain for $thr2; show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Query plan already deleted
Warnings:
Note 1003 select * from t0,t3 where t3.a=112233
a a a a
set debug_dbug=''; set debug_dbug='';
drop table t3; drop table t3;
...@@ -524,10 +510,7 @@ set @show_explain_probe_select_id=1; ...@@ -524,10 +510,7 @@ set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_end'; set debug_dbug='d,show_explain_probe_join_exec_end';
SELECT * FROM t2 WHERE (5, 78) IN (SELECT `a1`, MAX(`a1`) FROM t2 GROUP BY `a1`); SELECT * FROM t2 WHERE (5, 78) IN (SELECT `a1`, MAX(`a1`) FROM t2 GROUP BY `a1`);
show explain for $thr2; show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Query plan already deleted
Warnings:
Note 1003 SELECT * FROM t2 WHERE (5, 78) IN (SELECT `a1`, MAX(`a1`) FROM t2 GROUP BY `a1`)
pk a1 pk a1
set debug_dbug=''; set debug_dbug='';
DROP TABLE t2; DROP TABLE t2;
...@@ -616,4 +599,30 @@ t1 1 b 1 b A NULL NULL NULL YES BTREE ...@@ -616,4 +599,30 @@ t1 1 b 1 b A NULL NULL NULL YES BTREE
t1 1 c 1 c A NULL NULL NULL YES BTREE t1 1 c 1 c A NULL NULL NULL YES BTREE
set debug_dbug=''; set debug_dbug='';
DROP TABLE t1; DROP TABLE t1;
#
# MDEV-324: SHOW EXPLAIN: Plan produced by SHOW EXPLAIN for a query with TEMPTABLE view
# loses 'DERIVED' line on the way without saying that the plan was already deleted
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2);
CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1;
EXPLAIN SELECT a + 1 FROM v1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED t1 ALL NULL NULL NULL NULL 2
set debug_dbug='d,show_explain_probe_join_tab_preread';
set @show_explain_probe_select_id=1;
SELECT a + 1 FROM v1;
show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED NULL NULL NULL NULL NULL NULL NULL Query plan already deleted
Warnings:
Note 1003 SELECT a + 1 FROM v1
a + 1
2
3
set debug_dbug='';
DROP VIEW v1;
DROP TABLE t1;
drop table t0; drop table t0;
...@@ -191,6 +191,7 @@ set debug_dbug='d,show_explain_probe_join_exec_end'; ...@@ -191,6 +191,7 @@ set debug_dbug='d,show_explain_probe_join_exec_end';
send select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1; send select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1;
connection default; connection default;
--source include/wait_condition.inc --source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND
evalp show explain for $thr2; evalp show explain for $thr2;
connection con1; connection con1;
reap; reap;
...@@ -325,7 +326,9 @@ send SELECT alias.a FROM t2, ( SELECT * FROM t2 ) AS alias GROUP BY alias.a; ...@@ -325,7 +326,9 @@ send SELECT alias.a FROM t2, ( SELECT * FROM t2 ) AS alias GROUP BY alias.a;
connection default; connection default;
--source include/wait_condition.inc --source include/wait_condition.inc
--echo # FIXED by "conservative assumptions about when QEP is available" fix:
--echo # NOTE: current code will not show "Using join buffer": --echo # NOTE: current code will not show "Using join buffer":
--error ER_ERROR_WHEN_EXECUTING_COMMAND
evalp show explain for $thr2; evalp show explain for $thr2;
connection con1; connection con1;
reap; reap;
...@@ -374,6 +377,7 @@ send SELECT * FROM v1, t2; ...@@ -374,6 +377,7 @@ send SELECT * FROM v1, t2;
connection default; connection default;
--source include/wait_condition.inc --source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND
evalp show explain for $thr2; evalp show explain for $thr2;
connection con1; connection con1;
reap; reap;
...@@ -403,6 +407,7 @@ set debug_dbug='d,show_explain_probe_join_exec_end'; ...@@ -403,6 +407,7 @@ set debug_dbug='d,show_explain_probe_join_exec_end';
send select * from t0 where 1>10; send select * from t0 where 1>10;
connection default; connection default;
--source include/wait_condition.inc --source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND
evalp show explain for $thr2; evalp show explain for $thr2;
connection con1; connection con1;
reap; reap;
...@@ -418,6 +423,7 @@ set debug_dbug='d,show_explain_probe_join_exec_end'; ...@@ -418,6 +423,7 @@ set debug_dbug='d,show_explain_probe_join_exec_end';
send select * from t0,t3 where t3.a=112233; send select * from t0,t3 where t3.a=112233;
connection default; connection default;
--source include/wait_condition.inc --source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND
evalp show explain for $thr2; evalp show explain for $thr2;
connection con1; connection con1;
reap; reap;
...@@ -513,6 +519,7 @@ send ...@@ -513,6 +519,7 @@ send
SELECT * FROM t2 WHERE (5, 78) IN (SELECT `a1`, MAX(`a1`) FROM t2 GROUP BY `a1`); SELECT * FROM t2 WHERE (5, 78) IN (SELECT `a1`, MAX(`a1`) FROM t2 GROUP BY `a1`);
connection default; connection default;
--source include/wait_condition.inc --source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND
evalp show explain for $thr2; evalp show explain for $thr2;
connection con1; connection con1;
reap; reap;
...@@ -601,6 +608,32 @@ set debug_dbug=''; ...@@ -601,6 +608,32 @@ set debug_dbug='';
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-324: SHOW EXPLAIN: Plan produced by SHOW EXPLAIN for a query with TEMPTABLE view
--echo # loses 'DERIVED' line on the way without saying that the plan was already deleted
--echo #
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2);
CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1;
EXPLAIN SELECT a + 1 FROM v1;
set debug_dbug='d,show_explain_probe_join_tab_preread';
set @show_explain_probe_select_id=1;
send
SELECT a + 1 FROM v1;
connection default;
--source include/wait_condition.inc
evalp show explain for $thr2;
connection con1;
reap;
set debug_dbug='';
DROP VIEW v1;
DROP TABLE t1;
## TODO: Test this: have several SHOW EXPLAIN requests be queued up for a ## TODO: Test this: have several SHOW EXPLAIN requests be queued up for a
## thread and served together. ## thread and served together.
......
...@@ -2356,13 +2356,14 @@ int select_result_explain_buffer::send_data(List<Item> &items) ...@@ -2356,13 +2356,14 @@ int select_result_explain_buffer::send_data(List<Item> &items)
} }
/* Write all strings out to the output, and free them. */
void select_result_explain_buffer::flush_data() void select_result_explain_buffer::flush_data()
{ {
List_iterator<String> it(data_rows); List_iterator<String> it(data_rows);
String *str; String *str;
while ((str= it++)) while ((str= it++))
{ {
/* TODO: write out the lines. */
protocol->set_packet(str->ptr(), str->length()); protocol->set_packet(str->ptr(), str->length());
protocol->write(); protocol->write();
delete str; delete str;
...@@ -2370,6 +2371,20 @@ void select_result_explain_buffer::flush_data() ...@@ -2370,6 +2371,20 @@ void select_result_explain_buffer::flush_data()
data_rows.empty(); data_rows.empty();
} }
/* Just free all of the accumulated strings */
void select_result_explain_buffer::discard_data()
{
List_iterator<String> it(data_rows);
String *str;
while ((str= it++))
{
delete str;
}
data_rows.empty();
}
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
...@@ -3288,6 +3303,7 @@ void Show_explain_request::get_explain_data(void *arg) ...@@ -3288,6 +3303,7 @@ void Show_explain_request::get_explain_data(void *arg)
// Actually, change the ARENA, because we're going to allocate items! // Actually, change the ARENA, because we're going to allocate items!
Query_arena backup_arena; Query_arena backup_arena;
THD *target_thd= req->target_thd; THD *target_thd= req->target_thd;
bool printed_anything= FALSE;
target_thd->set_n_backup_active_arena((Query_arena*)req->request_thd, target_thd->set_n_backup_active_arena((Query_arena*)req->request_thd,
&backup_arena); &backup_arena);
...@@ -3296,7 +3312,11 @@ void Show_explain_request::get_explain_data(void *arg) ...@@ -3296,7 +3312,11 @@ void Show_explain_request::get_explain_data(void *arg)
target_thd->query_length(), target_thd->query_length(),
&my_charset_bin); &my_charset_bin);
if (target_thd->lex->unit.print_explain(req->explain_buf, 0 /* explain flags */)) if (target_thd->lex->unit.print_explain(req->explain_buf, 0 /* explain flags*/,
&printed_anything))
req->failed_to_produce= TRUE;
if (!printed_anything)
req->failed_to_produce= TRUE; req->failed_to_produce= TRUE;
target_thd->restore_active_arena((Query_arena*)req->request_thd, target_thd->restore_active_arena((Query_arena*)req->request_thd,
......
...@@ -3328,6 +3328,8 @@ class select_result_explain_buffer : public select_result_sink ...@@ -3328,6 +3328,8 @@ class select_result_explain_buffer : public select_result_sink
/* this will be called in the parent thread: */ /* this will be called in the parent thread: */
void flush_data(); void flush_data();
void discard_data();
List<String> data_rows; List<String> data_rows;
}; };
......
...@@ -4074,7 +4074,8 @@ int print_explain_message_line(select_result_sink *result, ...@@ -4074,7 +4074,8 @@ int print_explain_message_line(select_result_sink *result,
int st_select_lex::print_explain(select_result_sink *output, int st_select_lex::print_explain(select_result_sink *output,
uint8 explain_flags) uint8 explain_flags,
bool *printed_anything)
{ {
int res; int res;
if (join && join->have_query_plan == JOIN::QEP_AVAILABLE) if (join && join->have_query_plan == JOIN::QEP_AVAILABLE)
...@@ -4083,6 +4084,7 @@ int st_select_lex::print_explain(select_result_sink *output, ...@@ -4083,6 +4084,7 @@ int st_select_lex::print_explain(select_result_sink *output,
There is a number of reasons join can be marked as degenerate, so all There is a number of reasons join can be marked as degenerate, so all
three conditions below can happen simultaneously, or individually: three conditions below can happen simultaneously, or individually:
*/ */
*printed_anything= TRUE;
if (!join->table_count || !join->tables_list || join->zero_result_cause) if (!join->table_count || !join->tables_list || join->zero_result_cause)
{ {
/* It's a degenerate join */ /* It's a degenerate join */
...@@ -4112,7 +4114,8 @@ int st_select_lex::print_explain(select_result_sink *output, ...@@ -4112,7 +4114,8 @@ int st_select_lex::print_explain(select_result_sink *output,
*/ */
if (!(unit->item && unit->item->eliminated)) if (!(unit->item && unit->item->eliminated))
{ {
unit->print_explain(output, explain_flags); if ((res= unit->print_explain(output, explain_flags, printed_anything)))
goto err;
} }
} }
} }
...@@ -4120,7 +4123,9 @@ int st_select_lex::print_explain(select_result_sink *output, ...@@ -4120,7 +4123,9 @@ int st_select_lex::print_explain(select_result_sink *output,
{ {
const char *msg; const char *msg;
if (!join) if (!join)
DBUG_ASSERT(0); // psergey: TODO: can this happen or not? DBUG_ASSERT(0); /* Seems not to be possible */
/* Not printing anything useful, don't touch *printed_anything here */
if (join->have_query_plan == JOIN::QEP_NOT_PRESENT_YET) if (join->have_query_plan == JOIN::QEP_NOT_PRESENT_YET)
msg= "Not yet optimized"; msg= "Not yet optimized";
else else
...@@ -4132,12 +4137,12 @@ int st_select_lex::print_explain(select_result_sink *output, ...@@ -4132,12 +4137,12 @@ int st_select_lex::print_explain(select_result_sink *output,
0, msg); 0, msg);
} }
err: err:
return 0; return res;
} }
int st_select_lex_unit::print_explain(select_result_sink *output, int st_select_lex_unit::print_explain(select_result_sink *output,
uint8 explain_flags) uint8 explain_flags, bool *printed_anything)
{ {
int res= 0; int res= 0;
SELECT_LEX *first= first_select(); SELECT_LEX *first= first_select();
...@@ -4148,12 +4153,15 @@ int st_select_lex_unit::print_explain(select_result_sink *output, ...@@ -4148,12 +4153,15 @@ int st_select_lex_unit::print_explain(select_result_sink *output,
If there is only one child, 'first', and it has join==NULL, emit "not in If there is only one child, 'first', and it has join==NULL, emit "not in
EXPLAIN state" error. EXPLAIN state" error.
*/ */
return 1; const char *msg="Query plan already deleted";
res= print_explain_message_line(output, first, TRUE /* on_the_fly */,
0, msg);
return 0;
} }
for (SELECT_LEX *sl= first; sl; sl= sl->next_select()) for (SELECT_LEX *sl= first; sl; sl= sl->next_select())
{ {
if ((res= sl->print_explain(output, explain_flags))) if ((res= sl->print_explain(output, explain_flags, printed_anything)))
break; break;
} }
......
...@@ -718,7 +718,8 @@ class st_select_lex_unit: public st_select_lex_node { ...@@ -718,7 +718,8 @@ class st_select_lex_unit: public st_select_lex_node {
friend int subselect_union_engine::exec(); friend int subselect_union_engine::exec();
List<Item> *get_unit_column_types(); List<Item> *get_unit_column_types();
int print_explain(select_result_sink *output, uint8 explain_flags); int print_explain(select_result_sink *output, uint8 explain_flags,
bool *printed_anything);
}; };
typedef class st_select_lex_unit SELECT_LEX_UNIT; typedef class st_select_lex_unit SELECT_LEX_UNIT;
...@@ -1039,7 +1040,8 @@ class st_select_lex: public st_select_lex_node ...@@ -1039,7 +1040,8 @@ class st_select_lex: public st_select_lex_node
bool save_prep_leaf_tables(THD *thd); bool save_prep_leaf_tables(THD *thd);
bool is_merged_child_of(st_select_lex *ancestor); bool is_merged_child_of(st_select_lex *ancestor);
int print_explain(select_result_sink *output, uint8 explain_flags); int print_explain(select_result_sink *output, uint8 explain_flags,
bool *printed_anything);
/* /*
For MODE_ONLY_FULL_GROUP_BY we need to maintain two flags: For MODE_ONLY_FULL_GROUP_BY we need to maintain two flags:
- Non-aggregated fields are used in this select. - Non-aggregated fields are used in this select.
......
...@@ -10365,9 +10365,18 @@ bool JOIN_TAB::preread_init() ...@@ -10365,9 +10365,18 @@ bool JOIN_TAB::preread_init()
mysql_handle_single_derived(join->thd->lex, mysql_handle_single_derived(join->thd->lex,
derived, DT_CREATE | DT_FILL)) derived, DT_CREATE | DT_FILL))
return TRUE; return TRUE;
preread_init_done= TRUE; preread_init_done= TRUE;
if (select && select->quick) if (select && select->quick)
select->quick->replace_handler(table->file); select->quick->replace_handler(table->file);
DBUG_EXECUTE_IF("show_explain_probe_join_tab_preread",
if (dbug_user_var_equals_int(join->thd,
"show_explain_probe_select_id",
join->select_lex->select_number))
dbug_serve_apcs(join->thd, 1);
);
return FALSE; return FALSE;
} }
......
...@@ -2085,6 +2085,7 @@ void mysqld_show_explain(THD *thd, ulong thread_id) ...@@ -2085,6 +2085,7 @@ void mysqld_show_explain(THD *thd, ulong thread_id)
"Target is not running EXPLAINable command"); "Target is not running EXPLAINable command");
} }
bres= TRUE; bres= TRUE;
explain_buf->discard_data();
} }
else else
{ {
......
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