Fix for bug #5890 "Triggers fail for DELETE without WHERE".
If we have DELETE with always true WHERE clause we should not use optimized delete_all_rows() method for tables with DELETE triggers, because in this case we will lose side-effect of deletion. mysql-test/r/trigger.result: Added test for bug #5890 "Triggers fail for DELETE without WHERE". mysql-test/t/trigger.test: Added test for bug #5890 "Triggers fail for DELETE without WHERE". sql/sql_delete.cc: mysql_delete(): We should not use optimized delete_all_rows() method for tables with DELETE triggers, because in this case we will lose side-effect of deletion. sql/sql_trigger.h: Added new Table_triggers_list::has_delete_triggers() method which allows to understand quickly if we have some DELETE triggers in our list.
This commit is contained in:
parent
e5fd013fdf
commit
bb43e8317f
@ -174,3 +174,15 @@ create trigger tx1 before insert on t1 for each row set new.x1col = 'x';
|
|||||||
insert into t1 values ('y');
|
insert into t1 values ('y');
|
||||||
drop trigger t1.tx1;
|
drop trigger t1.tx1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
create table t1 (i int) engine=myisam;
|
||||||
|
insert into t1 values (1), (2);
|
||||||
|
create trigger trg1 before delete on t1 for each row set @del_before:= @del_before + old.i;
|
||||||
|
create trigger trg2 after delete on t1 for each row set @del_after:= @del_after + old.i;
|
||||||
|
set @del_before:=0, @del_after:= 0;
|
||||||
|
delete from t1;
|
||||||
|
select @del_before, @del_after;
|
||||||
|
@del_before @del_after
|
||||||
|
3 3
|
||||||
|
drop trigger t1.trg1;
|
||||||
|
drop trigger t1.trg2;
|
||||||
|
drop table t1;
|
||||||
|
@ -207,3 +207,20 @@ create trigger tx1 before insert on t1 for each row set new.x1col = 'x';
|
|||||||
insert into t1 values ('y');
|
insert into t1 values ('y');
|
||||||
drop trigger t1.tx1;
|
drop trigger t1.tx1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test for bug #5890 "Triggers fail for DELETE without WHERE".
|
||||||
|
# If we are going to delete all rows in table but DELETE triggers exist
|
||||||
|
# we should perform row-by-row deletion instead of using optimized
|
||||||
|
# delete_all_rows() method.
|
||||||
|
#
|
||||||
|
create table t1 (i int) engine=myisam;
|
||||||
|
insert into t1 values (1), (2);
|
||||||
|
create trigger trg1 before delete on t1 for each row set @del_before:= @del_before + old.i;
|
||||||
|
create trigger trg2 after delete on t1 for each row set @del_after:= @del_after + old.i;
|
||||||
|
set @del_before:=0, @del_after:= 0;
|
||||||
|
delete from t1;
|
||||||
|
select @del_before, @del_after;
|
||||||
|
drop trigger t1.trg1;
|
||||||
|
drop trigger t1.trg2;
|
||||||
|
drop table t1;
|
||||||
|
@ -62,9 +62,14 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
|
|||||||
if (thd->lex->duplicates == DUP_IGNORE)
|
if (thd->lex->duplicates == DUP_IGNORE)
|
||||||
thd->lex->select_lex.no_error= 1;
|
thd->lex->select_lex.no_error= 1;
|
||||||
|
|
||||||
/* Test if the user wants to delete all rows */
|
/*
|
||||||
|
Test if the user wants to delete all rows and deletion doesn't have
|
||||||
|
any side-effects (because of triggers), so we can use optimized
|
||||||
|
handler::delete_all_rows() method.
|
||||||
|
*/
|
||||||
if (!using_limit && const_cond && (!conds || conds->val_int()) &&
|
if (!using_limit && const_cond && (!conds || conds->val_int()) &&
|
||||||
!(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)))
|
!(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) &&
|
||||||
|
!(table->triggers && table->triggers->has_delete_triggers()))
|
||||||
{
|
{
|
||||||
deleted= table->file->records;
|
deleted= table->file->records;
|
||||||
if (!(error=table->file->delete_all_rows()))
|
if (!(error=table->file->delete_all_rows()))
|
||||||
|
@ -58,5 +58,11 @@ public:
|
|||||||
static bool check_n_load(THD *thd, const char *db, const char *table_name,
|
static bool check_n_load(THD *thd, const char *db, const char *table_name,
|
||||||
TABLE *table);
|
TABLE *table);
|
||||||
|
|
||||||
|
bool has_delete_triggers()
|
||||||
|
{
|
||||||
|
return (bodies[TRG_EVENT_DELETE][TRG_ACTION_BEFORE] ||
|
||||||
|
bodies[TRG_EVENT_DELETE][TRG_ACTION_AFTER]);
|
||||||
|
}
|
||||||
|
|
||||||
friend class Item_trigger_field;
|
friend class Item_trigger_field;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user