summaryrefslogtreecommitdiff
path: root/sql/sql_delete.cc
diff options
context:
space:
mode:
authorKristofer Pettersson <kristofer.pettersson@sun.com>2009-03-27 17:08:14 +0100
committerKristofer Pettersson <kristofer.pettersson@sun.com>2009-03-27 17:08:14 +0100
commita20bc967cecb9a1254c446f9179c4dc80c18464b (patch)
treecd6d31bf2ada9b8620b1e976a5d2b69aae0f5609 /sql/sql_delete.cc
parentff37912ff43f0fdde68393ddae2a7629d6fe79f0 (diff)
downloadmariadb-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.cc42
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()))