diff options
Diffstat (limited to 'mysql-test/t')
-rw-r--r-- | mysql-test/t/trigger-trans.test | 82 | ||||
-rw-r--r-- | mysql-test/t/trigger.test | 365 |
2 files changed, 446 insertions, 1 deletions
diff --git a/mysql-test/t/trigger-trans.test b/mysql-test/t/trigger-trans.test index 5c135d98878..8103a1ba0b1 100644 --- a/mysql-test/t/trigger-trans.test +++ b/mysql-test/t/trigger-trans.test @@ -49,4 +49,84 @@ insert into t1 values ('The Pie', 50, 1, 1); select * from t1; drop table t1; -# End of 5.0 tests +--echo +--echo Bug#26141 mixing table types in trigger causes full +--echo table lock on innodb table +--echo +--echo Ensure we do not open and lock tables for the triggers we do not +--echo fire. +--echo +--disable_warnings +drop table if exists t1, t2, t3; +drop trigger if exists trg_bug26141_au; +drop trigger if exists trg_bug26141_ai; +--enable_warnings +# Note, for InnoDB to allow concurrent UPDATE and INSERT the +# table must have a unique key. +create table t1 (c int primary key) engine=innodb; +create table t2 (c int) engine=myisam; +create table t3 (c int) engine=myisam; +insert into t1 (c) values (1); +delimiter |; + +create trigger trg_bug26141_ai after insert on t1 +for each row +begin + insert into t2 (c) values (1); +# We need the 'sync' lock to synchronously wait in connection 2 till +# the moment when the trigger acquired all the locks. + select release_lock("lock_bug26141_sync") into @a; +# 1000 is time in seconds of lock wait timeout -- this is a way +# to cause a manageable sleep up to 1000 seconds + select get_lock("lock_bug26141_wait", 1000) into @a; +end| + +create trigger trg_bug26141_au after update on t1 +for each row +begin + insert into t3 (c) values (1); +end| +delimiter ;| + +# Establish an alternative connection. +--connect (connection_aux,localhost,root,,test,,) +--connect (connection_update,localhost,root,,test,,) + +connection connection_aux; +# Lock the wait lock, it must not be locked, so specify zero timeout. +select get_lock("lock_bug26141_wait", 0); + +# +connection default; +# +# Run the trigger synchronously +# +select get_lock("lock_bug26141_sync", /* must not be priorly locked */ 0); +# Will acquire the table level locks, perform the insert into t2, +# release the sync lock and block on the wait lock. +send insert into t1 (c) values (2); + +connection connection_update; +# Wait for the trigger to acquire its locks and unlock the sync lock. +select get_lock("lock_bug26141_sync", 1000); +# +# This must continue: after the fix for the bug, we do not +# open tables for t2, and with c=4 innobase allows the update +# to run concurrently with insert. +update t1 set c=3 where c=1; +select release_lock("lock_bug26141_sync"); +connection connection_aux; +select release_lock("lock_bug26141_wait"); +connection default; +reap; +select * from t1; +select * from t2; +select * from t3; + +# Drops the trigger as well. +drop table t1, t2, t3; +disconnect connection_update; +disconnect connection_aux; + + +--echo End of 5.0 tests diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 0fa92f33de2..a6390036322 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -1828,5 +1828,370 @@ DROP TRIGGER t1_test; DROP TABLE t1,t2; SET SESSION LOW_PRIORITY_UPDATES=DEFAULT; SET GLOBAL LOW_PRIORITY_UPDATES=DEFAULT; +--echo +--echo Bug#28502 Triggers that update another innodb table will block +--echo on X lock unnecessarily +--echo +--echo Ensure we do not open and lock tables for triggers we do not fire. +--echo +--disable_warnings +drop table if exists t1, t2; +drop trigger if exists trg_bug28502_au; +--enable_warnings + +create table t1 (id int, count int); +create table t2 (id int); +delimiter |; + +create trigger trg_bug28502_au before update on t2 +for each row +begin + if (new.id is not null) then + update t1 set count= count + 1 where id = old.id; + end if; +end| + +delimiter ;| +insert into t1 (id, count) values (1, 0); + +lock table t1 write; + +--connect (connection_insert, localhost, root, , test, , ) +connection connection_insert; +# Is expected to pass. +insert into t2 set id=1; +connection default; +unlock tables; +update t2 set id=1 where id=1; +select * from t1; +select * from t2; +# Will drop the trigger +drop table t1, t2; +disconnect connection_insert; +--echo +--echo Additionally, provide test coverage for triggers and +--echo all MySQL data changing commands. +--echo +--disable_warnings +drop table if exists t1, t2, t1_op_log; +drop view if exists v1; +drop trigger if exists trg_bug28502_bi; +drop trigger if exists trg_bug28502_ai; +drop trigger if exists trg_bug28502_bu; +drop trigger if exists trg_bug28502_au; +drop trigger if exists trg_bug28502_bd; +drop trigger if exists trg_bug28502_ad; +--enable_warnings +create table t1 (id int primary key auto_increment, operation varchar(255)); +create table t2 (id int primary key); +create table t1_op_log(operation varchar(255)); +create view v1 as select * from t1; +create trigger trg_bug28502_bi before insert on t1 +for each row + insert into t1_op_log (operation) + values (concat("Before INSERT, new=", new.operation)); + +create trigger trg_bug28502_ai after insert on t1 +for each row + insert into t1_op_log (operation) + values (concat("After INSERT, new=", new.operation)); + +create trigger trg_bug28502_bu before update on t1 +for each row + insert into t1_op_log (operation) + values (concat("Before UPDATE, new=", new.operation, + ", old=", old.operation)); + +create trigger trg_bug28502_au after update on t1 +for each row + insert into t1_op_log (operation) + values (concat("After UPDATE, new=", new.operation, + ", old=", old.operation)); + +create trigger trg_bug28502_bd before delete on t1 +for each row + insert into t1_op_log (operation) + values (concat("Before DELETE, old=", old.operation)); + +create trigger trg_bug28502_ad after delete on t1 +for each row + insert into t1_op_log (operation) + values (concat("After DELETE, old=", old.operation)); + +insert into t1 (operation) values ("INSERT"); + +set @id=last_insert_id(); + +select * from t1; +select * from t1_op_log; +truncate t1_op_log; + +update t1 set operation="UPDATE" where id=@id; + +select * from t1; +select * from t1_op_log; +truncate t1_op_log; + +delete from t1 where id=@id; + +select * from t1; +select * from t1_op_log; +truncate t1; +truncate t1_op_log; + +insert into t1 (id, operation) values +(NULL, "INSERT ON DUPLICATE KEY UPDATE, inserting a new key") +on duplicate key update id=NULL, operation="Should never happen"; + +set @id=last_insert_id(); + +select * from t1; +select * from t1_op_log; +truncate t1_op_log; + +insert into t1 (id, operation) values +(@id, "INSERT ON DUPLICATE KEY UPDATE, the key value is the same") +on duplicate key update id=NULL, +operation="INSERT ON DUPLICATE KEY UPDATE, updating the duplicate"; + +select * from t1; +select * from t1_op_log; +truncate t1; +truncate t1_op_log; + +replace into t1 values (NULL, "REPLACE, inserting a new key"); + +set @id=last_insert_id(); + +select * from t1; +select * from t1_op_log; +truncate t1_op_log; + +replace into t1 values (@id, "REPLACE, deleting the duplicate"); + +select * from t1; +select * from t1_op_log; +truncate t1; +truncate t1_op_log; + +create table if not exists t1 +select NULL, "CREATE TABLE ... SELECT, inserting a new key"; + +set @id=last_insert_id(); + +select * from t1; +select * from t1_op_log; +truncate t1_op_log; + +create table if not exists t1 replace +select @id, "CREATE TABLE ... REPLACE SELECT, deleting a duplicate key"; + +select * from t1; +select * from t1_op_log; +truncate t1; +truncate t1_op_log; + +insert into t1 (id, operation) +select NULL, "INSERT ... SELECT, inserting a new key"; + +set @id=last_insert_id(); + +select * from t1; +select * from t1_op_log; +truncate t1_op_log; + +insert into t1 (id, operation) +select @id, +"INSERT ... SELECT ... ON DUPLICATE KEY UPDATE, updating a duplicate" +on duplicate key update id=NULL, +operation="INSERT ... SELECT ... ON DUPLICATE KEY UPDATE, updating a duplicate"; + +select * from t1; +select * from t1_op_log; +truncate t1; +truncate t1_op_log; + +replace into t1 (id, operation) +select NULL, "REPLACE ... SELECT, inserting a new key"; + +set @id=last_insert_id(); + +select * from t1; +select * from t1_op_log; +truncate t1_op_log; + +replace into t1 (id, operation) +select @id, "REPLACE ... SELECT, deleting a duplicate"; + +select * from t1; +select * from t1_op_log; +truncate t1; +truncate t1_op_log; + +insert into t1 (id, operation) values (1, "INSERT for multi-DELETE"); +insert into t2 (id) values (1); +delete t1.*, t2.* from t1, t2 where t1.id=1; + +select * from t1; +select * from t2; +select * from t1_op_log; +truncate t1; +truncate t2; +truncate t1_op_log; + +insert into t1 (id, operation) values (1, "INSERT for multi-UPDATE"); +insert into t2 (id) values (1); +update t1, t2 set t1.id=2, operation="multi-UPDATE" where t1.id=1; +update t1, t2 +set t2.id=3, operation="multi-UPDATE, SET for t2, but the trigger is fired" where t1.id=2; + +select * from t1; +select * from t2; +select * from t1_op_log; +truncate table t1; +truncate table t2; +truncate table t1_op_log; + +--echo +--echo Now do the same but use a view instead of the base table. +--echo + +insert into v1 (operation) values ("INSERT"); + +set @id=last_insert_id(); + +select * from t1; +select * from t1_op_log; +truncate t1_op_log; + +update v1 set operation="UPDATE" where id=@id; + +select * from t1; +select * from t1_op_log; +truncate t1_op_log; + +delete from v1 where id=@id; + +select * from t1; +select * from t1_op_log; +truncate t1; +truncate t1_op_log; + +insert into v1 (id, operation) values +(NULL, "INSERT ON DUPLICATE KEY UPDATE, inserting a new key") +on duplicate key update id=NULL, operation="Should never happen"; + +set @id=last_insert_id(); + +select * from t1; +select * from t1_op_log; +truncate t1_op_log; + +insert into v1 (id, operation) values +(@id, "INSERT ON DUPLICATE KEY UPDATE, the key value is the same") +on duplicate key update id=NULL, +operation="INSERT ON DUPLICATE KEY UPDATE, updating the duplicate"; + +select * from t1; +select * from t1_op_log; +truncate t1; +truncate t1_op_log; + +replace into v1 values (NULL, "REPLACE, inserting a new key"); + +set @id=last_insert_id(); + +select * from t1; +select * from t1_op_log; +truncate t1_op_log; + +replace into v1 values (@id, "REPLACE, deleting the duplicate"); + +select * from t1; +select * from t1_op_log; +truncate t1; +truncate t1_op_log; + +create table if not exists v1 +select NULL, "CREATE TABLE ... SELECT, inserting a new key"; + +set @id=last_insert_id(); + +select * from t1; +select * from t1_op_log; +truncate t1_op_log; + +create table if not exists v1 replace +select @id, "CREATE TABLE ... REPLACE SELECT, deleting a duplicate key"; + +select * from t1; +select * from t1_op_log; +truncate t1; +truncate t1_op_log; + +insert into v1 (id, operation) +select NULL, "INSERT ... SELECT, inserting a new key"; + +set @id=last_insert_id(); + +select * from t1; +select * from t1_op_log; +truncate t1_op_log; + +insert into v1 (id, operation) +select @id, +"INSERT ... SELECT ... ON DUPLICATE KEY UPDATE, updating a duplicate" +on duplicate key update id=NULL, +operation="INSERT ... SELECT ... ON DUPLICATE KEY UPDATE, updating a duplicate"; + +select * from t1; +select * from t1_op_log; +truncate t1; +truncate t1_op_log; + +replace into v1 (id, operation) +select NULL, "REPLACE ... SELECT, inserting a new key"; + +set @id=last_insert_id(); + +select * from t1; +select * from t1_op_log; +truncate t1_op_log; + +replace into v1 (id, operation) +select @id, "REPLACE ... SELECT, deleting a duplicate"; + +select * from t1; +select * from t1_op_log; +truncate t1; +truncate t1_op_log; + +insert into v1 (id, operation) values (1, "INSERT for multi-DELETE"); +insert into t2 (id) values (1); + +delete v1.*, t2.* from v1, t2 where v1.id=1; + +select * from t1; +select * from t2; +select * from t1_op_log; +truncate t1; +truncate t2; +truncate t1_op_log; + +insert into v1 (id, operation) values (1, "INSERT for multi-UPDATE"); +insert into t2 (id) values (1); +update v1, t2 set v1.id=2, operation="multi-UPDATE" where v1.id=1; +update v1, t2 +set t2.id=3, operation="multi-UPDATE, SET for t2, but the trigger is fired" where v1.id=2; + +select * from t1; +select * from t2; +select * from t1_op_log; + +drop view v1; +drop table t1, t2, t1_op_log; + +# +# TODO: test LOAD DATA INFILE --echo End of 5.0 tests |