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.
This commit is contained in:
parent
a356cfbefb
commit
a06170c8d8
@ -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> ¬_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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user