Commit f33fc2fa authored by Igor Babaev's avatar Igor Babaev

MDEV-30539 EXPLAIN EXTENDED: no message with queries for DML statements

EXPLAIN EXTENDED for an UPDATE/DELETE/INSERT/REPLACE statement did not
produce the warning containing the text representation of the query
obtained after the optimization phase. Such warning was produced for
SELECT statements, but not for DML statements.
The patch fixes this defect of EXPLAIN EXTENDED for DML statements.
parent 011261f4
......@@ -788,6 +788,22 @@ INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
DROP TABLE t1;
--echo #75
CREATE TABLE t1 (id INT PRIMARY KEY, i INT);
--let $query = INSERT INTO t1 VALUES (3,10), (7,11), (3,11) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id);
--source include/explain_utils.inc
DROP TABLE t1;
--echo #76
CREATE TABLE t1 (id INT PRIMARY KEY, i INT);
CREATE TABLE t2 (a INT, b INT);
INSERT INTO t2 VALUES (1,10), (3,10), (7,11), (3,11);
--let $query = INSERT INTO t1 SELECT * FROM t2 ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id);
--source include/explain_utils.inc
DROP TABLE t1,t2;
--echo #
--echo # Bug #12949629: CLIENT LOSES CONNECTION AFTER EXECUTING A PROCEDURE WITH
--echo # EXPLAIN UPDATE/DEL/INS
......
......@@ -157,9 +157,13 @@ id select_type table partitions type possible_keys key key_len ref rows Extra
explain extended update t2 set b=3 where a in (3,4);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1003 update `test`.`t2` set `test`.`t2`.`b` = 3 where `test`.`t2`.`a` in (3,4)
explain extended delete from t2 where a in (3,4);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1003 delete from `test`.`t2` where `test`.`t2`.`a` in (3,4)
drop table t1,t2;
#
# Check the special case where partition pruning removed all partitions
......
......@@ -1253,7 +1253,7 @@ EXPLAIN
DROP TABLES t1, t2;
# End of 10.3 tests
#
# MDEV-28538: multi-table UPDATE/DELETE with possible exists-to-in
# MDEV-30538: multi-table UPDATE/DELETE with possible exists-to-in
#
create table t1 (c1 int, c2 int, c3 int, index idx(c2));
insert into t1 values
......
......@@ -1134,7 +1134,7 @@ DROP TABLES t1, t2;
--echo # End of 10.3 tests
--echo #
--echo # MDEV-28538: multi-table UPDATE/DELETE with possible exists-to-in
--echo # MDEV-30538: multi-table UPDATE/DELETE with possible exists-to-in
--echo #
create table t1 (c1 int, c2 int, c3 int, index idx(c2));
......
......@@ -3766,7 +3766,7 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
"select_id": 1,
"steps": [
{
"expanded_query": "select NULL AS `NULL` from t0 join t1 where t0.a = t1.a and t1.a < 3"
"expanded_query": "delete from t0,t1 using t0 join t1 where t0.a = t1.a and t1.a < 3"
}
]
}
......
......@@ -5566,11 +5566,15 @@ EXPLAIN EXTENDED UPDATE t3 SET c3 = ( SELECT COUNT(d1.c1) FROM ( SELECT a11.c1 F
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 0 100.00
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
Note 1003 /* select#1 */ update `test`.`t3` set `test`.`t3`.`c3` = (/* select#2 */ select count(NULL) from `test`.`t1` `a11` straight_join `test`.`t2` `a21` join `test`.`t1` `a12` where 0)
PREPARE stmt FROM "EXPLAIN EXTENDED UPDATE t3 SET c3 = ( SELECT COUNT(d1.c1) FROM ( SELECT a11.c1 FROM t1 AS a11 STRAIGHT_JOIN t2 AS a21 ON a21.c2 = a11.c1 JOIN t1 AS a12 ON a12.c1 = a11.c1 ) d1 )";
EXECUTE stmt;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 0 100.00
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
Note 1003 /* select#1 */ update `test`.`t3` set `test`.`t3`.`c3` = (/* select#2 */ select count(NULL) from `test`.`t1` `a11` straight_join `test`.`t2` `a21` join `test`.`t1` `a12` where 0)
DEALLOCATE PREPARE stmt;
DROP TABLE t1, t2, t3;
#
......
......@@ -171,6 +171,8 @@ x
explain extended delete history from t1 before system_time '2039-01-01 23:00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 1 100.00 Using where
Warnings:
Note 1003 delete from `test`.`t1` FOR SYSTEM_TIME BEFORE TIMESTAMP '2039-01-01 23:00' where `test`.`t1`.`row_end` < '2039-01-01 23:00' and is_history(`test`.`t1`.`row_end`)
create or replace procedure p() delete history from t1 before system_time '2039-01-01 23:00';
call p;
select * from t1;
......
......@@ -1084,6 +1084,8 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list,
DBUG_RETURN(TRUE);
select_lex->fix_prepare_information(thd, conds, &fake_conds);
if (!thd->lex->upd_del_where)
thd->lex->upd_del_where= *conds;
DBUG_RETURN(FALSE);
}
......
......@@ -161,7 +161,7 @@ void Explain_query::query_plan_ready()
Send EXPLAIN output to the client.
*/
int Explain_query::send_explain(THD *thd)
int Explain_query::send_explain(THD *thd, bool extended)
{
select_result *result;
LEX *lex= thd->lex;
......@@ -174,8 +174,22 @@ int Explain_query::send_explain(THD *thd)
if (thd->lex->explain_json)
print_explain_json(result, thd->lex->analyze_stmt);
else
{
res= print_explain(result, lex->describe, thd->lex->analyze_stmt);
if (extended)
{
char buff[1024];
String str(buff,(uint32) sizeof(buff), system_charset_info);
str.length(0);
/*
The warnings system requires input in utf8, @see
mysqld_show_warnings().
*/
lex->unit.print(&str, QT_EXPLAIN_EXTENDED);
push_warning(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_YES, str.c_ptr_safe());
}
}
if (res)
result->abort_result_set();
else
......@@ -185,6 +199,7 @@ int Explain_query::send_explain(THD *thd)
}
/*
The main entry point to print EXPLAIN of the entire query
*/
......
......@@ -474,7 +474,7 @@ class Explain_query : public Sql_alloc
bool is_analyze);
/* Send tabular EXPLAIN to the client */
int send_explain(THD *thd);
int send_explain(THD *thd, bool extended);
/* Return tabular EXPLAIN output as a text string */
bool print_explain_str(THD *thd, String *out_str, bool is_analyze);
......
......@@ -827,7 +827,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
save_insert_query_plan(thd, table_list);
if (thd->lex->describe)
{
retval= thd->lex->explain->send_explain(thd);
bool extended= thd->lex->describe & DESCRIBE_EXTENDED;
retval= thd->lex->explain->send_explain(thd, extended);
goto abort;
}
......@@ -1250,7 +1251,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
goto abort;
if (thd->lex->analyze_stmt)
{
retval= thd->lex->explain->send_explain(thd);
bool extended= thd->lex->describe & DESCRIBE_EXTENDED;
retval= thd->lex->explain->send_explain(thd, extended);
goto abort;
}
DBUG_PRINT("info", ("touched: %llu copied: %llu updated: %llu deleted: %llu",
......
......@@ -780,6 +780,8 @@ void LEX::start(THD *thd_arg)
frame_bottom_bound= NULL;
win_spec= NULL;
upd_del_where= NULL;
vers_conditions.empty();
period_conditions.empty();
......
......@@ -1417,6 +1417,10 @@ class st_select_lex: public st_select_lex_node
}
bool setup_ref_array(THD *thd, uint order_group_num);
void print(THD *thd, String *str, enum_query_type query_type);
void print_item_list(THD *thd, String *str, enum_query_type query_type);
void print_set_clause(THD *thd, String *str, enum_query_type query_type);
void print_on_duplicate_key_clause(THD *thd, String *str,
enum_query_type query_type);
static void print_order(String *str,
ORDER *order,
enum_query_type query_type);
......@@ -3493,6 +3497,8 @@ struct LEX: public Query_tables_list
Window_frame_bound *frame_bottom_bound;
Window_spec *win_spec;
Item *upd_del_where;
/* System Versioning */
vers_select_conds_t vers_conditions;
vers_select_conds_t period_conditions;
......
......@@ -4744,7 +4744,10 @@ mysql_execute_command(THD *thd)
}
if (!res && (explain || lex->analyze_stmt))
res= thd->lex->explain->send_explain(thd);
{
bool extended= thd->lex->describe & DESCRIBE_EXTENDED;
res= thd->lex->explain->send_explain(thd, extended);
}
/* revert changes for SP */
MYSQL_INSERT_SELECT_DONE(res, (ulong) thd->get_row_count_func());
......@@ -4813,7 +4816,10 @@ mysql_execute_command(THD *thd)
if (thd->lex->analyze_stmt || thd->lex->describe)
{
if (!res)
res= thd->lex->explain->send_explain(thd);
{
bool extended= thd->lex->describe & DESCRIBE_EXTENDED;
res= thd->lex->explain->send_explain(thd, extended);
}
}
delete sel_result;
......@@ -4875,7 +4881,10 @@ mysql_execute_command(THD *thd)
else
{
if (lex->describe || lex->analyze_stmt)
res= thd->lex->explain->send_explain(thd);
{
bool extended= thd->lex->describe & DESCRIBE_EXTENDED;
res= thd->lex->explain->send_explain(thd, extended);
}
}
multi_delete_error:
delete result;
......@@ -6463,7 +6472,10 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
thd->protocol= save_protocol;
}
if (!res)
res= thd->lex->explain->send_explain(thd);
{
bool extended= thd->lex->describe & DESCRIBE_EXTENDED;
res= thd->lex->explain->send_explain(thd, extended);
}
}
}
}
......
This diff is collapsed.
......@@ -1371,7 +1371,8 @@ int mysql_update(THD *thd,
goto err;
emit_explain_and_leave:
int err2= thd->lex->explain->send_explain(thd);
bool extended= thd->lex->describe & DESCRIBE_EXTENDED;
int err2= thd->lex->explain->send_explain(thd, extended);
delete select;
free_underlaid_joins(thd, select_lex);
......@@ -1445,6 +1446,8 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
select_lex->fix_prepare_information(thd, conds, &fake_conds);
if (!thd->lex->upd_del_where)
thd->lex->upd_del_where= *conds;
DBUG_RETURN(FALSE);
}
......@@ -1974,7 +1977,10 @@ bool mysql_multi_update(THD *thd, TABLE_LIST *table_list, List<Item> *fields,
else
{
if (thd->lex->describe || thd->lex->analyze_stmt)
res= thd->lex->explain->send_explain(thd);
{
bool extended= thd->lex->describe & DESCRIBE_EXTENDED;
res= thd->lex->explain->send_explain(thd, extended);
}
}
thd->abort_on_warning= 0;
DBUG_RETURN(res);
......
......@@ -2708,6 +2708,8 @@ struct TABLE_LIST
}
void print(THD *thd, table_map eliminated_tables, String *str,
enum_query_type query_type);
void print_leaf_tables(THD *thd, String *str,
enum_query_type query_type);
bool check_single_table(TABLE_LIST **table, table_map map,
TABLE_LIST *view);
bool set_insert_values(MEM_ROOT *mem_root);
......
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