Commit 6519ca51 authored by Sergey Petrunya's avatar Sergey Petrunya

EXPLAIN UPDATE/DELETE

- Make EXPLAIN UPDATE/DELETE work inside SPs
- Return correct error code from mysql_delete()
- EXPLAIN <multi-DELETE> will create a multi_delete object (as it 
  affects the optimization). select_result will be only used for 
  producing EXPLAIN output.
parent e8eeb2e7
......@@ -49,7 +49,7 @@ id select_type table type possible_keys key key_len ref rows Extra
explain delete t1 from t0, t1 where t0.a = t1.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 ALL NULL NULL NULL NULL 8 Using where
1 SIMPLE t1 ref a a 5 test.t0.a 4 Using index
1 SIMPLE t1 ref a a 5 test.t0.a 4
drop table t0, t1;
# ###################################################################
# ## EXPLAIN UPDATE tests
......
......@@ -313,14 +313,26 @@ sp_get_flags_for_command(LEX *lex)
flags= sp_head::HAS_COMMIT_OR_ROLLBACK;
break;
case SQLCOM_DELETE:
case SQLCOM_DELETE_MULTI:
{
if (lex->select_lex.item_list.is_empty())
/*
DELETE normally doesn't return resultset, but there are two exceptions:
- DELETE ... RETURNING
- EXPLAIN DELETE ...
*/
if (lex->select_lex.item_list.is_empty() && !lex->describe)
flags= 0;
else
flags= sp_head::MULTI_RESULTS;
break;
}
case SQLCOM_UPDATE:
case SQLCOM_UPDATE_MULTI:
{
if (!lex->describe)
flags= 0;
else
{
/* This is DELETE ... RETURNING ... */
flags= sp_head::MULTI_RESULTS;
}
break;
}
default:
......@@ -2988,7 +3000,6 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
}
reinit_stmt_before_use(thd, m_lex);
// not here, but inside every instr: create_qpf_query(m_lex);
if (open_tables)
res= instr->exec_open_and_lock_tables(thd, m_lex->query_tables);
......
......@@ -183,7 +183,6 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
bool const_cond_result;
ha_rows deleted= 0;
bool reverse= FALSE;
bool err= true;
ORDER *order= (ORDER *) ((order_list && order_list->elements) ?
order_list->first : NULL);
SELECT_LEX *select_lex= &thd->lex->select_lex;
......@@ -659,7 +658,7 @@ exit_without_my_ok:
List<Item> dummy; /* note: looked in 5.6 and they too use a dummy list like this */
result2->prepare(dummy, &thd->lex->unit);
thd->send_explain_fields(result2);
int err2= thd->lex->query_plan_footprint->print_explain(result2, 0 /* explain flags*/);
int err2= thd->lex->query_plan_footprint->print_explain(result2, thd->lex->describe);
if (err2)
result2->abort_result_set();
......@@ -669,7 +668,7 @@ exit_without_my_ok:
delete select;
free_underlaid_joins(thd, select_lex);
//table->set_keyread(false);
DBUG_RETURN((err || thd->is_error() || thd->killed) ? 1 : 0);
DBUG_RETURN((err2 || thd->is_error() || thd->killed) ? 1 : 0);
}
......
......@@ -3332,18 +3332,7 @@ end_with_restore_list:
if (!thd->is_fatal_error)
{
if (explain)
{
result= new select_send();
if (thd->send_explain_fields(result))
{
delete result;
result= NULL;
}
}
else
result= new multi_delete(aux_tables, lex->table_count);
result= new multi_delete(aux_tables, lex->table_count);
if (result)
{
res= mysql_select(thd, &select_lex->ref_pointer_array,
......@@ -3362,20 +3351,22 @@ end_with_restore_list:
if (!explain)
{
MYSQL_MULTI_DELETE_DONE(res, del_result->num_deleted());
if (res)
result->abort_result_set(); /* for both DELETE and EXPLAIN DELETE */
}
else
{
result->reset_offset_limit();
thd->lex->query_plan_footprint->print_explain(result,
thd->lex->describe);
}
if (res)
result->abort_result_set(); /* for both DELETE and EXPLAIN DELETE */
else
{
if (explain)
result->send_eof();
if (!res)
{
select_result *result= new select_send();
LEX *lex= thd->lex;
if (thd->send_explain_fields(result) ||
lex->query_plan_footprint->print_explain(result, lex->describe) ||
result->send_eof())
res= 1;
}
else
result->abort_result_set(); /* for both DELETE and EXPLAIN DELETE */
}
delete result;
}
......
......@@ -22990,10 +22990,13 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order,
unit= unit->next_unit())
{
/*
Display subqueries only if they are not parts of eliminated WHERE/ON
clauses.
Display subqueries only if
(1) they are not parts of ON clauses that were eliminated by table
elimination.
(2) they are not merged derived tables
*/
if (!(unit->item && unit->item->eliminated))
if (!(unit->item && unit->item->eliminated) && // (1)
(!unit->derived || unit->derived->is_materialized_derived())) // (2)
{
qp_node->add_child(unit->first_select()->select_number);
}
......
......@@ -1039,8 +1039,8 @@ 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 /* explain flags*/);
int err2= thd->lex->query_plan_footprint->print_explain(result,
thd->lex->describe);
if (err2)
result->abort_result_set();
else
......@@ -1048,7 +1048,7 @@ exit_without_my_ok:
delete select;
free_underlaid_joins(thd, select_lex);
DBUG_RETURN((error >= 0 || thd->is_error()) ? 1 : 0);
DBUG_RETURN((err2 || thd->is_error()) ? 1 : 0);
}
/*
......@@ -1518,7 +1518,7 @@ bool mysql_multi_update(THD *thd,
{
if (explain)
{
thd->lex->query_plan_footprint->print_explain(output, 0);
thd->lex->query_plan_footprint->print_explain(output, thd->lex->describe);
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