[SHOW] EXPLAIN UPDATE/DELETE, code re-structuring

- Make query plan be re-saved after the first join execution
  (saving it after JOIN::cleanup is too late because EXPLAIN output 
   is currently produced before that)
- Handle QPF allocation/deallocation for edge cases, like unsuccessful
  BINLOG command.
- Work around the problem with UNION's direct subselects not being visible.
- Update test results ("Using temporary; Using filesort" are now always printed 
  last in the Extra column)
- This cset gets rid of memory leaks/crashes. Some result mismatches still remain.
This commit is contained in:
Sergey Petrunya 2013-06-27 16:41:12 +04:00
parent 99a8bfe68c
commit 8b7bbcf4dc
11 changed files with 68 additions and 18 deletions

View file

@ -1031,7 +1031,7 @@ update t22 set c = '2005-12-08 15:58:27' where a = 255;
explain select t21.* from t21,t22 where t21.a = t22.a and
t22.a in (select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null) and t22.c is null order by t21.a;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t11 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort; Start temporary
1 PRIMARY t11 ALL NULL NULL NULL NULL 8 Using where; Start temporary; Using temporary; Using filesort
1 PRIMARY t12 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
1 PRIMARY t22 ALL NULL NULL NULL NULL 26 Using where; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t21 ALL NULL NULL NULL NULL 26 Using where; Using join buffer (flat, BNL join)

View file

@ -1041,7 +1041,7 @@ update t22 set c = '2005-12-08 15:58:27' where a = 255;
explain select t21.* from t21,t22 where t21.a = t22.a and
t22.a in (select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null) and t22.c is null order by t21.a;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t11 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort; Start temporary
1 PRIMARY t11 ALL NULL NULL NULL NULL 8 Using where; Start temporary; Using temporary; Using filesort
1 PRIMARY t12 hash_ALL NULL #hash#$hj 4 test.t11.a 8 Using where; Using join buffer (flat, BNLH join)
1 PRIMARY t22 hash_ALL NULL #hash#$hj 4 test.t11.a 26 Using where; End temporary; Using join buffer (incremental, BNLH join)
1 PRIMARY t21 hash_ALL NULL #hash#$hj 4 test.t11.a 26 Using where; Using join buffer (incremental, BNLH join)

View file

@ -3584,7 +3584,7 @@ View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` FORCE INDEX (PRIMARY) FORCE INDEX (`b`) order by `t1`.`a` latin1 latin1_swedish_ci
EXPLAIN SELECT * FROM v1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 15
1 SIMPLE t1 index NULL PRIMARY 4 NULL 15
CREATE VIEW v2 AS SELECT * FROM t1 USE KEY () ORDER BY a;
SHOW CREATE VIEW v2;
View Create View character_set_client collation_connection

View file

@ -9041,6 +9041,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
call might reset the value of current_stmt_binlog_format, so
we need to do any changes to that value after this function.
*/
delete_qpf_query(thd->lex);
lex_start(thd);
mysql_reset_thd_for_next_command(thd, 0);
/*

View file

@ -13,6 +13,7 @@
QPF_query::QPF_query()
{
upd_del_plan= NULL;
operations= 0;
//memset(&unions, 0, sizeof(unions));
//memset(&selects, 0, sizeof(selects));
}
@ -51,15 +52,18 @@ QPF_select *QPF_query::get_select(uint select_id)
void QPF_query::add_node(QPF_node *node)
{
operations++;
if (node->get_type() == QPF_node::QPF_UNION)
{
QPF_union *u= (QPF_union*)node;
uint select_id= u->get_select_id();
DBUG_ASSERT(!get_union(select_id));
if (unions.elements() <= select_id)
unions.resize(max(select_id+1, unions.elements()*2), NULL);
QPF_union *old_node;
if ((old_node= get_union(select_id)))
delete old_node;
unions.at(select_id)= u;
}
else
@ -73,10 +77,14 @@ void QPF_query::add_node(QPF_node *node)
else
{
uint select_id= sel->select_id;
DBUG_ASSERT(!get_select(select_id));
QPF_select *old_node;
//DBUG_ASSERT(!get_select(select_id));
if (selects.elements() <= select_id)
selects.resize(max(select_id+1, selects.elements()*2), NULL);
if ((old_node= get_select(select_id)))
delete old_node;
selects.at(select_id)= sel;
}
}

View file

@ -223,6 +223,8 @@ private:
Dynamic_array<QPF_select*> selects;
//QPF_union *unions[MAX_TABLES];
//QPF_select *selects[MAX_TABLES];
longlong operations;
};

View file

@ -2552,7 +2552,8 @@ void Query_tables_list::destroy_query_tables_list()
*/
LEX::LEX()
:result(0), option_type(OPT_DEFAULT), is_lex_started(0),
: query_plan_footprint(NULL),
result(0), option_type(OPT_DEFAULT), is_lex_started(0),
limit_rows_examined_cnt(ULONGLONG_MAX)
{

View file

@ -4750,8 +4750,14 @@ finish:
ha_maria::implicit_commit(thd, FALSE);
#endif
}
lex->unit.cleanup();
//psergey-todo: print EXPLAIN here? After the above JOIN::cleanup calls?
// how do we print EXPLAIN extended, then?
if (lex->describe)
{
DBUG_ASSERT(lex->query_plan_footprint);
///..
}
/* Free tables */
thd_proc_info(thd, "closing tables");
close_thread_tables(thd);

View file

@ -2347,6 +2347,36 @@ void JOIN::exec()
exec_inner();
if (!exec_qpf_saved)
{
if (select_lex->select_number != UINT_MAX &&
select_lex->select_number != INT_MAX /* this is not a UNION's "fake select */ &&
have_query_plan != QEP_NOT_PRESENT_YET &&
have_query_plan != QEP_DELETED && // this happens when there was no QEP ever, but then
//cleanup() is called multiple times
thd->lex->query_plan_footprint //&& // for "SET" command in SPs.
/*!thd->lex->query_plan_footprint->get_select(select_lex->select_number)*/)
{
const char *message= NULL;
if (!table_count || !tables_list || zero_result_cause)
{
/* It's a degenerate join */
message= zero_result_cause ? zero_result_cause : "No tables used";
}
save_qpf(thd->lex->query_plan_footprint,
need_tmp, // need_tmp_table
// !skip_sort_order && !no_order &&
// (order || group_list), // bool need_order
order != 0 && !skip_sort_order,
select_distinct, // bool distinct
message); // message
}
exec_qpf_saved= true;
}
DBUG_EXECUTE_IF("show_explain_probe_join_exec_end",
if (dbug_user_var_equals_int(thd,
"show_explain_probe_select_id",
@ -11151,7 +11181,7 @@ void JOIN::cleanup(bool full)
if (full)
{
//
/* Save it again */
#if 0
if (select_lex->select_number != UINT_MAX &&
select_lex->select_number != INT_MAX /* this is not a UNION's "fake select */ &&
@ -11159,8 +11189,8 @@ void JOIN::cleanup(bool full)
have_query_plan != QEP_DELETED && // this happens when there was no QEP ever, but then
//cleanup() is called multiple times
thd->lex->query_plan_footprint && // for "SET" command in SPs.
!thd->lex->query_plan_footprint->get_select(select_lex->select_number))
thd->lex->query_plan_footprint //&& // for "SET" command in SPs.
/*!thd->lex->query_plan_footprint->get_select(select_lex->select_number)*/)
{
const char *message= NULL;
@ -11178,8 +11208,6 @@ void JOIN::cleanup(bool full)
message); // message
}
#endif
//
have_query_plan= QEP_DELETED; //psergey: this is a problem!
}

View file

@ -1336,7 +1336,10 @@ public:
pre_sort_join_tab= NULL;
emb_sjm_nest= NULL;
sjm_lookup_tables= 0;
exec_qpf_saved= false;
}
bool exec_qpf_saved;
int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
COND *conds, uint og_num, ORDER *order, ORDER *group,

View file

@ -617,6 +617,7 @@ bool st_select_lex_unit::exec()
ulonglong add_rows=0;
ha_rows examined_rows= 0;
DBUG_ENTER("st_select_lex_unit::exec");
bool was_executed= executed;
if (executed && !uncacheable && !describe)
DBUG_RETURN(FALSE);
@ -626,8 +627,8 @@ bool st_select_lex_unit::exec()
saved_error= optimize();
save_union_qpf(thd->lex->query_plan_footprint);
if (!was_executed && thd->lex->query_plan_footprint)
save_union_qpf(thd->lex->query_plan_footprint);
if (uncacheable || !item || !item->assigned() || describe)
{
@ -776,8 +777,8 @@ bool st_select_lex_unit::exec()
if (!fake_select_lex->ref_pointer_array)
fake_select_lex->n_child_sum_items+= global_parameters->n_sum_items;
save_union_qpf_part2(thd->lex->query_plan_footprint);
if (!was_executed && thd->lex->query_plan_footprint)
save_union_qpf_part2(thd->lex->query_plan_footprint);
saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
&result_table_list,