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;
insert into t0 values (1),(2),(3),(4),(5),(6),(7),(8);
#
......
......@@ -49,6 +49,7 @@ void QPF_query::add_node(QPF_node *node)
if (node->get_type() == QPF_node::QPF_UNION)
{
QPF_union *u= (QPF_union*)node;
DBUG_ASSERT(!unions[u->get_select_id()]);
unions[u->get_select_id()]= u;
}
else
......@@ -60,7 +61,10 @@ void QPF_query::add_node(QPF_node *node)
DBUG_ASSERT(0);
}
else
{
DBUG_ASSERT(!selects[sel->select_id]);
selects[sel->select_id] = sel;
}
}
}
......@@ -493,7 +497,7 @@ int QPF_delete::print_explain(QPF_query *query, select_result_sink *output,
const char *msg= "Deleting all rows";
int res= print_explain_message_line(output, explain_flags,
1 /*select number*/,
"SIMPLE", msg);
select_type, msg);
return res;
}
......@@ -513,7 +517,7 @@ int QPF_update::print_explain(QPF_query *query, select_result_sink *output,
const char *msg= "Impossible where";
int res= print_explain_message_line(output, explain_flags,
1 /*select number*/,
"SIMPLE", msg);
select_type, msg);
return res;
}
......@@ -541,7 +545,7 @@ int QPF_update::print_explain(QPF_query *query, select_result_sink *output,
print_explain_row(output, explain_flags,
1, /* id */
"SIMPLE",
select_type,
table_name.c_ptr(),
// partitions,
jtype,
......
......@@ -350,6 +350,8 @@ public:
virtual enum qpf_node_type get_type() { return QPF_UPDATE; }
virtual int get_select_id() { return 1; /* always root */ }
const char *select_type;
bool impossible_where;
StringBuffer<64> table_name;
......
......@@ -58,10 +58,12 @@ void Delete_plan::save_query_plan_footprint(QPF_query *query)
if (deleting_all_rows)
{
qpf->deleting_all_rows= true;
qpf->select_type= "SIMPLE";
}
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;
......@@ -71,13 +73,14 @@ void Delete_plan::save_query_plan_footprint(QPF_query *query)
void Update_plan::save_query_plan_footprint(QPF_query *query)
{
QPF_update* qpf= new QPF_update;
save_query_plan_footprint_intern(qpf);
save_query_plan_footprint_intern(query, 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);
if (impossible_where)
{
......@@ -85,8 +88,10 @@ void Update_plan::save_query_plan_footprint_intern(QPF_update *qpf)
return;
}
// TODO: do we need the following: select_type
//select_lex->set_explain_type(TRUE);
qpf->impossible_where= false;
select_lex->set_explain_type(TRUE);
qpf->select_type= select_lex->type;
/* Set jtype */
if (select && select->quick)
......@@ -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);
}
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,
query_plan.select_lex= &thd->lex->select_lex;
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))
DBUG_RETURN(TRUE);
......@@ -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 */
result->prepare(dummy, &thd->lex->unit);
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)
result->abort_result_set();
......
......@@ -4337,6 +4337,13 @@ int st_select_lex_unit::save_qpf(QPF_query *output)
{
//int res= 0;
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;
/*
......
......@@ -730,10 +730,7 @@ public:
friend int subselect_union_engine::exec();
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);
};
......@@ -2379,6 +2376,7 @@ class Update_plan
protected:
bool impossible_where;
public:
bool updating_a_view;
TABLE *table;
SQL_SELECT *select;
uint index;
......@@ -2396,7 +2394,7 @@ public:
void set_impossible_where() { impossible_where= true; }
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() {}
Update_plan() : impossible_where(false), using_filesort(false) {}
......
......@@ -314,6 +314,10 @@ int mysql_update(THD *thd,
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE");
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 */
table->covering_keys= table->s->keys_in_use;
table->quick_keys.clear_all();
......@@ -1013,13 +1017,14 @@ exit_without_my_ok:
query_plan.save_query_plan_footprint(thd->lex->query_plan_footprint);
select_send *result;
bool printed_anything;
//bool printed_anything;
if (!(result= new select_send()))
return 1; /* purecov: inspected */
List<Item> dummy; /* note: looked in 5.6 and they too use a dummy list like this */
result->prepare(dummy, &thd->lex->unit);
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)
result->abort_result_set();
......@@ -1498,6 +1503,7 @@ bool mysql_multi_update(THD *thd,
{
if (explain)
{
thd->lex->query_plan_footprint->print_explain(output, 0);
output->send_eof();
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