diff options
author | Kristofer Pettersson <kristofer.pettersson@sun.com> | 2009-03-27 17:08:14 +0100 |
---|---|---|
committer | Kristofer Pettersson <kristofer.pettersson@sun.com> | 2009-03-27 17:08:14 +0100 |
commit | a20bc967cecb9a1254c446f9179c4dc80c18464b (patch) | |
tree | cd6d31bf2ada9b8620b1e976a5d2b69aae0f5609 /sql/sql_delete.cc | |
parent | ff37912ff43f0fdde68393ddae2a7629d6fe79f0 (diff) | |
download | mariadb-git-a20bc967cecb9a1254c446f9179c4dc80c18464b.tar.gz |
Bug#40127 Multiple table DELETE IGNORE hangs on foreign key constraint violation
on 5.0
The server crashes on an assert in net_end_statement indicating that the
Diagnostics area wasn't set properly during execution.
This happened on a multi table DELETE operation using the IGNORE keyword.
The keyword is suppose to allow for execution to continue on a best effort
despite some non-fatal errors. Instead execution stopped and no client
response was sent which would have led to a protocol error if it hadn't been
for the assert.
This patch corrects this issue by checking for the existence of an IGNORE
option before setting an error state during row-by-row delete iteration.
mysql-test/r/innodb_mysql.result:
* Added test case for bug40127
mysql-test/t/innodb_mysql.test:
* Added test case for bug40127
sql/sql_delete.cc:
* IGNORE option wasn't implemented in multi_delete::send_data
and multi_delete::do_deletes
Diffstat (limited to 'sql/sql_delete.cc')
-rw-r--r-- | sql/sql_delete.cc | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index d87eafa3e0c..1b42e522491 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -709,6 +709,8 @@ bool multi_delete::send_data(List<Item> &values) TABLE_LIST *del_table; DBUG_ENTER("multi_delete::send_data"); + bool ignore= thd->lex->current_select->no_error; + for (del_table= delete_tables; del_table; del_table= del_table->next_local, secure_counter++) @@ -741,8 +743,12 @@ bool multi_delete::send_data(List<Item> &values) TRG_ACTION_AFTER, FALSE)) DBUG_RETURN(1); } - else + else if (!ignore) { + /* + If the IGNORE option is used errors caused by ha_delete_row don't + have to stop the iteration. + */ table->file->print_error(error,MYF(0)); DBUG_RETURN(1); } @@ -834,6 +840,11 @@ int multi_delete::do_deletes() { int local_error= 0, counter= 0, tmp_error; bool will_batch; + /* + If the IGNORE option is used all non fatal errors will be translated + to warnings and we should not break the row-by-row iteration + */ + bool ignore= thd->lex->current_select->no_error; DBUG_ENTER("do_deletes"); DBUG_ASSERT(do_delete); @@ -872,18 +883,29 @@ int multi_delete::do_deletes() local_error= 1; break; } - if ((local_error=table->file->ha_delete_row(table->record[0]))) + + local_error= table->file->ha_delete_row(table->record[0]); + if (local_error && !ignore) { - table->file->print_error(local_error,MYF(0)); - break; + table->file->print_error(local_error,MYF(0)); + break; } - deleted++; - if (table->triggers && - table->triggers->process_triggers(thd, TRG_EVENT_DELETE, - TRG_ACTION_AFTER, FALSE)) + + /* + Increase the reported number of deleted rows only if no error occurred + during ha_delete_row. + Also, don't execute the AFTER trigger if the row operation failed. + */ + if (!local_error) { - local_error= 1; - break; + deleted++; + if (table->triggers && + table->triggers->process_triggers(thd, TRG_EVENT_DELETE, + TRG_ACTION_AFTER, FALSE)) + { + local_error= 1; + break; + } } } if (will_batch && (tmp_error= table->file->end_bulk_delete())) |