Commit a06170c8 authored by Sergey Petrunya's avatar Sergey Petrunya

MDEV-3798: EXPLAIN UPDATE/DELETE

- Fix a problem with EXPLAIN multi_table UPDATE: 
  = Do use multi_update object, because multi_update::prepare() does
    various setup, e.g. it disables index-only for the tables to be updated.
  = Protect multi_update::prepare() from being invoked multiple times. 
    If the query has subqueries, they may try to invoke it, for some reason.
parent a356cfbe
......@@ -100,7 +100,7 @@ id select_type table type possible_keys key key_len ref rows Extra
explain update t0, t1 set t1.a=t1.a+1 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;
#
# Try DELETE ... RETURNING ...
......
......@@ -4181,7 +4181,9 @@ class multi_update :public select_result_interceptor
so that afterward send_error() needs to find out that.
*/
bool error_handled;
/* Need this to protect against multiple prepare() calls */
bool prepared;
public:
multi_update(TABLE_LIST *ut, List<TABLE_LIST> *leaves_list,
List<Item> *fields, List<Item> *values,
......
......@@ -1464,32 +1464,14 @@ bool mysql_multi_update(THD *thd,
multi_update **result)
{
bool res;
select_result *output;
bool explain= test(thd->lex->describe);
DBUG_ENTER("mysql_multi_update");
if (explain)
if (!(*result= new multi_update(table_list,
&thd->lex->select_lex.leaf_tables,
fields, values,
handle_duplicates, ignore)))
{
/* Handle EXPLAIN UPDATE */
if (!(output= new select_send()) ||
thd->send_explain_fields(output))
{
delete output;
DBUG_RETURN(TRUE);
}
select_lex->set_explain_type(FALSE);
*result= NULL; /* no multi_update object */
}
else
{
if (!(*result= new multi_update(table_list,
&thd->lex->select_lex.leaf_tables,
fields, values,
handle_duplicates, ignore)))
{
DBUG_RETURN(TRUE);
}
output= *result;
DBUG_RETURN(TRUE);
}
thd->abort_on_warning= test(thd->variables.sql_mode &
......@@ -1504,7 +1486,7 @@ bool mysql_multi_update(THD *thd,
(ORDER *)NULL,
options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
OPTION_SETUP_TABLES_DONE,
output, unit, select_lex);
*result, unit, select_lex);
DBUG_PRINT("info",("res: %d report_error: %d", res, (int) thd->is_error()));
res|= thd->is_error();
......@@ -1512,12 +1494,8 @@ bool mysql_multi_update(THD *thd,
(*result)->abort_result_set();
else
{
if (explain)
{
thd->lex->explain->print_explain(output, thd->lex->describe);
output->send_eof();
delete output;
}
if (thd->lex->describe)
res= thd->lex->explain->send_explain(thd);
}
thd->abort_on_warning= 0;
DBUG_RETURN(res);
......@@ -1533,7 +1511,7 @@ multi_update::multi_update(TABLE_LIST *table_list,
tmp_tables(0), updated(0), found(0), fields(field_list),
values(value_list), table_count(0), copy_field(0),
handle_duplicates(handle_duplicates_arg), do_update(1), trans_safe(1),
transactional_tables(0), ignore(ignore_arg), error_handled(0)
transactional_tables(0), ignore(ignore_arg), error_handled(0), prepared(0)
{}
......@@ -1556,6 +1534,10 @@ int multi_update::prepare(List<Item> &not_used_values,
List_iterator<TABLE_LIST> ti(*leaves);
DBUG_ENTER("multi_update::prepare");
if (prepared)
DBUG_RETURN(0);
prepared= true;
thd->count_cuted_fields= CHECK_FIELD_WARN;
thd->cuted_fields=0L;
thd_proc_info(thd, "updating main table");
......
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