summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_delete.cc29
-rw-r--r--sql/sql_parse.cc39
2 files changed, 56 insertions, 12 deletions
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index c241cbf67c2..38fb897c4f8 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -258,8 +258,9 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
if (mysql_prepare_delete(thd, table_list, select_lex->with_wild,
select_lex->item_list, &conds))
DBUG_RETURN(TRUE);
-
- (void) result->prepare(select_lex->item_list, NULL);
+
+ if (with_select)
+ (void) result->prepare(select_lex->item_list, NULL);
if (thd->lex->current_select->first_cond_optimization)
{
@@ -672,17 +673,21 @@ cleanup:
}
DBUG_ASSERT(transactional_table || !deleted || thd->transaction.stmt.modified_non_trans_table);
- if (thd->lex->analyze_stmt)
- goto emit_explain_and_leave;
free_underlaid_joins(thd, select_lex);
if (error < 0 ||
(thd->lex->ignore && !thd->is_error() && !thd->is_fatal_error))
{
- if (!with_select)
- my_ok(thd, deleted);
- else
+ if (thd->lex->analyze_stmt)
+ {
+ error= 0;
+ goto send_nothing_and_leave;
+ }
+
+ if (with_select)
result->send_eof();
+ else
+ my_ok(thd, deleted);
DBUG_PRINT("info",("%ld records deleted",(long) deleted));
}
DBUG_RETURN(error >= 0 || thd->is_error());
@@ -695,13 +700,17 @@ produce_explain_and_leave:
*/
query_plan.save_explain_data(thd->lex->explain);
-emit_explain_and_leave:
- int err2= thd->lex->explain->send_explain(thd);
+send_nothing_and_leave:
+ /*
+ ANALYZE DELETE jumps here. We can't send explain right here, because
+ we might be using ANALYZE DELETE ...RETURNING, in which case we have
+ Protocol_discard active.
+ */
delete select;
free_underlaid_joins(thd, select_lex);
//table->set_keyread(false);
- DBUG_RETURN((err2 || thd->is_error() || thd->killed) ? 1 : 0);
+ DBUG_RETURN((thd->is_error() || thd->killed) ? 1 : 0);
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 78c98d2d7be..019fd55e3d8 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3567,12 +3567,47 @@ end_with_restore_list:
unit->set_limit(select_lex);
MYSQL_DELETE_START(thd->query());
- if (!(sel_result= lex->result) && !(sel_result= new select_send()))
- return 1;
+ Protocol *save_protocol;
+ bool replaced_protocol= false;
+
+ if (!select_lex->item_list.is_empty())
+ {
+ /* This is DELETE ... RETURNING. It will return output to the client */
+ if (thd->lex->analyze_stmt)
+ {
+ /*
+ Actually, it is ANALYZE .. DELETE .. RETURNING. We need to produce
+ output and then discard it.
+ */
+ sel_result= new select_send_analyze();
+ replaced_protocol= true;
+ save_protocol= thd->protocol;
+ thd->protocol= new Protocol_discard(thd);
+ }
+ else
+ {
+ if (!(sel_result= lex->result) && !(sel_result= new select_send()))
+ return 1;
+ }
+ }
+
res = mysql_delete(thd, all_tables,
select_lex->where, &select_lex->order_list,
unit->select_limit_cnt, select_lex->options,
sel_result);
+
+ if (replaced_protocol)
+ {
+ delete thd->protocol;
+ thd->protocol= save_protocol;
+ }
+
+ if (thd->lex->analyze_stmt || thd->lex->describe)
+ {
+ if (!res)
+ res= thd->lex->explain->send_explain(thd);
+ }
+
delete sel_result;
MYSQL_DELETE_DONE(res, (ulong) thd->get_row_count_func());
break;