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;
|
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
|
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 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;
|
drop table t0, t1;
|
||||||
#
|
#
|
||||||
# Try DELETE ... RETURNING ...
|
# Try DELETE ... RETURNING ...
|
||||||
|
@ -4182,6 +4182,8 @@ class multi_update :public select_result_interceptor
|
|||||||
*/
|
*/
|
||||||
bool error_handled;
|
bool error_handled;
|
||||||
|
|
||||||
|
/* Need this to protect against multiple prepare() calls */
|
||||||
|
bool prepared;
|
||||||
public:
|
public:
|
||||||
multi_update(TABLE_LIST *ut, List<TABLE_LIST> *leaves_list,
|
multi_update(TABLE_LIST *ut, List<TABLE_LIST> *leaves_list,
|
||||||
List<Item> *fields, List<Item> *values,
|
List<Item> *fields, List<Item> *values,
|
||||||
|
@ -1464,24 +1464,8 @@ bool mysql_multi_update(THD *thd,
|
|||||||
multi_update **result)
|
multi_update **result)
|
||||||
{
|
{
|
||||||
bool res;
|
bool res;
|
||||||
select_result *output;
|
|
||||||
bool explain= test(thd->lex->describe);
|
|
||||||
DBUG_ENTER("mysql_multi_update");
|
DBUG_ENTER("mysql_multi_update");
|
||||||
|
|
||||||
if (explain)
|
|
||||||
{
|
|
||||||
/* 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,
|
if (!(*result= new multi_update(table_list,
|
||||||
&thd->lex->select_lex.leaf_tables,
|
&thd->lex->select_lex.leaf_tables,
|
||||||
fields, values,
|
fields, values,
|
||||||
@ -1489,8 +1473,6 @@ bool mysql_multi_update(THD *thd,
|
|||||||
{
|
{
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
output= *result;
|
|
||||||
}
|
|
||||||
|
|
||||||
thd->abort_on_warning= test(thd->variables.sql_mode &
|
thd->abort_on_warning= test(thd->variables.sql_mode &
|
||||||
(MODE_STRICT_TRANS_TABLES |
|
(MODE_STRICT_TRANS_TABLES |
|
||||||
@ -1504,7 +1486,7 @@ bool mysql_multi_update(THD *thd,
|
|||||||
(ORDER *)NULL,
|
(ORDER *)NULL,
|
||||||
options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
|
options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
|
||||||
OPTION_SETUP_TABLES_DONE,
|
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()));
|
DBUG_PRINT("info",("res: %d report_error: %d", res, (int) thd->is_error()));
|
||||||
res|= thd->is_error();
|
res|= thd->is_error();
|
||||||
@ -1512,12 +1494,8 @@ bool mysql_multi_update(THD *thd,
|
|||||||
(*result)->abort_result_set();
|
(*result)->abort_result_set();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (explain)
|
if (thd->lex->describe)
|
||||||
{
|
res= thd->lex->explain->send_explain(thd);
|
||||||
thd->lex->explain->print_explain(output, thd->lex->describe);
|
|
||||||
output->send_eof();
|
|
||||||
delete output;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
thd->abort_on_warning= 0;
|
thd->abort_on_warning= 0;
|
||||||
DBUG_RETURN(res);
|
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),
|
tmp_tables(0), updated(0), found(0), fields(field_list),
|
||||||
values(value_list), table_count(0), copy_field(0),
|
values(value_list), table_count(0), copy_field(0),
|
||||||
handle_duplicates(handle_duplicates_arg), do_update(1), trans_safe(1),
|
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);
|
List_iterator<TABLE_LIST> ti(*leaves);
|
||||||
DBUG_ENTER("multi_update::prepare");
|
DBUG_ENTER("multi_update::prepare");
|
||||||
|
|
||||||
|
if (prepared)
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
prepared= true;
|
||||||
|
|
||||||
thd->count_cuted_fields= CHECK_FIELD_WARN;
|
thd->count_cuted_fields= CHECK_FIELD_WARN;
|
||||||
thd->cuted_fields=0L;
|
thd->cuted_fields=0L;
|
||||||
thd_proc_info(thd, "updating main table");
|
thd_proc_info(thd, "updating main table");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user