Commit 52cfa54c authored by Sergey Petrunya's avatar Sergey Petrunya

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

Single table UPDATE/DELETE
- Correctly print type=SIMPLE vs type=PRIMARY
- Handle UPDATE/DELETE of mergeable VIEWs: we get the 
  VIEW's select as the first subquery. 
  (MySQL 5.6 doesn't print it because it finds that the
   subquery is not attached to any select)
parent 0a560289
drop table if exists t0; drop table if exists t0, t1;
create table t0 (a int) engine=myisam; create table t0 (a int) engine=myisam;
insert into t0 values (1),(2),(3),(4),(5),(6),(7),(8); insert into t0 values (1),(2),(3),(4),(5),(6),(7),(8);
# #
......
...@@ -49,6 +49,7 @@ void QPF_query::add_node(QPF_node *node) ...@@ -49,6 +49,7 @@ void QPF_query::add_node(QPF_node *node)
if (node->get_type() == QPF_node::QPF_UNION) if (node->get_type() == QPF_node::QPF_UNION)
{ {
QPF_union *u= (QPF_union*)node; QPF_union *u= (QPF_union*)node;
DBUG_ASSERT(!unions[u->get_select_id()]);
unions[u->get_select_id()]= u; unions[u->get_select_id()]= u;
} }
else else
...@@ -60,7 +61,10 @@ void QPF_query::add_node(QPF_node *node) ...@@ -60,7 +61,10 @@ void QPF_query::add_node(QPF_node *node)
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
else else
{
DBUG_ASSERT(!selects[sel->select_id]);
selects[sel->select_id] = sel; selects[sel->select_id] = sel;
}
} }
} }
...@@ -493,7 +497,7 @@ int QPF_delete::print_explain(QPF_query *query, select_result_sink *output, ...@@ -493,7 +497,7 @@ int QPF_delete::print_explain(QPF_query *query, select_result_sink *output,
const char *msg= "Deleting all rows"; const char *msg= "Deleting all rows";
int res= print_explain_message_line(output, explain_flags, int res= print_explain_message_line(output, explain_flags,
1 /*select number*/, 1 /*select number*/,
"SIMPLE", msg); select_type, msg);
return res; return res;
} }
...@@ -513,7 +517,7 @@ int QPF_update::print_explain(QPF_query *query, select_result_sink *output, ...@@ -513,7 +517,7 @@ int QPF_update::print_explain(QPF_query *query, select_result_sink *output,
const char *msg= "Impossible where"; const char *msg= "Impossible where";
int res= print_explain_message_line(output, explain_flags, int res= print_explain_message_line(output, explain_flags,
1 /*select number*/, 1 /*select number*/,
"SIMPLE", msg); select_type, msg);
return res; return res;
} }
...@@ -541,7 +545,7 @@ int QPF_update::print_explain(QPF_query *query, select_result_sink *output, ...@@ -541,7 +545,7 @@ int QPF_update::print_explain(QPF_query *query, select_result_sink *output,
print_explain_row(output, explain_flags, print_explain_row(output, explain_flags,
1, /* id */ 1, /* id */
"SIMPLE", select_type,
table_name.c_ptr(), table_name.c_ptr(),
// partitions, // partitions,
jtype, jtype,
......
...@@ -350,6 +350,8 @@ public: ...@@ -350,6 +350,8 @@ public:
virtual enum qpf_node_type get_type() { return QPF_UPDATE; } virtual enum qpf_node_type get_type() { return QPF_UPDATE; }
virtual int get_select_id() { return 1; /* always root */ } virtual int get_select_id() { return 1; /* always root */ }
const char *select_type;
bool impossible_where; bool impossible_where;
StringBuffer<64> table_name; StringBuffer<64> table_name;
......
...@@ -58,10 +58,12 @@ void Delete_plan::save_query_plan_footprint(QPF_query *query) ...@@ -58,10 +58,12 @@ void Delete_plan::save_query_plan_footprint(QPF_query *query)
if (deleting_all_rows) if (deleting_all_rows)
{ {
qpf->deleting_all_rows= true; qpf->deleting_all_rows= true;
qpf->select_type= "SIMPLE";
} }
else else
{ {
Update_plan::save_query_plan_footprint_intern(qpf); qpf->deleting_all_rows= false;
Update_plan::save_query_plan_footprint_intern(query, qpf);
} }
query->upd_del_plan= qpf; query->upd_del_plan= qpf;
...@@ -71,13 +73,14 @@ void Delete_plan::save_query_plan_footprint(QPF_query *query) ...@@ -71,13 +73,14 @@ void Delete_plan::save_query_plan_footprint(QPF_query *query)
void Update_plan::save_query_plan_footprint(QPF_query *query) void Update_plan::save_query_plan_footprint(QPF_query *query)
{ {
QPF_update* qpf= new QPF_update; QPF_update* qpf= new QPF_update;
save_query_plan_footprint_intern(qpf); save_query_plan_footprint_intern(query, qpf);
query->upd_del_plan= qpf; query->upd_del_plan= qpf;
} }
void Update_plan::save_query_plan_footprint_intern(QPF_update *qpf) void Update_plan::save_query_plan_footprint_intern(QPF_query *query, QPF_update *qpf)
{ {
qpf->select_type= "SIMPLE";
qpf->table_name.append(table->pos_in_table_list->alias); qpf->table_name.append(table->pos_in_table_list->alias);
if (impossible_where) if (impossible_where)
{ {
...@@ -85,8 +88,10 @@ void Update_plan::save_query_plan_footprint_intern(QPF_update *qpf) ...@@ -85,8 +88,10 @@ void Update_plan::save_query_plan_footprint_intern(QPF_update *qpf)
return; return;
} }
// TODO: do we need the following: select_type qpf->impossible_where= false;
//select_lex->set_explain_type(TRUE);
select_lex->set_explain_type(TRUE);
qpf->select_type= select_lex->type;
/* Set jtype */ /* Set jtype */
if (select && select->quick) if (select && select->quick)
...@@ -134,6 +139,28 @@ void Update_plan::save_query_plan_footprint_intern(QPF_update *qpf) ...@@ -134,6 +139,28 @@ void Update_plan::save_query_plan_footprint_intern(QPF_update *qpf)
{ {
explain_append_mrr_info((QUICK_RANGE_SELECT*)select->quick, &qpf->mrr_type); explain_append_mrr_info((QUICK_RANGE_SELECT*)select->quick, &qpf->mrr_type);
} }
bool skip= updating_a_view;
/* Save subquery children */
for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit();
unit;
unit= unit->next_unit())
{
if (skip)
{
skip= false;
continue;
}
/*
Display subqueries only if they are not parts of eliminated WHERE/ON
clauses.
*/
if (!(unit->item && unit->item->eliminated))
qpf->add_child(unit->first_select()->select_number);
//TODO: temporary?:
unit->save_qpf(query);
}
} }
...@@ -194,6 +221,9 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ...@@ -194,6 +221,9 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
query_plan.select_lex= &thd->lex->select_lex; query_plan.select_lex= &thd->lex->select_lex;
query_plan.table= table; query_plan.table= table;
//psergey-todo: Ugly, discuss with Sanja
query_plan.updating_a_view= test(table_list->view);
if (mysql_prepare_delete(thd, table_list, &conds)) if (mysql_prepare_delete(thd, table_list, &conds))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
...@@ -612,7 +642,7 @@ exit_without_my_ok: ...@@ -612,7 +642,7 @@ exit_without_my_ok:
List<Item> dummy; /* note: looked in 5.6 and they too use a dummy list like this */ List<Item> dummy; /* note: looked in 5.6 and they too use a dummy list like this */
result->prepare(dummy, &thd->lex->unit); result->prepare(dummy, &thd->lex->unit);
thd->send_explain_fields(result); thd->send_explain_fields(result);
int err2= thd->lex->query_plan_footprint->print_explain(result, 0); int err2= thd->lex->query_plan_footprint->print_explain(result, 0 /* explain flags*/);
if (err2) if (err2)
result->abort_result_set(); result->abort_result_set();
......
...@@ -4337,6 +4337,13 @@ int st_select_lex_unit::save_qpf(QPF_query *output) ...@@ -4337,6 +4337,13 @@ int st_select_lex_unit::save_qpf(QPF_query *output)
{ {
//int res= 0; //int res= 0;
SELECT_LEX *first= first_select(); SELECT_LEX *first= first_select();
if (!first->next_select())
{
/* This is a 1-way UNION, i.e. not really a UNION */
first->save_qpf(output);
return 0;
}
QPF_union *qpfu= new QPF_union; QPF_union *qpfu= new QPF_union;
/* /*
......
...@@ -730,10 +730,7 @@ public: ...@@ -730,10 +730,7 @@ public:
friend int subselect_union_engine::exec(); friend int subselect_union_engine::exec();
List<Item> *get_unit_column_types(); List<Item> *get_unit_column_types();
#if 0
int print_explain(select_result_sink *output, uint8 explain_flags,
bool *printed_anything);
#endif
int save_qpf(QPF_query *output); int save_qpf(QPF_query *output);
}; };
...@@ -2379,6 +2376,7 @@ class Update_plan ...@@ -2379,6 +2376,7 @@ class Update_plan
protected: protected:
bool impossible_where; bool impossible_where;
public: public:
bool updating_a_view;
TABLE *table; TABLE *table;
SQL_SELECT *select; SQL_SELECT *select;
uint index; uint index;
...@@ -2396,7 +2394,7 @@ public: ...@@ -2396,7 +2394,7 @@ public:
void set_impossible_where() { impossible_where= true; } void set_impossible_where() { impossible_where= true; }
void save_query_plan_footprint(QPF_query *query); void save_query_plan_footprint(QPF_query *query);
void save_query_plan_footprint_intern(QPF_update *qpf); void save_query_plan_footprint_intern(QPF_query *query, QPF_update *qpf);
virtual ~Update_plan() {} virtual ~Update_plan() {}
Update_plan() : impossible_where(false), using_filesort(false) {} Update_plan() : impossible_where(false), using_filesort(false) {}
......
...@@ -314,6 +314,10 @@ int mysql_update(THD *thd, ...@@ -314,6 +314,10 @@ int mysql_update(THD *thd,
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE"); my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE");
DBUG_RETURN(1); DBUG_RETURN(1);
} }
//psergey-todo: Ugly, discuss with Sanja
query_plan.updating_a_view= test(table_list->view);
/* Calculate "table->covering_keys" based on the WHERE */ /* Calculate "table->covering_keys" based on the WHERE */
table->covering_keys= table->s->keys_in_use; table->covering_keys= table->s->keys_in_use;
table->quick_keys.clear_all(); table->quick_keys.clear_all();
...@@ -1013,13 +1017,14 @@ exit_without_my_ok: ...@@ -1013,13 +1017,14 @@ exit_without_my_ok:
query_plan.save_query_plan_footprint(thd->lex->query_plan_footprint); query_plan.save_query_plan_footprint(thd->lex->query_plan_footprint);
select_send *result; select_send *result;
bool printed_anything; //bool printed_anything;
if (!(result= new select_send())) if (!(result= new select_send()))
return 1; /* purecov: inspected */ return 1; /* purecov: inspected */
List<Item> dummy; /* note: looked in 5.6 and they too use a dummy list like this */ List<Item> dummy; /* note: looked in 5.6 and they too use a dummy list like this */
result->prepare(dummy, &thd->lex->unit); result->prepare(dummy, &thd->lex->unit);
thd->send_explain_fields(result); thd->send_explain_fields(result);
int err2= thd->lex->print_explain(result, 0 /* explain flags*/, &printed_anything); //int err2= thd->lex->print_explain(result, 0 /* explain flags*/, &printed_anything);
int err2= thd->lex->query_plan_footprint->print_explain(result, 0 /* explain flags*/);
if (err2) if (err2)
result->abort_result_set(); result->abort_result_set();
...@@ -1498,6 +1503,7 @@ bool mysql_multi_update(THD *thd, ...@@ -1498,6 +1503,7 @@ bool mysql_multi_update(THD *thd,
{ {
if (explain) if (explain)
{ {
thd->lex->query_plan_footprint->print_explain(output, 0);
output->send_eof(); output->send_eof();
delete output; delete output;
} }
......
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