diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sql_delete.cc | 29 | ||||
-rw-r--r-- | sql/sql_parse.cc | 39 |
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; |