2474 lines
		
	
	
		
			69 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
		
		
			
		
	
	
			2474 lines
		
	
	
		
			69 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
|  | # This test uses chmod, can't be run with root permissions | ||
|  | -- source include/not_as_root.inc | ||
|  | 
 | ||
|  | 
 | ||
|  | # | ||
|  | # Basic triggers test | ||
|  | # | ||
|  | 
 | ||
|  | --disable_warnings | ||
|  | drop table if exists t1, t2, t3, t4; | ||
|  | drop view if exists v1; | ||
|  | drop database if exists mysqltest; | ||
|  | drop function if exists f1; | ||
|  | drop function if exists f2; | ||
|  | drop procedure if exists p1; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | # Create additional connections used through test | ||
|  | connect (addconroot1, localhost, root,,); | ||
|  | connect (addconroot2, localhost, root,,); | ||
|  | # Connection without current database set | ||
|  | connect (addconwithoutdb, localhost, root,,*NO-ONE*); | ||
|  | connection default; | ||
|  | 
 | ||
|  | create table t1 (i int); | ||
|  | 
 | ||
|  | # let us test some very simple trigger | ||
|  | create trigger trg before insert on t1 for each row set @a:=1; | ||
|  | set @a:=0; | ||
|  | select @a; | ||
|  | insert into t1 values (1); | ||
|  | select @a; | ||
|  | drop trigger trg; | ||
|  | 
 | ||
|  | # let us test simple trigger reading some values  | ||
|  | create trigger trg before insert on t1 for each row set @a:=new.i; | ||
|  | insert into t1 values (123); | ||
|  | select @a; | ||
|  | drop trigger trg; | ||
|  | 
 | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # Let us test before insert trigger | ||
|  | # Such triggers can be used for setting complex default values | ||
|  | create table t1 (i int not null, j int); | ||
|  | delimiter |; | ||
|  | create trigger trg before insert on t1 for each row  | ||
|  | begin  | ||
|  |   if isnull(new.j) then | ||
|  |     set new.j:= new.i * 10; | ||
|  |   end if; | ||
|  | end| | ||
|  | insert into t1 (i) values (1)| | ||
|  | insert into t1 (i,j) values (2, 3)| | ||
|  | select * from t1| | ||
|  | drop trigger trg| | ||
|  | drop table t1| | ||
|  | delimiter ;| | ||
|  | 
 | ||
|  | # After insert trigger | ||
|  | # Useful for aggregating data | ||
|  | create table t1 (i int not null primary key); | ||
|  | create trigger trg after insert on t1 for each row  | ||
|  |   set @a:= if(@a,concat(@a, ":", new.i), new.i); | ||
|  | set @a:=""; | ||
|  | insert into t1 values (2),(3),(4),(5); | ||
|  | select @a; | ||
|  | drop trigger trg; | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # PS doesn't work with multi-row statements | ||
|  | --disable_ps_protocol | ||
|  | # Before update trigger | ||
|  | # (In future we will achieve this via proper error handling in triggers) | ||
|  | create table t1 (aid int not null primary key, balance int not null default 0); | ||
|  | insert into t1 values (1, 1000), (2,3000); | ||
|  | delimiter |; | ||
|  | create trigger trg before update on t1 for each row  | ||
|  | begin | ||
|  |   declare loc_err varchar(255); | ||
|  |   if abs(new.balance - old.balance) > 1000 then | ||
|  |     set new.balance:= old.balance; | ||
|  |     set loc_err := concat("Too big change for aid = ", new.aid); | ||
|  |     set @update_failed:= if(@update_failed, concat(@a, ":", loc_err), loc_err); | ||
|  |   end if; | ||
|  | end| | ||
|  | set @update_failed:=""| | ||
|  | update t1 set balance=1500| | ||
|  | select @update_failed; | ||
|  | select * from t1| | ||
|  | drop trigger trg| | ||
|  | drop table t1| | ||
|  | delimiter ;| | ||
|  | --enable_ps_protocol | ||
|  | 
 | ||
|  | # After update trigger | ||
|  | create table t1 (i int); | ||
|  | insert into t1 values (1),(2),(3),(4); | ||
|  | create trigger trg after update on t1 for each row  | ||
|  |   set @total_change:=@total_change + new.i - old.i; | ||
|  | set @total_change:=0; | ||
|  | update t1 set i=3; | ||
|  | select @total_change; | ||
|  | drop trigger trg; | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # Before delete trigger | ||
|  | # This can be used for aggregation too :) | ||
|  | create table t1 (i int); | ||
|  | insert into t1 values (1),(2),(3),(4); | ||
|  | create trigger trg before delete on t1 for each row  | ||
|  |   set @del_sum:= @del_sum + old.i; | ||
|  | set @del_sum:= 0; | ||
|  | delete from t1 where i <= 3; | ||
|  | select @del_sum; | ||
|  | drop trigger trg; | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # After delete trigger.  | ||
|  | # Just run out of imagination. | ||
|  | create table t1 (i int); | ||
|  | insert into t1 values (1),(2),(3),(4); | ||
|  | create trigger trg after delete on t1 for each row set @del:= 1; | ||
|  | set @del:= 0; | ||
|  | delete from t1 where i <> 0; | ||
|  | select @del; | ||
|  | drop trigger trg; | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # Several triggers on one table | ||
|  | create table t1 (i int, j int); | ||
|  | 
 | ||
|  | delimiter |; | ||
|  | create trigger trg1 before insert on t1 for each row  | ||
|  | begin | ||
|  |   if new.j > 10 then | ||
|  |     set new.j := 10; | ||
|  |   end if; | ||
|  | end| | ||
|  | create trigger trg2 before update on t1 for each row  | ||
|  | begin | ||
|  |   if old.i % 2 = 0 then | ||
|  |     set new.j := -1; | ||
|  |   end if; | ||
|  | end| | ||
|  | create trigger trg3 after update on t1 for each row  | ||
|  | begin | ||
|  |   if new.j = -1 then | ||
|  |     set @fired:= "Yes"; | ||
|  |   end if; | ||
|  | end| | ||
|  | delimiter ;| | ||
|  | set @fired:=""; | ||
|  | insert into t1 values (1,2),(2,3),(3,14); | ||
|  | select @fired; | ||
|  | select * from t1; | ||
|  | update t1 set j= 20; | ||
|  | select @fired; | ||
|  | select * from t1; | ||
|  | 
 | ||
|  | drop trigger trg1; | ||
|  | drop trigger trg2; | ||
|  | drop trigger trg3; | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | 
 | ||
|  | # Let us test how triggers work for special forms of INSERT such as | ||
|  | # REPLACE and INSERT ... ON DUPLICATE KEY UPDATE | ||
|  | create table t1 (id int not null primary key, data int); | ||
|  | create trigger t1_bi before insert on t1 for each row | ||
|  |   set @log:= concat(@log, "(BEFORE_INSERT: new=(id=", new.id, ", data=", new.data,"))"); | ||
|  | create trigger t1_ai after insert on t1 for each row | ||
|  |   set @log:= concat(@log, "(AFTER_INSERT: new=(id=", new.id, ", data=", new.data,"))"); | ||
|  | create trigger t1_bu before update on t1 for each row | ||
|  |   set @log:= concat(@log, "(BEFORE_UPDATE: old=(id=", old.id, ", data=", old.data, | ||
|  |                                         ") new=(id=", new.id, ", data=", new.data,"))"); | ||
|  | create trigger t1_au after update on t1 for each row | ||
|  |   set @log:= concat(@log, "(AFTER_UPDATE: old=(id=", old.id, ", data=", old.data, | ||
|  |                                        ") new=(id=", new.id, ", data=", new.data,"))"); | ||
|  | create trigger t1_bd before delete on t1 for each row | ||
|  |   set @log:= concat(@log, "(BEFORE_DELETE: old=(id=", old.id, ", data=", old.data,"))"); | ||
|  | create trigger t1_ad after delete on t1 for each row | ||
|  |   set @log:= concat(@log, "(AFTER_DELETE: old=(id=", old.id, ", data=", old.data,"))"); | ||
|  | # Simple INSERT - both triggers should be called | ||
|  | set @log:= ""; | ||
|  | insert into t1 values (1, 1); | ||
|  | select @log; | ||
|  | # INSERT IGNORE for already existing key - only before trigger should fire | ||
|  | set @log:= ""; | ||
|  | insert ignore t1 values (1, 2); | ||
|  | select @log; | ||
|  | # INSERT ... ON DUPLICATE KEY UPDATE ... | ||
|  | set @log:= ""; | ||
|  | insert into t1 (id, data) values (1, 3), (2, 2) on duplicate key update data= data + 1; | ||
|  | select @log; | ||
|  | # REPLACE (also test for bug#13479 "REPLACE activates UPDATE trigger, | ||
|  | #          not the DELETE and INSERT triggers") | ||
|  | # We define REPLACE as INSERT which DELETEs old rows which conflict with | ||
|  | # row being inserted. So for the first record in statement below we will | ||
|  | # call before insert trigger, then delete will be executed (and both delete | ||
|  | # triggers should fire). Finally after insert trigger will be called. | ||
|  | # For the second record we will just call both on insert triggers. | ||
|  | set @log:= ""; | ||
|  | replace t1 values (1, 4), (3, 3); | ||
|  | select @log; | ||
|  | # Now we will drop ON DELETE triggers to test REPLACE which is internally | ||
|  | # executed via update | ||
|  | drop trigger t1_bd; | ||
|  | drop trigger t1_ad; | ||
|  | set @log:= ""; | ||
|  | replace t1 values (1, 5); | ||
|  | select @log; | ||
|  | 
 | ||
|  | # This also drops associated triggers | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | 
 | ||
|  | # | ||
|  | # Let us test triggers which access other tables. | ||
|  | # | ||
|  | # Trivial trigger which inserts data into another table | ||
|  | create table t1 (id int primary key, data varchar(10), fk int); | ||
|  | create table t2 (event varchar(100)); | ||
|  | create table t3 (id int primary key); | ||
|  | create trigger t1_ai after insert on t1 for each row  | ||
|  |   insert into t2 values (concat("INSERT INTO t1 id=", new.id, " data='", new.data, "'")); | ||
|  | insert into t1 (id, data) values (1, "one"), (2, "two"); | ||
|  | select * from t1; | ||
|  | select * from t2; | ||
|  | drop trigger t1_ai; | ||
|  | # Trigger which uses couple of tables (and partially emulates FK constraint) | ||
|  | delimiter |; | ||
|  | create trigger t1_bi before insert on t1 for each row | ||
|  | begin | ||
|  |   if exists (select id from t3 where id=new.fk) then | ||
|  |     insert into t2 values (concat("INSERT INTO t1 id=", new.id, " data='", new.data, "' fk=", new.fk)); | ||
|  |   else | ||
|  |     insert into t2 values (concat("INSERT INTO t1 FAILED id=", new.id, " data='", new.data, "' fk=", new.fk)); | ||
|  |     set new.id= NULL; | ||
|  |   end if; | ||
|  | end| | ||
|  | delimiter ;| | ||
|  | insert into t3 values (1); | ||
|  | --error ER_BAD_NULL_ERROR | ||
|  | insert into t1 values (4, "four", 1), (5, "five", 2); | ||
|  | select * from t1; | ||
|  | select * from t2; | ||
|  | drop table t1, t2, t3; | ||
|  | # Trigger which invokes function | ||
|  | create table t1 (id int primary key, data varchar(10)); | ||
|  | create table t2 (seq int); | ||
|  | insert into t2 values (10); | ||
|  | create function f1 () returns int return (select max(seq) from t2); | ||
|  | delimiter |; | ||
|  | create trigger t1_bi before insert on t1 for each row | ||
|  | begin | ||
|  |   if new.id > f1() then | ||
|  |     set new.id:= f1(); | ||
|  |   end if; | ||
|  | end| | ||
|  | delimiter ;| | ||
|  | insert into t1 values (1, "first"); | ||
|  | insert into t1 values (f1(), "max"); | ||
|  | select * from t1; | ||
|  | drop table t1, t2; | ||
|  | drop function f1; | ||
|  | # Trigger which forces invocation of another trigger | ||
|  | # (emulation of FK on delete cascade policy) | ||
|  | create table t1 (id int primary key, fk_t2 int); | ||
|  | create table t2 (id int primary key, fk_t3 int); | ||
|  | create table t3 (id int primary key); | ||
|  | insert into t1 values (1,1), (2,1), (3,2); | ||
|  | insert into t2 values (1,1), (2,2); | ||
|  | insert into t3 values (1), (2); | ||
|  | create trigger t3_ad after delete on t3 for each row | ||
|  |   delete from t2 where fk_t3=old.id; | ||
|  | create trigger t2_ad after delete on t2 for each row | ||
|  |   delete from t1 where fk_t2=old.id; | ||
|  | delete from t3 where id = 1; | ||
|  | select * from t1 left join (t2 left join t3 on t2.fk_t3 = t3.id) on t1.fk_t2 = t2.id; | ||
|  | drop table t1, t2, t3; | ||
|  | # Trigger which assigns value selected from table to field of row | ||
|  | # being inserted/updated. | ||
|  | create table t1 (id int primary key, copy int); | ||
|  | create table t2 (id int primary key, data int); | ||
|  | insert into t2 values (1,1), (2,2); | ||
|  | create trigger t1_bi before insert on t1 for each row | ||
|  |   set new.copy= (select data from t2 where id = new.id); | ||
|  | create trigger t1_bu before update on t1 for each row | ||
|  |   set new.copy= (select data from t2 where id = new.id); | ||
|  | insert into t1 values (1,3), (2,4), (3,3); | ||
|  | update t1 set copy= 1 where id = 2; | ||
|  | select * from t1; | ||
|  | drop table t1, t2; | ||
|  | 
 | ||
|  | # | ||
|  | # Test of wrong column specifiers in triggers | ||
|  | # | ||
|  | create table t1 (i int); | ||
|  | create table t3 (i int); | ||
|  | 
 | ||
|  | --error ER_TRG_NO_SUCH_ROW_IN_TRG | ||
|  | create trigger trg before insert on t1 for each row set @a:= old.i; | ||
|  | --error ER_TRG_NO_SUCH_ROW_IN_TRG | ||
|  | create trigger trg before delete on t1 for each row set @a:= new.i; | ||
|  | --error ER_TRG_CANT_CHANGE_ROW | ||
|  | create trigger trg before update on t1 for each row set old.i:=1; | ||
|  | --error ER_TRG_NO_SUCH_ROW_IN_TRG | ||
|  | create trigger trg before delete on t1 for each row set new.i:=1; | ||
|  | --error ER_TRG_CANT_CHANGE_ROW | ||
|  | create trigger trg after update on t1 for each row set new.i:=1; | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | create trigger trg before update on t1 for each row set new.j:=1; | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | create trigger trg before update on t1 for each row set @a:=old.j; | ||
|  | 
 | ||
|  | 
 | ||
|  | # | ||
|  | # Let us test various trigger creation errors | ||
|  | # Also quickly test table namespace (bug#5892/6182) | ||
|  | # | ||
|  | --error ER_NO_SUCH_TABLE | ||
|  | create trigger trg before insert on t2 for each row set @a:=1; | ||
|  | 
 | ||
|  | create trigger trg before insert on t1 for each row set @a:=1; | ||
|  | --error ER_TRG_ALREADY_EXISTS | ||
|  | create trigger trg after insert on t1 for each row set @a:=1; | ||
|  | --error ER_NOT_SUPPORTED_YET | ||
|  | create trigger trg2 before insert on t1 for each row set @a:=1; | ||
|  | --error ER_TRG_ALREADY_EXISTS | ||
|  | create trigger trg before insert on t3 for each row set @a:=1; | ||
|  | create trigger trg2 before insert on t3 for each row set @a:=1; | ||
|  | drop trigger trg2; | ||
|  | drop trigger trg; | ||
|  | 
 | ||
|  | --error ER_TRG_DOES_NOT_EXIST | ||
|  | drop trigger trg; | ||
|  | 
 | ||
|  | create view v1 as select * from t1; | ||
|  | --error ER_WRONG_OBJECT | ||
|  | create trigger trg before insert on v1 for each row set @a:=1; | ||
|  | drop view v1; | ||
|  | 
 | ||
|  | drop table t1; | ||
|  | drop table t3; | ||
|  | 
 | ||
|  | create temporary table t1 (i int); | ||
|  | --error ER_TRG_ON_VIEW_OR_TEMP_TABLE | ||
|  | create trigger trg before insert on t1 for each row set @a:=1; | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | # | ||
|  | # Tests for various trigger-related bugs | ||
|  | # | ||
|  | 
 | ||
|  | # Test for bug #5887 "Triggers with string literals cause errors". | ||
|  | # New .FRM parser was not handling escaped strings properly. | ||
|  | create table t1 (x1col char);   | ||
|  | create trigger tx1 before insert on t1 for each row set new.x1col = 'x'; | ||
|  | insert into t1 values ('y'); | ||
|  | drop trigger tx1; | ||
|  | 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 trg1; | ||
|  | drop trigger trg2; | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # Test for bug #5859 "DROP TABLE does not drop triggers". Trigger should not | ||
|  | # magically reappear when we recreate dropped table. | ||
|  | create table t1 (a int); | ||
|  | create trigger trg1 before insert on t1 for each row set new.a= 10; | ||
|  | drop table t1; | ||
|  | create table t1 (a int); | ||
|  | insert into t1 values (); | ||
|  | select * from t1; | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # Test for bug #6559 "DROP DATABASE forgets to drop triggers".  | ||
|  | create database mysqltest; | ||
|  | use mysqltest; | ||
|  | create table t1 (i int); | ||
|  | create trigger trg1 before insert on t1 for each row set @a:= 1; | ||
|  | # This should succeed | ||
|  | drop database mysqltest; | ||
|  | use test; | ||
|  | 
 | ||
|  | # Test for bug #8791 | ||
|  | # "Triggers: Allowed to create triggers on a subject table in a different DB".  | ||
|  | create database mysqltest; | ||
|  | create table mysqltest.t1 (i int); | ||
|  | --error ER_TRG_IN_WRONG_SCHEMA | ||
|  | create trigger trg1 before insert on mysqltest.t1 for each row set @a:= 1; | ||
|  | use mysqltest; | ||
|  | --error ER_NO_SUCH_TABLE | ||
|  | create trigger test.trg1 before insert on t1 for each row set @a:= 1; | ||
|  | drop database mysqltest; | ||
|  | use test; | ||
|  | 
 | ||
|  | 
 | ||
|  | # Test for bug #5860 "Multi-table UPDATE does not activate update triggers" | ||
|  | # We will also test how delete triggers wor for multi-table DELETE. | ||
|  | create table t1 (i int, j int default 10, k int not null, key (k)); | ||
|  | create table t2 (i int); | ||
|  | insert into t1 (i, k) values (1, 1); | ||
|  | insert into t2 values (1); | ||
|  | create trigger trg1 before update on t1 for each row set @a:= @a + new.j - old.j; | ||
|  | create trigger trg2 after update on t1 for each row set @b:= "Fired"; | ||
|  | set @a:= 0, @b:= ""; | ||
|  | # Check that trigger works in case of update on the fly | ||
|  | update t1, t2 set j = j + 10 where t1.i = t2.i; | ||
|  | select @a, @b; | ||
|  | insert into t1 values (2, 13, 2); | ||
|  | insert into t2 values (2); | ||
|  | set @a:= 0, @b:= ""; | ||
|  | # And now let us check that triggers work in case of multi-update which | ||
|  | # is done through temporary tables... | ||
|  | update t1, t2 set j = j + 15 where t1.i = t2.i and t1.k >= 2; | ||
|  | select @a, @b; | ||
|  | # Let us test delete triggers for multi-delete now. | ||
|  | # We create triggers for both tables because we want test how they | ||
|  | # work in both on-the-fly and via-temp-tables cases. | ||
|  | create trigger trg3 before delete on t1 for each row set @c:= @c + old.j; | ||
|  | create trigger trg4 before delete on t2 for each row set @d:= @d + old.i; | ||
|  | create trigger trg5 after delete on t1 for each row set @e:= "After delete t1 fired"; | ||
|  | create trigger trg6 after delete on t2 for each row set @f:= "After delete t2 fired"; | ||
|  | set @c:= 0, @d:= 0, @e:= "", @f:= ""; | ||
|  | delete t1, t2 from t1, t2 where t1.i = t2.i; | ||
|  | select @c, @d, @e, @f; | ||
|  | # This also will drop triggers | ||
|  | drop table t1, t2; | ||
|  | 
 | ||
|  | # Test for bug #6812 "Triggers are not activated for INSERT ... SELECT". | ||
|  | # (We also check the fact that trigger modifies some field does not affect | ||
|  | #  value of next record inserted). | ||
|  | delimiter |; | ||
|  | create table t1 (i int, j int default 10)| | ||
|  | create table t2 (i int)| | ||
|  | insert into t2 values (1), (2)| | ||
|  | create trigger trg1 before insert on t1 for each row  | ||
|  | begin | ||
|  |   if new.i = 1 then | ||
|  |     set new.j := 1; | ||
|  |   end if; | ||
|  | end| | ||
|  | create trigger trg2 after insert on t1 for each row set @a:= 1| | ||
|  | set @a:= 0| | ||
|  | insert into t1 (i) select * from t2| | ||
|  | select * from t1| | ||
|  | select @a| | ||
|  | # This also will drop triggers | ||
|  | drop table t1, t2| | ||
|  | delimiter ;| | ||
|  | 
 | ||
|  | # Test for bug #8755 "Trigger is not activated by LOAD DATA" | ||
|  | create table t1 (i int, j int, k int); | ||
|  | create trigger trg1 before insert on t1 for each row set new.k = new.i; | ||
|  | create trigger trg2 after insert on t1 for each row set @b:= "Fired";  | ||
|  | set @b:=""; | ||
|  | # Test triggers with file with separators | ||
|  | load data infile '../../std_data/rpl_loaddata.dat' into table t1 (@a, i); | ||
|  | select *, @b from t1; | ||
|  | set @b:=""; | ||
|  | # Test triggers with fixed size row file | ||
|  | load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (i, j); | ||
|  | select *, @b from t1; | ||
|  | # This also will drop triggers | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # Test for bug #5894 "Triggers with altered tables cause corrupt databases" | ||
|  | # Also tests basic error handling for various kinds of triggers. | ||
|  | create table t1 (i int, at int, k int, key(k)) engine=myisam; | ||
|  | create table t2 (i int); | ||
|  | insert into t1 values (1, 1, 1); | ||
|  | # We need at least 3 elements in t2 to test multi-update properly | ||
|  | insert into t2 values (1), (2), (3); | ||
|  | # Create and then break "after" triggers | ||
|  | create trigger ai after insert on t1 for each row set @a:= new.at; | ||
|  | create trigger au after update on t1 for each row set @a:= new.at; | ||
|  | create trigger ad after delete on t1 for each row set @a:= old.at; | ||
|  | alter table t1 drop column at; | ||
|  | # We still should be able select data from tables. | ||
|  | select * from t1; | ||
|  | # The following statements changing t1 should fail, but still cause | ||
|  | # their main effect. This is because operation on the table row is | ||
|  | # executed before "after" trigger and its effect cannot be rolled back | ||
|  | # when whole statement fails, because t1 is MyISAM table. | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | insert into t1 values (2, 1); | ||
|  | select * from t1; | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | update t1 set k = 2 where i = 2; | ||
|  | select * from t1; | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | delete from t1 where i = 2; | ||
|  | select * from t1; | ||
|  | # Should fail and insert only 1 row | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (i, k); | ||
|  | select * from t1; | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | insert into t1 select 3, 3; | ||
|  | select * from t1; | ||
|  | # Multi-update working on the fly, again it will update only | ||
|  | # one row even if more matches | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | update t1, t2 set k = k + 10 where t1.i = t2.i; | ||
|  | select * from t1; | ||
|  | # The same for multi-update via temp table | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | update t1, t2 set k = k + 10 where t1.i = t2.i and k < 3; | ||
|  | select * from t1; | ||
|  | # Multi-delete on the fly | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | delete t1, t2 from t1 straight_join t2 where t1.i = t2.i; | ||
|  | select * from t1; | ||
|  | # And via temporary storage | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | delete t2, t1 from t2 straight_join t1 where t1.i = t2.i; | ||
|  | select * from t1; | ||
|  | # Prepare table for testing of REPLACE and INSERT ... ON DUPLICATE KEY UPDATE | ||
|  | alter table t1 add primary key (i); | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | insert into t1 values (3, 4) on duplicate key update k= k + 10; | ||
|  | select * from t1; | ||
|  | # The following statement will delete old row and won't | ||
|  | # insert new one since after delete trigger will fail. | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | replace into t1 values (3, 3); | ||
|  | select * from t1; | ||
|  | # Also drops all triggers | ||
|  | drop table t1, t2; | ||
|  | 
 | ||
|  | create table t1 (i int, bt int, k int, key(k)) engine=myisam; | ||
|  | create table t2 (i int); | ||
|  | insert into t1 values (1, 1, 1), (2, 2, 2); | ||
|  | insert into t2 values (1), (2), (3); | ||
|  | # Create and then break "before" triggers | ||
|  | create trigger bi before insert on t1 for each row set @a:= new.bt; | ||
|  | create trigger bu before update on t1 for each row set @a:= new.bt; | ||
|  | create trigger bd before delete on t1 for each row set @a:= old.bt; | ||
|  | alter table t1 drop column bt; | ||
|  | # The following statements changing t1 should fail and should not | ||
|  | # cause any effect on table, since "before" trigger is executed  | ||
|  | # before operation on the table row. | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | insert into t1 values (3, 3); | ||
|  | select * from t1; | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | update t1 set i = 2; | ||
|  | select * from t1; | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | delete from t1; | ||
|  | select * from t1; | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (i, k); | ||
|  | select * from t1; | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | insert into t1 select 3, 3; | ||
|  | select * from t1; | ||
|  | # Both types of multi-update (on the fly and via temp table) | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | update t1, t2 set k = k + 10 where t1.i = t2.i; | ||
|  | select * from t1; | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | update t1, t2 set k = k + 10 where t1.i = t2.i and k < 2; | ||
|  | select * from t1; | ||
|  | # Both types of multi-delete | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | delete t1, t2 from t1 straight_join t2 where t1.i = t2.i; | ||
|  | select * from t1; | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | delete t2, t1 from t2 straight_join t1 where t1.i = t2.i; | ||
|  | select * from t1; | ||
|  | # Let us test REPLACE/INSERT ... ON DUPLICATE KEY UPDATE. | ||
|  | # To test properly code-paths different from those that are used | ||
|  | # in ordinary INSERT we need to drop "before insert" trigger. | ||
|  | alter table t1 add primary key (i); | ||
|  | drop trigger bi; | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | insert into t1 values (2, 4) on duplicate key update k= k + 10; | ||
|  | select * from t1; | ||
|  | --error ER_BAD_FIELD_ERROR | ||
|  | replace into t1 values (2, 4); | ||
|  | select * from t1; | ||
|  | # Also drops all triggers | ||
|  | drop table t1, t2; | ||
|  | 
 | ||
|  | # Test for bug #5893 "Triggers with dropped functions cause crashes" | ||
|  | # Appropriate error should be reported instead of crash. | ||
|  | # Also test for bug #11889 "Server crashes when dropping trigger | ||
|  | # using stored routine". | ||
|  | --disable_warnings | ||
|  | drop function if exists bug5893; | ||
|  | --enable_warnings | ||
|  | create table t1 (col1 int, col2 int);  | ||
|  | insert into t1 values (1, 2); | ||
|  | create function bug5893 () returns int return 5; | ||
|  | create trigger t1_bu before update on t1 for each row set new.col1= bug5893(); | ||
|  | drop function bug5893;  | ||
|  | --error ER_SP_DOES_NOT_EXIST | ||
|  | update t1 set col2 = 4; | ||
|  | # This should not crash server too. | ||
|  | drop trigger t1_bu; | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # | ||
|  | # storing and restoring parsing modes for triggers (BUG#5891) | ||
|  | # | ||
|  | set sql_mode='ansi'; | ||
|  | create table t1 ("t1 column" int); | ||
|  | create trigger t1_bi before insert on t1 for each row set new."t1 column" = 5; | ||
|  | set sql_mode=""; | ||
|  | insert into t1 values (0); | ||
|  | # create trigger with different sql_mode | ||
|  | create trigger t1_af after insert on t1 for each row set @a=10; | ||
|  | insert into t1 values (0); | ||
|  | select * from t1; | ||
|  | select @a; | ||
|  | --replace_column 6 # | ||
|  | show triggers; | ||
|  | drop table t1; | ||
|  | # check that rigger preserve sql_mode during execution | ||
|  | set sql_mode="traditional"; | ||
|  | create table t1 (a date); | ||
|  | -- error 1292 | ||
|  | insert into t1 values ('2004-01-00'); | ||
|  | set sql_mode=""; | ||
|  | create trigger t1_bi before insert on t1 for each row set new.a = '2004-01-00'; | ||
|  | set sql_mode="traditional"; | ||
|  | insert into t1 values ('2004-01-01'); | ||
|  | select * from t1; | ||
|  | set sql_mode=default; | ||
|  | show create table t1; | ||
|  | --replace_column 6 # | ||
|  | show triggers; | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # Test for bug #12280 "Triggers: crash if flush tables" | ||
|  | # FLUSH TABLES and FLUSH PRIVILEGES should be disallowed inside | ||
|  | # of functions and triggers. | ||
|  | create table t1 (id int); | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | create trigger t1_ai after insert on t1 for each row reset query cache; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | create trigger t1_ai after insert on t1 for each row reset master; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | create trigger t1_ai after insert on t1 for each row reset slave; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | create trigger t1_ai after insert on t1 for each row flush hosts; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | create trigger t1_ai after insert on t1 for each row flush tables with read lock; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | create trigger t1_ai after insert on t1 for each row flush logs; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | create trigger t1_ai after insert on t1 for each row flush status; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | create trigger t1_ai after insert on t1 for each row flush slave; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | create trigger t1_ai after insert on t1 for each row flush master; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | create trigger t1_ai after insert on t1 for each row flush des_key_file; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | create trigger t1_ai after insert on t1 for each row flush user_resources; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | create trigger t1_ai after insert on t1 for each row flush tables; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | create trigger t1_ai after insert on t1 for each row flush privileges; | ||
|  | --disable_warnings | ||
|  | drop procedure if exists p1; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | create trigger t1_ai after insert on t1 for each row call p1(); | ||
|  | create procedure p1() flush tables; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | insert into t1 values (0); | ||
|  | 
 | ||
|  | drop procedure p1; | ||
|  | create procedure p1() reset query cache; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | insert into t1 values (0); | ||
|  | 
 | ||
|  | drop procedure p1; | ||
|  | create procedure p1() reset master; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | insert into t1 values (0); | ||
|  | 
 | ||
|  | drop procedure p1; | ||
|  | create procedure p1() reset slave; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | insert into t1 values (0); | ||
|  | 
 | ||
|  | drop procedure p1; | ||
|  | create procedure p1() flush hosts; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | insert into t1 values (0); | ||
|  | 
 | ||
|  | drop procedure p1; | ||
|  | create procedure p1() flush privileges; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | insert into t1 values (0); | ||
|  | 
 | ||
|  | drop procedure p1; | ||
|  | create procedure p1() flush tables with read lock; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | insert into t1 values (0); | ||
|  | 
 | ||
|  | drop procedure p1; | ||
|  | create procedure p1() flush tables; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | insert into t1 values (0); | ||
|  | 
 | ||
|  | drop procedure p1; | ||
|  | create procedure p1() flush logs; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | insert into t1 values (0); | ||
|  | 
 | ||
|  | drop procedure p1; | ||
|  | create procedure p1() flush status; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | insert into t1 values (0); | ||
|  | 
 | ||
|  | drop procedure p1; | ||
|  | create procedure p1() flush slave; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | insert into t1 values (0); | ||
|  | 
 | ||
|  | drop procedure p1; | ||
|  | create procedure p1() flush master; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | insert into t1 values (0); | ||
|  | 
 | ||
|  | drop procedure p1; | ||
|  | create procedure p1() flush des_key_file; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | insert into t1 values (0); | ||
|  | 
 | ||
|  | drop procedure p1; | ||
|  | create procedure p1() flush user_resources; | ||
|  | --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG | ||
|  | insert into t1 values (0); | ||
|  | 
 | ||
|  | drop procedure p1; | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # Test for bug #11973 "SELECT .. INTO var_name; in trigger cause | ||
|  | #                      crash on update" | ||
|  | 
 | ||
|  | create table t1 (id int, data int, username varchar(16)); | ||
|  | insert into t1 (id, data) values (1, 0); | ||
|  | delimiter |; | ||
|  | create trigger t1_whoupdated before update on t1 for each row | ||
|  | begin | ||
|  |   declare user varchar(32); | ||
|  |   declare i int; | ||
|  |   select user() into user; | ||
|  |   set NEW.username = user; | ||
|  |   select count(*) from ((select 1) union (select 2)) as d1 into i; | ||
|  | end| | ||
|  | delimiter ;| | ||
|  | update t1 set data = 1; | ||
|  | 
 | ||
|  | connection addconroot1; | ||
|  | update t1 set data = 2; | ||
|  | 
 | ||
|  | connection default; | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # | ||
|  | # #11587 Trigger causes lost connection error | ||
|  | # | ||
|  | 
 | ||
|  | create table t1 (c1 int, c2 datetime); | ||
|  | delimiter |; | ||
|  | --error ER_SP_NO_RETSET | ||
|  | create trigger tr1 before insert on t1 for each row  | ||
|  | begin  | ||
|  |   set new.c2= '2004-04-01'; | ||
|  |   select 'hello'; | ||
|  | end| | ||
|  | delimiter ;| | ||
|  | 
 | ||
|  | insert into t1 (c1) values (1),(2),(3); | ||
|  | select * from t1; | ||
|  | 
 | ||
|  | --disable_warnings | ||
|  | drop procedure if exists bug11587; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | delimiter |; | ||
|  | create procedure bug11587(x char(16)) | ||
|  | begin | ||
|  |   select "hello"; | ||
|  |   select "hello again"; | ||
|  | end| | ||
|  | 
 | ||
|  | create trigger tr1 before insert on t1 for each row  | ||
|  | begin  | ||
|  |   call bug11587(); | ||
|  |   set new.c2= '2004-04-02'; | ||
|  | end| | ||
|  | delimiter ;| | ||
|  | 
 | ||
|  | --error ER_SP_NO_RETSET | ||
|  | insert into t1 (c1) values (4),(5),(6); | ||
|  | select * from t1; | ||
|  | 
 | ||
|  | drop procedure bug11587; | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # Test for bug #11896 "Partial locking in case of recursive trigger | ||
|  | # definitions". Recursion in triggers should not be allowed. | ||
|  | # We also should not allow to change tables which are used in | ||
|  | # statements invoking this trigger. | ||
|  | create table t1 (f1 integer); | ||
|  | create table t2 (f2 integer); | ||
|  | create trigger t1_ai after insert on t1 | ||
|  |   for each row insert into t2 values (new.f1+1); | ||
|  | create trigger t2_ai after insert on t2 | ||
|  |   for each row insert into t1 values (new.f2+1); | ||
|  | # Allow SP resursion to be show that it has not influence here | ||
|  | set @SAVE_SP_RECURSION_LEVELS=@@max_sp_recursion_depth; | ||
|  | set @@max_sp_recursion_depth=100; | ||
|  | --error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG | ||
|  | insert into t1 values (1); | ||
|  | set @@max_sp_recursion_depth=@SAVE_SP_RECURSION_LEVELS; | ||
|  | select * from t1; | ||
|  | select * from t2; | ||
|  | drop trigger t1_ai; | ||
|  | drop trigger t2_ai; | ||
|  | create trigger t1_bu before update on t1 | ||
|  |   for each row insert into t1 values (2); | ||
|  | --error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG | ||
|  | update t1 set f1= 10; | ||
|  | select * from t1; | ||
|  | drop trigger t1_bu; | ||
|  | create trigger t1_bu before update on t1 | ||
|  |   for each row delete from t1 where f1=new.f1; | ||
|  | --error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG | ||
|  | update t1 set f1= 10; | ||
|  | select * from t1; | ||
|  | drop trigger t1_bu; | ||
|  | # This should work tough | ||
|  | create trigger t1_bi before insert on t1 | ||
|  |   for each row set new.f1=(select sum(f1) from t1); | ||
|  | insert into t1 values (3); | ||
|  | select * from t1; | ||
|  | drop trigger t1_bi; | ||
|  | drop tables t1, t2; | ||
|  | 
 | ||
|  | # Tests for bug #12704 "Server crashes during trigger execution". | ||
|  | # If we run DML statements and CREATE TRIGGER statements concurrently | ||
|  | # it may happen that trigger will be created while DML statement is | ||
|  | # waiting for table lock. In this case we have to reopen tables and | ||
|  | # recalculate prelocking set. | ||
|  | # Unfortunately these tests rely on the order in which tables are locked | ||
|  | # by statement so they are non determenistic and are disabled. | ||
|  | --disable_parsing | ||
|  | create table t1 (id int); | ||
|  | create table t2 (id int); | ||
|  | create table t3 (id int); | ||
|  | create function f1() returns int return (select max(id)+2 from t2); | ||
|  | create view v1 as select f1() as f; | ||
|  | 
 | ||
|  | # Let us check that we notice trigger at all | ||
|  | connection addconroot1; | ||
|  | lock tables t2 write; | ||
|  | connection default; | ||
|  | send insert into t1 values ((select max(id) from t2)), (2); | ||
|  | --sleep 1 | ||
|  | connection addconroot2; | ||
|  | create trigger t1_trg before insert on t1 for each row set NEW.id:= 1; | ||
|  | connection addconroot1; | ||
|  | unlock tables; | ||
|  | connection default; | ||
|  | reap; | ||
|  | select * from t1; | ||
|  | 
 | ||
|  | # Check that we properly calculate new prelocking set | ||
|  | insert into t2 values (3); | ||
|  | connection addconroot1; | ||
|  | lock tables t2 write; | ||
|  | connection default; | ||
|  | send insert into t1 values ((select max(id) from t2)), (4); | ||
|  | --sleep 1 | ||
|  | connection addconroot2; | ||
|  | drop trigger t1_trg; | ||
|  | create trigger t1_trg before insert on t1 for each row | ||
|  |   insert into t3 values (new.id); | ||
|  | connection addconroot1; | ||
|  | unlock tables; | ||
|  | connection default; | ||
|  | reap; | ||
|  | select * from t1; | ||
|  | select * from t3; | ||
|  | 
 | ||
|  | # We should be able to do this even if fancy views are involved | ||
|  | connection addconroot1; | ||
|  | lock tables t2 write; | ||
|  | connection default; | ||
|  | send insert into t1 values ((select max(f) from v1)), (6); | ||
|  | --sleep 1 | ||
|  | connection addconroot2; | ||
|  | drop trigger t1_trg; | ||
|  | create trigger t1_trg before insert on t1 for each row | ||
|  |   insert into t3 values (new.id + 100); | ||
|  | connection addconroot1; | ||
|  | unlock tables; | ||
|  | connection default; | ||
|  | reap; | ||
|  | select * from t1; | ||
|  | select * from t3; | ||
|  | 
 | ||
|  | # This also should work for multi-update | ||
|  | # Let us drop trigger to demonstrate that prelocking set is really | ||
|  | # rebuilt | ||
|  | drop trigger t1_trg; | ||
|  | connection addconroot1; | ||
|  | lock tables t2 write; | ||
|  | connection default; | ||
|  | send update t1, t2 set t1.id=10 where t1.id=t2.id; | ||
|  | --sleep 1 | ||
|  | connection addconroot2; | ||
|  | create trigger t1_trg before update on t1 for each row | ||
|  |   insert into t3 values (new.id); | ||
|  | connection addconroot1; | ||
|  | unlock tables; | ||
|  | connection default; | ||
|  | reap; | ||
|  | select * from t1; | ||
|  | select * from t3; | ||
|  | 
 | ||
|  | # And even for multi-update converted from ordinary update thanks to view | ||
|  | drop view v1; | ||
|  | drop trigger t1_trg; | ||
|  | create view v1 as select t1.id as id1 from t1, t2 where t1.id= t2.id; | ||
|  | insert into t2 values (10); | ||
|  | connection addconroot1; | ||
|  | lock tables t2 write; | ||
|  | connection default; | ||
|  | send update v1 set id1= 11; | ||
|  | --sleep 1 | ||
|  | connection addconroot2; | ||
|  | create trigger t1_trg before update on t1 for each row | ||
|  |   insert into t3 values (new.id + 100); | ||
|  | connection addconroot1; | ||
|  | unlock tables; | ||
|  | connection default; | ||
|  | reap; | ||
|  | select * from t1; | ||
|  | select * from t3; | ||
|  | 
 | ||
|  | drop function f1; | ||
|  | drop view v1; | ||
|  | drop table t1, t2, t3; | ||
|  | --enable_parsing | ||
|  | 
 | ||
|  | # | ||
|  | # Test for bug #13399 "Crash when executing PS/SP which should activate | ||
|  | # trigger which is now dropped". See also test for similar bug for stored | ||
|  | # routines in sp-error.test (#12329). | ||
|  | create table t1 (id int); | ||
|  | create table t2 (id int); | ||
|  | create trigger t1_bi before insert on t1 for each row insert into t2 values (new.id); | ||
|  | prepare stmt1 from "insert into t1 values (10)"; | ||
|  | create procedure p1() insert into t1 values (10);  | ||
|  | call p1(); | ||
|  | # Actually it is enough to do FLUSH TABLES instead of DROP TRIGGER | ||
|  | drop trigger t1_bi; | ||
|  | # Server should not crash on these two statements | ||
|  | execute stmt1; | ||
|  | call p1(); | ||
|  | deallocate prepare stmt1; | ||
|  | drop procedure p1; | ||
|  | 
 | ||
|  | # Let us test more complex situation when we alter trigger in such way that | ||
|  | # it uses different set of tables (or simply add new trigger). | ||
|  | create table t3 (id int); | ||
|  | create trigger t1_bi after insert on t1 for each row insert into t2 values (new.id); | ||
|  | prepare stmt1 from "insert into t1 values (10)"; | ||
|  | create procedure p1() insert into t1 values (10);  | ||
|  | call p1(); | ||
|  | # Altering trigger forcing it use different set of tables | ||
|  | drop trigger t1_bi; | ||
|  | create trigger t1_bi after insert on t1 for each row insert into t3 values (new.id); | ||
|  | execute stmt1; | ||
|  | # Until we implement proper mechanism for invalidation of SP statements | ||
|  | # invoked whenever a table used in SP changes, this statement will fail with | ||
|  | # 'Table ...  does not exist' error. | ||
|  | --error ER_NO_SUCH_TABLE  | ||
|  | call p1(); | ||
|  | deallocate prepare stmt1; | ||
|  | drop procedure p1; | ||
|  | drop table t1, t2, t3; | ||
|  | 
 | ||
|  | # | ||
|  | # BUG#13549 "Server crash with nested stored procedures". | ||
|  | # Server should not crash when during execution of stored procedure | ||
|  | # we have to parse trigger/function definition and this new trigger/ | ||
|  | # function has more local variables declared than invoking stored | ||
|  | # procedure and last of these variables is used in argument of NOT | ||
|  | # operator. | ||
|  | # | ||
|  | create table t1 (a int); | ||
|  | DELIMITER //; | ||
|  | CREATE PROCEDURE `p1`() | ||
|  | begin | ||
|  |   insert into t1 values (1); | ||
|  | end// | ||
|  | create trigger trg before insert on t1 for each row  | ||
|  | begin  | ||
|  |   declare done int default 0; | ||
|  |   set done= not done; | ||
|  | end// | ||
|  | DELIMITER ;// | ||
|  | CALL p1(); | ||
|  | drop procedure p1; | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # | ||
|  | # Test for bug #14863 "Triggers: crash if create and there is no current | ||
|  | # database". We should not crash and give proper error when database for | ||
|  | # trigger or its table is not specified and there is no current database. | ||
|  | # | ||
|  | connection addconwithoutdb; | ||
|  | --error ER_NO_DB_ERROR | ||
|  | create trigger t1_bi before insert on test.t1 for each row set @a:=0; | ||
|  | --error ER_NO_SUCH_TABLE | ||
|  | create trigger test.t1_bi before insert on t1 for each row set @a:=0; | ||
|  | --error ER_NO_DB_ERROR | ||
|  | drop trigger t1_bi; | ||
|  | connection default; | ||
|  | 
 | ||
|  | # | ||
|  | # Tests for bug #13525 "Rename table does not keep info of triggers" | ||
|  | # and bug #17866 "Problem with renaming table with triggers with fully | ||
|  | # qualified subject table". | ||
|  | # | ||
|  | create table t1 (id int); | ||
|  | create trigger t1_bi before insert on t1 for each row set @a:=new.id; | ||
|  | create trigger t1_ai after insert on test.t1 for each row set @b:=new.id; | ||
|  | insert into t1 values (101); | ||
|  | select @a, @b; | ||
|  | select trigger_schema, trigger_name, event_object_schema, | ||
|  |        event_object_table, action_statement from information_schema.triggers | ||
|  |        where event_object_schema = 'test'; | ||
|  | rename table t1 to t2; | ||
|  | # Trigger should work after rename | ||
|  | insert into t2 values (102); | ||
|  | select @a, @b; | ||
|  | select trigger_schema, trigger_name, event_object_schema, | ||
|  |        event_object_table, action_statement from information_schema.triggers | ||
|  |        where event_object_schema = 'test'; | ||
|  | # Let us check that the same works for simple ALTER TABLE ... RENAME | ||
|  | alter table t2 rename to t3; | ||
|  | insert into t3 values (103); | ||
|  | select @a, @b; | ||
|  | select trigger_schema, trigger_name, event_object_schema, | ||
|  |        event_object_table, action_statement from information_schema.triggers | ||
|  |        where event_object_schema = 'test'; | ||
|  | # And for more complex ALTER TABLE | ||
|  | alter table t3 rename to t4, add column val int default 0; | ||
|  | insert into t4 values (104, 1); | ||
|  | select @a, @b; | ||
|  | select trigger_schema, trigger_name, event_object_schema, | ||
|  |        event_object_table, action_statement from information_schema.triggers | ||
|  |        where event_object_schema = 'test'; | ||
|  | # .TRN file should be updated with new table name | ||
|  | drop trigger t1_bi; | ||
|  | drop trigger t1_ai; | ||
|  | drop table t4; | ||
|  | # Rename between different databases if triggers exist should fail | ||
|  | create database mysqltest; | ||
|  | use mysqltest; | ||
|  | create table t1 (id int); | ||
|  | create trigger t1_bi before insert on t1 for each row set @a:=new.id; | ||
|  | insert into t1 values (101); | ||
|  | select @a; | ||
|  | select trigger_schema, trigger_name, event_object_schema, | ||
|  |        event_object_table, action_statement from information_schema.triggers | ||
|  |        where event_object_schema = 'test' or event_object_schema = 'mysqltest'; | ||
|  | --error ER_TRG_IN_WRONG_SCHEMA | ||
|  | rename table t1 to test.t2; | ||
|  | insert into t1 values (102); | ||
|  | select @a; | ||
|  | select trigger_schema, trigger_name, event_object_schema, | ||
|  |        event_object_table, action_statement from information_schema.triggers | ||
|  |        where event_object_schema = 'test' or event_object_schema = 'mysqltest'; | ||
|  | # There should be no fantom .TRN files  | ||
|  | --error ER_TRG_DOES_NOT_EXIST | ||
|  | drop trigger test.t1_bi; | ||
|  | # Let us also check handling of this restriction in ALTER TABLE ... RENAME | ||
|  | --error ER_TRG_IN_WRONG_SCHEMA | ||
|  | alter table t1 rename to test.t1; | ||
|  | insert into t1 values (103); | ||
|  | select @a; | ||
|  | select trigger_schema, trigger_name, event_object_schema, | ||
|  |        event_object_table, action_statement from information_schema.triggers | ||
|  |        where event_object_schema = 'test' or event_object_schema = 'mysqltest'; | ||
|  | # Again there should be no fantom .TRN files  | ||
|  | --error ER_TRG_DOES_NOT_EXIST | ||
|  | drop trigger test.t1_bi; | ||
|  | --error ER_TRG_IN_WRONG_SCHEMA | ||
|  | alter table t1 rename to test.t1, add column val int default 0; | ||
|  | insert into t1 values (104); | ||
|  | select @a; | ||
|  | select trigger_schema, trigger_name, event_object_schema, | ||
|  |        event_object_table, action_statement from information_schema.triggers | ||
|  |        where event_object_schema = 'test' or event_object_schema = 'mysqltest'; | ||
|  | # Table definition should not change | ||
|  | show create table t1; | ||
|  | # And once again check for fantom .TRN files  | ||
|  | --error ER_TRG_DOES_NOT_EXIST | ||
|  | drop trigger test.t1_bi; | ||
|  | drop trigger t1_bi; | ||
|  | drop table t1; | ||
|  | drop database mysqltest; | ||
|  | use test; | ||
|  | # And now let us check that the properly handle rename if there is some | ||
|  | # error during it (that we rollback such renames completely). | ||
|  | create table t1 (id int); | ||
|  | create trigger t1_bi before insert on t1 for each row set @a:=new.id; | ||
|  | create trigger t1_ai after insert on t1 for each row set @b:=new.id; | ||
|  | insert into t1 values (101); | ||
|  | select @a, @b; | ||
|  | select trigger_schema, trigger_name, event_object_schema, | ||
|  |        event_object_table, action_statement from information_schema.triggers | ||
|  |        where event_object_schema = 'test'; | ||
|  | # Trick which makes update of second .TRN file impossible | ||
|  | let $MYSQLD_DATADIR= `select @@datadir`; | ||
|  | write_file $MYSQLD_DATADIR/test/t1_ai.TRN~; | ||
|  | dummy | ||
|  | EOF | ||
|  | chmod 0000 $MYSQLD_DATADIR/test/t1_ai.TRN~; | ||
|  | # Normalize the datadir path; the embedded server doesn't chdir to datadir | ||
|  | --replace_result $MYSQLTEST_VARDIR . mysqld.1/data/ '' | ||
|  | --error 1 | ||
|  | rename table t1 to t2; | ||
|  | # 't1' should be still there and triggers should work correctly | ||
|  | insert into t1 values (102); | ||
|  | select @a, @b; | ||
|  | select trigger_schema, trigger_name, event_object_schema, | ||
|  |        event_object_table, action_statement from information_schema.triggers | ||
|  |        where event_object_schema = 'test'; | ||
|  | chmod 0600 $MYSQLD_DATADIR/test/t1_ai.TRN~; | ||
|  | remove_file $MYSQLD_DATADIR/test/t1_ai.TRN~; | ||
|  | # Let us check that updates to .TRN files were rolled back too | ||
|  | drop trigger t1_bi; | ||
|  | drop trigger t1_ai; | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # Test for bug #16829 "Firing trigger with RETURN crashes the server" | ||
|  | # RETURN is not supposed to be used anywhere except functions, so error | ||
|  | # should be returned when one attempts to create trigger with RETURN. | ||
|  | create table t1 (i int); | ||
|  | --error ER_SP_BADRETURN | ||
|  | create trigger t1_bi before insert on t1 for each row return 0; | ||
|  | insert into t1 values (1); | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # Test for bug #17764 "Trigger crashes MyISAM table" | ||
|  | # | ||
|  | # Table was reported as crashed when it was subject table of trigger invoked | ||
|  | # by insert statement which was executed with enabled bulk insert mode (which | ||
|  | # is actually set of optimizations enabled by handler::start_bulk_insert()) | ||
|  | # and this trigger also explicitly referenced it. | ||
|  | # The same problem arose when table to which bulk insert was done was also | ||
|  | # referenced in function called by insert statement. | ||
|  | create table t1 (a varchar(64), b int); | ||
|  | create table t2 like t1; | ||
|  | create trigger t1_ai after insert on t1 for each row | ||
|  |   set @a:= (select max(a) from t1); | ||
|  | insert into t1 (a) values | ||
|  |   ("Twas"),("brillig"),("and"),("the"),("slithy"),("toves"), | ||
|  |   ("Did"),("gyre"),("and"),("gimble"),("in"),("the"),("wabe"); | ||
|  | create trigger t2_ai after insert on t2 for each row | ||
|  |   set @a:= (select max(a) from t2); | ||
|  | insert into t2 select * from t1; | ||
|  | load data infile '../../std_data/words.dat' into table t1 (a); | ||
|  | drop trigger t1_ai; | ||
|  | drop trigger t2_ai; | ||
|  | # Test that the problem for functions is fixed as well | ||
|  | create function f1() returns int return (select max(b) from t1); | ||
|  | insert into t1 values | ||
|  |   ("All",f1()),("mimsy",f1()),("were",f1()),("the",f1()),("borogoves",f1()), | ||
|  |   ("And",f1()),("the",f1()),("mome", f1()),("raths",f1()),("outgrabe",f1()); | ||
|  | create function f2() returns int return (select max(b) from t2); | ||
|  | insert into t2 select a, f2() from t1; | ||
|  | load data infile '../../std_data/words.dat' into table t1 (a) set b:= f1(); | ||
|  | drop function f1; | ||
|  | drop function f2; | ||
|  | drop table t1, t2; | ||
|  | 
 | ||
|  | # | ||
|  | # Test for bug #16021 "Wrong index given to function in trigger" which | ||
|  | # was caused by the same bulk insert optimization as bug #17764 but had | ||
|  | # slightly different symptoms (instead of reporting table as crashed | ||
|  | # storage engine reported error number 124) | ||
|  | # | ||
|  | create table t1(i int not null, j int not null, n numeric(15,2), primary key(i,j)); | ||
|  | create table t2(i int not null, n numeric(15,2), primary key(i)); | ||
|  | delimiter |; | ||
|  | create trigger t1_ai after insert on t1 for each row | ||
|  | begin | ||
|  |   declare sn numeric(15,2); | ||
|  |   select sum(n) into sn from t1 where i=new.i; | ||
|  |   replace into t2 values(new.i, sn); | ||
|  | end| | ||
|  | delimiter ;| | ||
|  | insert into t1 values | ||
|  |   (1,1,10.00),(1,2,10.00),(1,3,10.00),(1,4,10.00),(1,5,10.00), | ||
|  |   (1,6,10.00),(1,7,10.00),(1,8,10.00),(1,9,10.00),(1,10,10.00), | ||
|  |   (1,11,10.00),(1,12,10.00),(1,13,10.00),(1,14,10.00),(1,15,10.00); | ||
|  | select * from t1; | ||
|  | select * from t2; | ||
|  | drop tables t1, t2; | ||
|  | 
 | ||
|  | # | ||
|  | # Test for Bug #16461 connection_id() does not work properly inside trigger | ||
|  | # | ||
|  | --disable_warnings | ||
|  | DROP TABLE IF EXISTS t1; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | CREATE TABLE t1 ( | ||
|  |     conn_id INT, | ||
|  |     trigger_conn_id INT | ||
|  | ); | ||
|  | CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW | ||
|  |   SET NEW.trigger_conn_id = CONNECTION_ID(); | ||
|  | 
 | ||
|  | INSERT INTO t1 (conn_id, trigger_conn_id) VALUES (CONNECTION_ID(), -1); | ||
|  | 
 | ||
|  | connect (con1,localhost,root,,); | ||
|  | INSERT INTO t1 (conn_id, trigger_conn_id) VALUES (CONNECTION_ID(), -1); | ||
|  | connection default; | ||
|  | disconnect con1; | ||
|  | 
 | ||
|  | SELECT * FROM t1 WHERE conn_id != trigger_conn_id; | ||
|  | 
 | ||
|  | DROP TRIGGER t1_bi; | ||
|  | DROP TABLE t1; | ||
|  | 
 | ||
|  | 
 | ||
|  | # | ||
|  | # Bug#6951: Triggers/Traditional: SET @ result wrong | ||
|  | # | ||
|  | --disable_warnings | ||
|  | DROP TABLE IF EXISTS t1; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | CREATE TABLE t1 (i1 INT); | ||
|  | 
 | ||
|  | SET @save_sql_mode=@@sql_mode; | ||
|  | 
 | ||
|  | SET SQL_MODE=''; | ||
|  | 
 | ||
|  | CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW | ||
|  |   SET @x = 5/0; | ||
|  | 
 | ||
|  | SET SQL_MODE='traditional'; | ||
|  | 
 | ||
|  | CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW | ||
|  |   SET @x = 5/0; | ||
|  | 
 | ||
|  | SET @x=1; | ||
|  | INSERT INTO t1 VALUES (@x); | ||
|  | SELECT @x; | ||
|  | 
 | ||
|  | SET @x=2; | ||
|  | UPDATE t1 SET i1 = @x; | ||
|  | SELECT @x; | ||
|  | 
 | ||
|  | SET SQL_MODE=''; | ||
|  | 
 | ||
|  | SET @x=3; | ||
|  | INSERT INTO t1 VALUES (@x); | ||
|  | SELECT @x; | ||
|  | 
 | ||
|  | SET @x=4; | ||
|  | UPDATE t1 SET i1 = @x; | ||
|  | SELECT @x; | ||
|  | 
 | ||
|  | SET @@sql_mode=@save_sql_mode; | ||
|  | 
 | ||
|  | DROP TRIGGER t1_ai; | ||
|  | DROP TRIGGER t1_au; | ||
|  | DROP TABLE t1; | ||
|  | 
 | ||
|  | 
 | ||
|  | # | ||
|  | # Test for bug #14635 Accept NEW.x as INOUT parameters to stored | ||
|  | # procedures from within triggers | ||
|  | # | ||
|  | --disable_warnings | ||
|  | DROP TABLE IF EXISTS t1; | ||
|  | DROP PROCEDURE IF EXISTS p1; | ||
|  | DROP PROCEDURE IF EXISTS p2; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | CREATE TABLE t1 (i1 INT); | ||
|  | 
 | ||
|  | # Check that NEW.x pseudo variable is accepted as INOUT and OUT | ||
|  | # parameter to stored routine. | ||
|  | INSERT INTO t1 VALUES (3); | ||
|  | CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET i1 = 5; | ||
|  | CREATE PROCEDURE p2(INOUT i1 INT) DETERMINISTIC NO SQL SET i1 = i1 * 7; | ||
|  | delimiter //; | ||
|  | CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW | ||
|  | BEGIN | ||
|  |   CALL p1(NEW.i1); | ||
|  |   CALL p2(NEW.i1); | ||
|  | END// | ||
|  | delimiter ;// | ||
|  | UPDATE t1 SET i1 = 11 WHERE i1 = 3; | ||
|  | DROP TRIGGER t1_bu; | ||
|  | DROP PROCEDURE p2; | ||
|  | DROP PROCEDURE p1; | ||
|  | 
 | ||
|  | # Check that OLD.x pseudo variable is not accepted as INOUT and OUT | ||
|  | # parameter to stored routine. | ||
|  | INSERT INTO t1 VALUES (13); | ||
|  | CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET @a = 17; | ||
|  | CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW | ||
|  |   CALL p1(OLD.i1); | ||
|  | --error ER_SP_NOT_VAR_ARG | ||
|  | UPDATE t1 SET i1 = 19 WHERE i1 = 13; | ||
|  | DROP TRIGGER t1_bu; | ||
|  | DROP PROCEDURE p1; | ||
|  | 
 | ||
|  | INSERT INTO t1 VALUES (23); | ||
|  | CREATE PROCEDURE p1(INOUT i1 INT) DETERMINISTIC NO SQL SET @a = i1 * 29; | ||
|  | CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW | ||
|  |   CALL p1(OLD.i1); | ||
|  | --error ER_SP_NOT_VAR_ARG | ||
|  | UPDATE t1 SET i1 = 31 WHERE i1 = 23; | ||
|  | DROP TRIGGER t1_bu; | ||
|  | DROP PROCEDURE p1; | ||
|  | 
 | ||
|  | # Check that NEW.x pseudo variable is read-only in the AFTER TRIGGER. | ||
|  | INSERT INTO t1 VALUES (37); | ||
|  | CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET @a = 41; | ||
|  | CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW | ||
|  |   CALL p1(NEW.i1); | ||
|  | --error ER_SP_NOT_VAR_ARG | ||
|  | UPDATE t1 SET i1 = 43 WHERE i1 = 37; | ||
|  | DROP TRIGGER t1_au; | ||
|  | DROP PROCEDURE p1; | ||
|  | 
 | ||
|  | INSERT INTO t1 VALUES (47); | ||
|  | CREATE PROCEDURE p1(INOUT i1 INT) DETERMINISTIC NO SQL SET @a = i1 * 49; | ||
|  | CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW | ||
|  |   CALL p1(NEW.i1); | ||
|  | --error ER_SP_NOT_VAR_ARG | ||
|  | UPDATE t1 SET i1 = 51 WHERE i1 = 47; | ||
|  | DROP TRIGGER t1_au; | ||
|  | DROP PROCEDURE p1; | ||
|  | 
 | ||
|  | # Post requisite. | ||
|  | SELECT * FROM t1; | ||
|  | 
 | ||
|  | DROP TABLE t1; | ||
|  | 
 | ||
|  | # | ||
|  | # Bug #18005: Creating a trigger on mysql.event leads to server crash on | ||
|  | # scheduler startup | ||
|  | # | ||
|  | # Bug #18361: Triggers on mysql.user table cause server crash | ||
|  | # | ||
|  | # We don't allow triggers on the mysql schema | ||
|  | delimiter |; | ||
|  | --error ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA | ||
|  | create trigger wont_work after update on mysql.user for each row | ||
|  | begin | ||
|  |  set @a:= 1; | ||
|  | end| | ||
|  | # Try when we're already using the mysql schema | ||
|  | use mysql| | ||
|  | --error ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA | ||
|  | create trigger wont_work after update on event for each row | ||
|  | begin | ||
|  |  set @a:= 1; | ||
|  | end| | ||
|  | use test| | ||
|  | delimiter ;| | ||
|  | 
 | ||
|  | 
 | ||
|  | # | ||
|  | # Test for BUG#16899: Possible buffer overflow in handling of DEFINER-clause. | ||
|  | # | ||
|  | 
 | ||
|  | # Prepare. | ||
|  | 
 | ||
|  | --disable_warnings | ||
|  | DROP TABLE IF EXISTS t1; | ||
|  | DROP TABLE IF EXISTS t2; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | CREATE TABLE t1(c INT); | ||
|  | CREATE TABLE t2(c INT); | ||
|  | 
 | ||
|  | --error ER_WRONG_STRING_LENGTH | ||
|  | CREATE DEFINER=1234567890abcdefGHIKL@localhost | ||
|  |   TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET @a = 1; | ||
|  | 
 | ||
|  | --error ER_WRONG_STRING_LENGTH | ||
|  | CREATE DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY | ||
|  |   TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW SET @a = 2; | ||
|  | 
 | ||
|  | # Cleanup. | ||
|  | 
 | ||
|  | DROP TABLE t1; | ||
|  | DROP TABLE t2; | ||
|  | 
 | ||
|  | # | ||
|  | # Bug#20028 Function with select return no data | ||
|  | #  | ||
|  | 
 | ||
|  | --disable_warnings | ||
|  | drop table if exists t1; | ||
|  | drop table if exists t2; | ||
|  | drop table if exists t3; | ||
|  | drop table if exists t4; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | SET @save_sql_mode=@@sql_mode; | ||
|  | 
 | ||
|  | delimiter |; | ||
|  | SET sql_mode='TRADITIONAL'| | ||
|  | create table t1 (id int(10) not null primary key, v int(10) )| | ||
|  | create table t2 (id int(10) not null primary key, v int(10) )| | ||
|  | create table t3 (id int(10) not null primary key, v int(10) )| | ||
|  | create table t4 (c int)| | ||
|  | 
 | ||
|  | create trigger t4_bi before insert on t4 for each row set @t4_bi_called:=1| | ||
|  | create trigger t4_bu before update on t4 for each row set @t4_bu_called:=1| | ||
|  | 
 | ||
|  | insert into t1 values(10, 10)| | ||
|  | set @a:=1/0| | ||
|  | select 1/0 from t1| | ||
|  | 
 | ||
|  | create trigger t1_bi before insert on t1 for each row set @a:=1/0| | ||
|  | 
 | ||
|  | insert into t1 values(20, 20)| | ||
|  | 
 | ||
|  | drop trigger t1_bi| | ||
|  | create trigger t1_bi before insert on t1 for each row | ||
|  | begin | ||
|  |   insert into t2 values (new.id, new.v); | ||
|  |   update t2 set v=v+1 where id= new.id; | ||
|  |   replace t3 values (new.id, 0); | ||
|  |   update t2, t3 set t2.v=new.v, t3.v=new.v where t2.id=t3.id; | ||
|  |   create temporary table t5 select * from t1; | ||
|  |   delete from t5; | ||
|  |   insert into t5 select * from t1; | ||
|  |   insert into t4 values (0); | ||
|  |   set @check= (select count(*) from t5); | ||
|  |   update t4 set c= @check; | ||
|  |   drop temporary table t5; | ||
|  | 
 | ||
|  |   set @a:=1/0; | ||
|  | end| | ||
|  | 
 | ||
|  | set @check=0, @t4_bi_called=0, @t4_bu_called=0| | ||
|  | insert into t1 values(30, 30)| | ||
|  | select @check, @t4_bi_called, @t4_bu_called| | ||
|  | 
 | ||
|  | delimiter ;| | ||
|  | 
 | ||
|  | SET @@sql_mode=@save_sql_mode; | ||
|  | 
 | ||
|  | drop table t1; | ||
|  | drop table t2; | ||
|  | drop table t3; | ||
|  | drop table t4; | ||
|  | 
 | ||
|  | # | ||
|  | # Bug#20670 "UPDATE using key and invoking trigger that modifies | ||
|  | #            this key does not stop" | ||
|  | # | ||
|  | 
 | ||
|  | --disable_warnings | ||
|  | drop table if exists t1; | ||
|  | --enable_warnings | ||
|  | create table t1 (i int, j int key); | ||
|  | insert into t1 values (1,1), (2,2), (3,3); | ||
|  | create trigger t1_bu before update on t1 for each row | ||
|  |   set new.j = new.j + 10; | ||
|  | # This should not work indefinitely and should cause | ||
|  | # expected result | ||
|  | update t1 set i= i+ 10 where j > 2; | ||
|  | select * from t1; | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # | ||
|  | # Bug#23556 TRUNCATE TABLE still maps to DELETE | ||
|  | # | ||
|  | CREATE TABLE t1 (a INT PRIMARY KEY); | ||
|  | CREATE TABLE t2 (a INT PRIMARY KEY); | ||
|  | INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8); | ||
|  | 
 | ||
|  | CREATE TRIGGER trg_t1 BEFORE DELETE on t1 FOR EACH ROW  | ||
|  |   INSERT INTO t2 VALUES (OLD.a); | ||
|  | 
 | ||
|  | FLUSH STATUS; | ||
|  | TRUNCATE t1; | ||
|  | SHOW STATUS LIKE 'handler_delete'; | ||
|  | SELECT COUNT(*) FROM t2; | ||
|  | 
 | ||
|  | INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8); | ||
|  | DELETE FROM t2; | ||
|  | 
 | ||
|  | FLUSH STATUS; | ||
|  | DELETE FROM t1; | ||
|  | SHOW STATUS LIKE 'handler_delete'; | ||
|  | SELECT COUNT(*) FROM t2; | ||
|  | 
 | ||
|  | DROP TRIGGER trg_t1; | ||
|  | DROP TABLE t1,t2; | ||
|  | 
 | ||
|  | # | ||
|  | # Bug #23651 "Server crashes when trigger which uses stored function | ||
|  | #             invoked from different connections". | ||
|  | # | ||
|  | --disable_warnings | ||
|  | drop table if exists t1; | ||
|  | drop function if exists f1; | ||
|  | --enable_warnings | ||
|  | create table t1 (i int); | ||
|  | create function f1() returns int return 10; | ||
|  | create trigger t1_bi before insert on t1 for each row set @a:= f1() + 10; | ||
|  | insert into t1 values (); | ||
|  | select @a; | ||
|  | connection addconroot1; | ||
|  | insert into t1 values (); | ||
|  | select @a; | ||
|  | connection default; | ||
|  | drop table t1; | ||
|  | drop function f1; | ||
|  | 
 | ||
|  | # | ||
|  | # Bug#23703: DROP TRIGGER needs an IF EXISTS | ||
|  | # | ||
|  | 
 | ||
|  | --disable_warnings | ||
|  | drop table if exists t1; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | create table t1(a int, b varchar(50)); | ||
|  | 
 | ||
|  | -- error ER_TRG_DOES_NOT_EXIST | ||
|  | drop trigger not_a_trigger; | ||
|  | 
 | ||
|  | drop trigger if exists not_a_trigger; | ||
|  | 
 | ||
|  | create trigger t1_bi before insert on t1 | ||
|  | for each row set NEW.b := "In trigger t1_bi"; | ||
|  | 
 | ||
|  | insert into t1 values (1, "a"); | ||
|  | drop trigger if exists t1_bi; | ||
|  | insert into t1 values (2, "b"); | ||
|  | drop trigger if exists t1_bi; | ||
|  | insert into t1 values (3, "c"); | ||
|  | 
 | ||
|  | select * from t1; | ||
|  | 
 | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # | ||
|  | # Bug#25398: crash when a trigger contains a SELECT with  | ||
|  | #            trigger fields in the select list under DISTINCT | ||
|  | # | ||
|  | 
 | ||
|  | CREATE TABLE t1 ( | ||
|  |   id int NOT NULL DEFAULT '0', | ||
|  |   a  varchar(10) NOT NULL, | ||
|  |   b  varchar(10), | ||
|  |   c  varchar(10), | ||
|  |   d  timestamp NOT NULL, | ||
|  |   PRIMARY KEY (id, a) | ||
|  | ); | ||
|  | 
 | ||
|  | CREATE TABLE t2 ( | ||
|  |   fubar_id         int unsigned NOT NULL DEFAULT '0', | ||
|  |   last_change_time datetime NOT NULL DEFAULT '0000-00-00 00:00:00', | ||
|  |   PRIMARY KEY  (fubar_id) | ||
|  | ); | ||
|  | 
 | ||
|  | DELIMITER |; | ||
|  | 
 | ||
|  | CREATE TRIGGER fubar_change | ||
|  |   AFTER UPDATE ON t1 | ||
|  |     FOR EACH ROW | ||
|  |       BEGIN | ||
|  |         INSERT INTO t2 (fubar_id, last_change_time) | ||
|  |           SELECT DISTINCT NEW.id AS fubar_id, NOW() AS last_change_time | ||
|  |             FROM t1 WHERE (id = NEW.id) AND (OLD.c != NEW.c) | ||
|  |         ON DUPLICATE KEY UPDATE | ||
|  |           last_change_time = | ||
|  |             IF((fubar_id = NEW.id)AND(OLD.c != NEW.c),NOW(),last_change_time); | ||
|  |       END | ||
|  | | | ||
|  | 
 | ||
|  | DELIMITER ;| | ||
|  | 
 | ||
|  | INSERT INTO t1 (id,a, b,c,d) VALUES | ||
|  |  (1,'a','b','c',now()),(2,'a','b','c',now()); | ||
|  | 
 | ||
|  | UPDATE t1 SET c='Bang!' WHERE id=1; | ||
|  | 
 | ||
|  | SELECT fubar_id FROM t2; | ||
|  | 
 | ||
|  | DROP TABLE t1,t2; | ||
|  | 
 | ||
|  | # | ||
|  | # Bug#21285 (Incorrect message error deleting records in a table with a | ||
|  | #           trigger for inserting) | ||
|  | # | ||
|  | 
 | ||
|  | --disable_warnings | ||
|  | DROP TABLE IF EXISTS bug21825_A; | ||
|  | DROP TABLE IF EXISTS bug21825_B; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | CREATE TABLE bug21825_A (id int(10)); | ||
|  | CREATE TABLE bug21825_B (id int(10)); | ||
|  | 
 | ||
|  | delimiter //; | ||
|  | 
 | ||
|  | CREATE TRIGGER trgA AFTER INSERT ON bug21825_A | ||
|  | FOR EACH ROW | ||
|  | BEGIN | ||
|  |   INSERT INTO bug21825_B (id) values (1); | ||
|  | END// | ||
|  | delimiter ;// | ||
|  | 
 | ||
|  | INSERT INTO bug21825_A (id) VALUES (10); | ||
|  | INSERT INTO bug21825_A (id) VALUES (20); | ||
|  | 
 | ||
|  | DROP TABLE bug21825_B; | ||
|  | 
 | ||
|  | # Must pass, the missing table in the insert trigger should not matter. | ||
|  | DELETE FROM bug21825_A WHERE id = 20; | ||
|  | 
 | ||
|  | DROP TABLE bug21825_A; | ||
|  | 
 | ||
|  | # | ||
|  | # Bug#22580 (DROP TABLE in nested stored procedure causes strange dependancy | ||
|  | # error) | ||
|  | # | ||
|  | 
 | ||
|  | --disable_warnings | ||
|  | DROP TABLE IF EXISTS bug22580_t1; | ||
|  | DROP PROCEDURE IF EXISTS bug22580_proc_1; | ||
|  | DROP PROCEDURE IF EXISTS bug22580_proc_2; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | CREATE TABLE bug22580_t1 (a INT, b INT); | ||
|  | 
 | ||
|  | DELIMITER ||; | ||
|  | 
 | ||
|  | CREATE PROCEDURE bug22580_proc_2() | ||
|  | BEGIN | ||
|  |   DROP TABLE IF EXISTS bug22580_tmp; | ||
|  |   CREATE TEMPORARY TABLE bug22580_tmp (a INT); | ||
|  |   DROP TABLE bug22580_tmp; | ||
|  | END|| | ||
|  | 
 | ||
|  | CREATE PROCEDURE bug22580_proc_1() | ||
|  | BEGIN | ||
|  |   CALL bug22580_proc_2(); | ||
|  | END|| | ||
|  | 
 | ||
|  | CREATE TRIGGER t1bu BEFORE UPDATE ON bug22580_t1 | ||
|  | FOR EACH ROW  | ||
|  | BEGIN | ||
|  |   CALL bug22580_proc_1(); | ||
|  | END|| | ||
|  | 
 | ||
|  | DELIMITER ;|| | ||
|  | 
 | ||
|  | # Must pass, the actions of the update trigger should not matter | ||
|  | INSERT INTO bug22580_t1 VALUES (1,1); | ||
|  | 
 | ||
|  | DROP TABLE bug22580_t1; | ||
|  | DROP PROCEDURE bug22580_proc_1; | ||
|  | DROP PROCEDURE bug22580_proc_2; | ||
|  | 
 | ||
|  | # | ||
|  | # Bug#27006: AFTER UPDATE triggers not fired with INSERT ... ON DUPLICATE | ||
|  | # | ||
|  | --disable_warnings | ||
|  | DROP TRIGGER IF EXISTS trg27006_a_update; | ||
|  | DROP TRIGGER IF EXISTS trg27006_a_insert; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | CREATE TABLE t1 ( | ||
|  |   `id` int(10) unsigned NOT NULL auto_increment, | ||
|  |   `val` varchar(10) NOT NULL, | ||
|  |   PRIMARY KEY  (`id`) | ||
|  | ); | ||
|  | CREATE TABLE t2 like t1; | ||
|  | DELIMITER |; | ||
|  | 
 | ||
|  | CREATE TRIGGER trg27006_a_insert AFTER INSERT ON t1 FOR EACH ROW | ||
|  | BEGIN | ||
|  |     insert into t2 values (NULL,new.val); | ||
|  | END | | ||
|  | CREATE TRIGGER trg27006_a_update AFTER UPDATE ON t1 FOR EACH ROW | ||
|  | BEGIN | ||
|  |     insert into t2 values (NULL,new.val); | ||
|  | END | | ||
|  | DELIMITER ;| | ||
|  | 
 | ||
|  | INSERT INTO t1(val) VALUES ('test1'),('test2'); | ||
|  | SELECT * FROM t1; | ||
|  | SELECT * FROM t2; | ||
|  | INSERT INTO t1 VALUES (2,'test2') ON DUPLICATE KEY UPDATE val=VALUES(val); | ||
|  | INSERT INTO t1 VALUES (2,'test3') ON DUPLICATE KEY UPDATE val=VALUES(val); | ||
|  | INSERT INTO t1 VALUES (3,'test4') ON DUPLICATE KEY UPDATE val=VALUES(val); | ||
|  | SELECT * FROM t1; | ||
|  | SELECT * FROM t2; | ||
|  | DROP TRIGGER trg27006_a_insert; | ||
|  | DROP TRIGGER trg27006_a_update; | ||
|  | drop table t1,t2; | ||
|  | 
 | ||
|  | # | ||
|  | # Bug #20903 "Crash when using CREATE TABLE .. SELECT and triggers" | ||
|  | # | ||
|  | 
 | ||
|  | --disable_warnings | ||
|  | drop table if exists t1, t2, t3; | ||
|  | --enable_warnings | ||
|  | create table t1 (i int); | ||
|  | create trigger t1_bi before insert on t1 for each row set new.i = 7; | ||
|  | create trigger t1_ai after insert on t1 for each row set @a := 7; | ||
|  | create table t2 (j int); | ||
|  | insert into t2 values (1), (2); | ||
|  | set @a:=""; | ||
|  | create table if not exists t1 select * from t2; | ||
|  | select * from t1; | ||
|  | select @a; | ||
|  | # Let us check that trigger that involves table also works ok. | ||
|  | drop trigger t1_bi; | ||
|  | drop trigger t1_ai; | ||
|  | create table t3 (isave int); | ||
|  | create trigger t1_bi before insert on t1 for each row insert into t3 values (new.i); | ||
|  | create table if not exists t1 select * from t2; | ||
|  | select * from t1; | ||
|  | select * from t3; | ||
|  | drop table t1, t2, t3; | ||
|  | 
 | ||
|  | disconnect addconroot1; | ||
|  | disconnect addconroot2; | ||
|  | disconnect addconwithoutdb; | ||
|  | # | ||
|  | # Bug #26162: Trigger DML ignores low_priority_updates setting | ||
|  | # | ||
|  | CREATE TABLE t1 (id INTEGER); | ||
|  | CREATE TABLE t2 (id INTEGER); | ||
|  | 
 | ||
|  | INSERT INTO t2 VALUES (1),(2); | ||
|  | 
 | ||
|  | # trigger that produces the high priority insert, but should be low, adding | ||
|  | # LOW_PRIORITY fixes this | ||
|  | CREATE TRIGGER t1_test AFTER INSERT ON t1 FOR EACH ROW  | ||
|  |   INSERT INTO t2 VALUES (new.id); | ||
|  | 
 | ||
|  | CONNECT (rl_holder,    localhost, root,,); | ||
|  | CONNECT (rl_acquirer,  localhost, root,,); | ||
|  | CONNECT (wl_acquirer,  localhost, root,,); | ||
|  | CONNECT (rl_contender, localhost, root,,); | ||
|  | 
 | ||
|  | CONNECTION rl_holder; | ||
|  | SELECT GET_LOCK('B26162',120); | ||
|  | 
 | ||
|  | CONNECTION rl_acquirer; | ||
|  | --send | ||
|  | SELECT 'rl_acquirer', GET_LOCK('B26162',120), id FROM t2 WHERE id = 1; | ||
|  | 
 | ||
|  | CONNECTION wl_acquirer; | ||
|  | SET SESSION LOW_PRIORITY_UPDATES=1; | ||
|  | SET GLOBAL LOW_PRIORITY_UPDATES=1; | ||
|  | #need to wait for rl_acquirer to lock on the B26162 lock  | ||
|  | sleep 2; | ||
|  | --send | ||
|  | INSERT INTO t1 VALUES (5); | ||
|  | 
 | ||
|  | CONNECTION rl_contender; | ||
|  | # must not "see" the row inserted by the INSERT (as it must run before the | ||
|  | # INSERT) | ||
|  | --send | ||
|  | SELECT 'rl_contender', id FROM t2 WHERE id > 1; | ||
|  | 
 | ||
|  | CONNECTION rl_holder; | ||
|  | #need to wait for wl_acquirer and rl_contender to lock on t2  | ||
|  | sleep 2; | ||
|  | SELECT RELEASE_LOCK('B26162'); | ||
|  | 
 | ||
|  | CONNECTION rl_acquirer; | ||
|  | --reap | ||
|  | SELECT RELEASE_LOCK('B26162'); | ||
|  | CONNECTION wl_acquirer; | ||
|  | --reap | ||
|  | CONNECTION rl_contender; | ||
|  | --reap | ||
|  | 
 | ||
|  | CONNECTION default; | ||
|  | DISCONNECT rl_acquirer; | ||
|  | DISCONNECT wl_acquirer; | ||
|  | DISCONNECT rl_contender; | ||
|  | DISCONNECT rl_holder; | ||
|  | 
 | ||
|  | 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 | ||
|  | --echo Bug#27248 Triggers: error if insert affects temporary table | ||
|  | --echo | ||
|  | --echo The bug was fixed by the fix for Bug#26141 | ||
|  | --echo | ||
|  | --disable_warnings | ||
|  | drop table if exists t1; | ||
|  | drop temporary table if exists t2; | ||
|  | --enable_warnings | ||
|  | create table t1 (s1 int); | ||
|  | create temporary table t2 (s1 int); | ||
|  | create trigger t1_bi before insert on t1 for each row insert into t2 values (0); | ||
|  | create trigger t1_bd before delete on t1 for each row delete from t2; | ||
|  | insert into t1 values (0); | ||
|  | insert into t1 values (0); | ||
|  | select * from t1; | ||
|  | select * from t2; | ||
|  | delete from t1; | ||
|  | select * from t1; | ||
|  | select * from t2; | ||
|  | drop table t1; | ||
|  | drop temporary table t2; | ||
|  | 
 | ||
|  | --echo #------------------------------------------------------------------------ | ||
|  | --echo # Bug#39953 Triggers are not working properly with multi table updates | ||
|  | --echo #------------------------------------------------------------------------ | ||
|  | 
 | ||
|  | --disable_warnings | ||
|  | DROP TABLE IF EXISTS t1; | ||
|  | DROP TRIGGER IF EXISTS t_insert; | ||
|  | DROP TABLE IF EXISTS t2; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | CREATE TABLE t1 (a int, date_insert timestamp, PRIMARY KEY (a)); | ||
|  | INSERT INTO t1 (a) VALUES (2),(5); | ||
|  | CREATE TABLE t2 (a int, b int, PRIMARY KEY (a)); | ||
|  | DELIMITER |; | ||
|  | CREATE TRIGGER t_insert AFTER INSERT ON t2 FOR EACH ROW BEGIN UPDATE t1,t2 SET | ||
|  | date_insert=NOW() WHERE t1.a=t2.b AND t2.a=NEW.a; END | | ||
|  | DELIMITER ;| | ||
|  | INSERT INTO t2 (a,b) VALUES (1,2); | ||
|  | 
 | ||
|  | DROP TRIGGER t_insert; | ||
|  | 
 | ||
|  | DELIMITER |; | ||
|  | CREATE TRIGGER t_insert AFTER INSERT ON t2 FOR EACH ROW BEGIN UPDATE t1,t2 SET | ||
|  | date_insert=NOW(),b=b+1 WHERE t1.a=t2.b AND t2.a=NEW.a; END | | ||
|  | DELIMITER ;| | ||
|  | --error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG | ||
|  | INSERT INTO t2 (a,b) VALUES (3,5); | ||
|  | 
 | ||
|  | DROP TABLE t1; | ||
|  | DROP TRIGGER t_insert; | ||
|  | DROP TABLE t2; | ||
|  | 
 | ||
|  | --echo End of 5.0 tests | ||
|  | 
 | ||
|  | # | ||
|  | # Bug#25411 (trigger code truncated) | ||
|  | # | ||
|  | 
 | ||
|  | --disable_warnings | ||
|  | drop table if exists table_25411_a; | ||
|  | drop table if exists table_25411_b; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | create table table_25411_a(a int); | ||
|  | create table table_25411_b(b int); | ||
|  | 
 | ||
|  | create trigger trg_25411a_ai after insert on table_25411_a | ||
|  | for each row | ||
|  |   insert into table_25411_b select new.*; | ||
|  | 
 | ||
|  | select * from table_25411_a; | ||
|  | 
 | ||
|  | --error ER_BAD_TABLE_ERROR | ||
|  | insert into table_25411_a values (1); | ||
|  | 
 | ||
|  | select * from table_25411_a; | ||
|  | 
 | ||
|  | drop table table_25411_a; | ||
|  | drop table table_25411_b; | ||
|  | 
 | ||
|  | # | ||
|  | # Bug #31866: MySQL Server crashes on SHOW CREATE TRIGGER statement | ||
|  | # | ||
|  | 
 | ||
|  | --disable_warnings | ||
|  | DROP TRIGGER IF EXISTS trg; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | --error ER_TRG_DOES_NOT_EXIST | ||
|  | SHOW CREATE TRIGGER trg; | ||
|  | 
 | ||
|  | # | ||
|  | # Bug#23713 LOCK TABLES + CREATE TRIGGER + FLUSH TABLES WITH READ LOCK = deadlock | ||
|  | # | ||
|  | # Test of trigger creation and removal under LOCK TABLES | ||
|  | # | ||
|  | 
 | ||
|  | --disable_warnings | ||
|  | drop table if exists t1; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | create table t1 (i int, j int); | ||
|  | 
 | ||
|  | create trigger t1_bi before insert on t1 for each row begin end; | ||
|  | --error ER_NOT_SUPPORTED_YET | ||
|  | create trigger t1_bi before insert on t1 for each row begin end; | ||
|  | drop trigger t1_bi; | ||
|  | --error ER_TRG_DOES_NOT_EXIST | ||
|  | drop trigger t1_bi; | ||
|  | 
 | ||
|  | lock tables t1 read; | ||
|  | --error ER_TABLE_NOT_LOCKED_FOR_WRITE | ||
|  | create trigger t1_bi before insert on t1 for each row begin end; | ||
|  | --error ER_TABLE_NOT_LOCKED_FOR_WRITE | ||
|  | create trigger t1_bi before insert on t1 for each row begin end; | ||
|  | --error ER_TRG_DOES_NOT_EXIST | ||
|  | drop trigger t1_bi; | ||
|  | unlock tables; | ||
|  | 
 | ||
|  | create trigger t1_bi before insert on t1 for each row begin end; | ||
|  | lock tables t1 read; | ||
|  | --error ER_TABLE_NOT_LOCKED_FOR_WRITE | ||
|  | create trigger t1_bi before insert on t1 for each row begin end; | ||
|  | --error ER_TABLE_NOT_LOCKED_FOR_WRITE | ||
|  | drop trigger t1_bi; | ||
|  | unlock tables; | ||
|  | drop trigger t1_bi; | ||
|  | 
 | ||
|  | lock tables t1 write; | ||
|  | create trigger b1_bi before insert on t1 for each row set new.i = new.i + 10; | ||
|  | insert into t1 values (10, 10); | ||
|  | drop trigger b1_bi; | ||
|  | insert into t1 values (10, 10); | ||
|  | select * from t1; | ||
|  | unlock tables; | ||
|  | 
 | ||
|  | drop table t1; | ||
|  | 
 | ||
|  | # | ||
|  | # Bug#23771 AFTER UPDATE trigger not invoked when there are no changes of the data | ||
|  | # | ||
|  | 
 | ||
|  | --disable_warnings | ||
|  | drop table if exists t1, t2; | ||
|  | drop trigger if exists trg1; | ||
|  | drop trigger if exists trg2; | ||
|  | --enable_warnings | ||
|  | create table t1 (a int); | ||
|  | create table t2 (b int); | ||
|  | create trigger trg1 after update on t1 for each row set @a= @a+1; | ||
|  | create trigger trg2 after update on t2 for each row set @b= @b+1; | ||
|  | insert into t1 values (1), (2), (3); | ||
|  | insert into t2 values (1), (2), (3); | ||
|  | set @a= 0; | ||
|  | set @b= 0; | ||
|  | update t1, t2 set t1.a= t1.a, t2.b= t2.b; | ||
|  | select @a, @b; | ||
|  | update t1, t2 set t1.a= t2.b, t2.b= t1.a; | ||
|  | select @a, @b; | ||
|  | update t1 set a= a; | ||
|  | select @a, @b; | ||
|  | update t2 set b= b; | ||
|  | select @a, @b; | ||
|  | update t1 set a= 1; | ||
|  | select @a, @b; | ||
|  | update t2 set b= 1; | ||
|  | select @a, @b; | ||
|  | drop trigger trg1; | ||
|  | drop trigger trg2; | ||
|  | drop table t1, t2; | ||
|  | 
 | ||
|  | # | ||
|  | # Bug#44653: Server crash noticed when executing random queries with partitions. | ||
|  | # | ||
|  | CREATE TABLE t1 ( a INT, b INT ); | ||
|  | CREATE TABLE t2 ( a INT AUTO_INCREMENT KEY, b INT ); | ||
|  | 
 | ||
|  | INSERT INTO t1 (a) VALUES (1); | ||
|  | 
 | ||
|  | delimiter //; | ||
|  | CREATE TRIGGER tr1 | ||
|  | BEFORE INSERT ON t2 | ||
|  | FOR EACH ROW  | ||
|  | BEGIN  | ||
|  |   UPDATE a_nonextisting_table SET a = 1; | ||
|  | END// | ||
|  | delimiter ;// | ||
|  | 
 | ||
|  | --disable_abort_on_error | ||
|  | CREATE TABLE IF NOT EXISTS t2 ( a INT, b INT ) SELECT a, b FROM t1; | ||
|  | --enable_abort_on_error | ||
|  | 
 | ||
|  | # Caused failed assertion | ||
|  | SELECT * FROM t2; | ||
|  | 
 | ||
|  | DROP TABLE t1, t2; | ||
|  | 
 | ||
|  | --echo # | ||
|  | --echo # Bug#51650 crash with user variables and triggers | ||
|  | --echo # | ||
|  | 
 | ||
|  | --disable_warnings | ||
|  | DROP TRIGGER IF EXISTS trg1; | ||
|  | DROP TABLE IF EXISTS t1, t2; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | CREATE TABLE t1 (b VARCHAR(50) NOT NULL); | ||
|  | CREATE TABLE t2 (a VARCHAR(10) NOT NULL DEFAULT ''); | ||
|  | 
 | ||
|  | delimiter //; | ||
|  | CREATE TRIGGER trg1 AFTER INSERT ON t2 | ||
|  | FOR EACH ROW BEGIN | ||
|  |   SELECT 1 FROM t1 c WHERE | ||
|  |     (@bug51650 IS NULL OR @bug51650 != c.b) AND c.b = NEW.a LIMIT 1 INTO @foo; | ||
|  | END// | ||
|  | delimiter ;// | ||
|  | 
 | ||
|  | SET @bug51650 = 1; | ||
|  | INSERT IGNORE INTO t2 VALUES(); | ||
|  | INSERT IGNORE INTO t1 SET b = '777'; | ||
|  | INSERT IGNORE INTO t2 SET a = '111'; | ||
|  | SET @bug51650 = 1; | ||
|  | INSERT IGNORE INTO t2 SET a = '777'; | ||
|  | 
 | ||
|  | DROP TRIGGER trg1; | ||
|  | DROP TABLE t1, t2; | ||
|  | 
 | ||
|  | # | ||
|  | # Bug #48525: trigger changes "Column 'id' cannot be null" behaviour | ||
|  | # | ||
|  | CREATE TABLE t1 (id INT NOT NULL); | ||
|  | CREATE TABLE t2 (id INT NOT NULL); | ||
|  | INSERT t1 VALUES (1),(2),(3); | ||
|  | UPDATE t1 SET id=NULL; | ||
|  | CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW | ||
|  |   INSERT INTO t2 VALUES (3); | ||
|  | UPDATE t1 SET id=NULL; | ||
|  | DROP TRIGGER t1_bu; | ||
|  | DROP TABLE t1,t2; | ||
|  | 
 | ||
|  | --echo # | ||
|  | --echo # Bug#50755: Crash if stored routine def contains version comments | ||
|  | --echo # | ||
|  | 
 | ||
|  | --disable_warnings | ||
|  | DROP DATABASE IF EXISTS db1; | ||
|  | DROP TRIGGER IF EXISTS trg1; | ||
|  | DROP TABLE IF EXISTS t1, t2; | ||
|  | --enable_warnings | ||
|  | 
 | ||
|  | CREATE DATABASE db1; | ||
|  | USE db1; | ||
|  | 
 | ||
|  | CREATE TABLE t1 (b INT); | ||
|  | CREATE TABLE t2 (a INT); | ||
|  | 
 | ||
|  | CREATE TRIGGER trg1 BEFORE INSERT ON t2 FOR EACH ROW INSERT/*!INTO*/t1 VALUES (1); | ||
|  | --echo # Used to crash | ||
|  | SHOW TRIGGERS IN db1; | ||
|  | --error ER_PARSE_ERROR | ||
|  | INSERT INTO t2 VALUES (1); | ||
|  | SELECT * FROM t1; | ||
|  | 
 | ||
|  | --echo # Work around Bug#45235 | ||
|  | let $MYSQLD_DATADIR = `select @@datadir`; | ||
|  | --remove_file $MYSQLD_DATADIR/db1/t2.TRG | ||
|  | --remove_file $MYSQLD_DATADIR/db1/trg1.TRN | ||
|  | 
 | ||
|  | DROP DATABASE db1; | ||
|  | USE test; | ||
|  | 
 | ||
|  | --echo End of 5.1 tests. |