mariadb/mysql-test/r/trigger.result
unknown c3da2d12f7 Fix for bug #5888 "Triggers with nonexistent columns cause packets
out of order". (final version)

Now instead of binding Item_trigger_field to TABLE objects during
trigger definition parsing at table open, we perform pass through
special list of all such objects in trigger. This allows easily check
all references to fields in old/new version of row in trigger during
execution of CREATE TRIGGER statement (this is more courtesy for users
since we can't check everything anyway).
We also report that such reference is bad by returning error from
Item_trigger_field::fix_fields() method (instead of setup_field())
This means that if trigger is broken we will bark during trigger
execution instead of trigger definition parsing at table open.
(i.e. now we allow to open tables with broken triggers).


mysql-test/r/trigger.result:
  Added test which attempts to create trigger for table referencing to
  field which does not exist in this table.
mysql-test/t/trigger.test:
  Added test which attempts to create trigger for table referencing to
  field which does not exist in this table.
sql/item.cc:
  Item_trigger_field::setup_field() now returns void. If any error
  will occur we will report it at fix_fields() stage.
sql/item.h:
  Item_trigger_field:
  - Added next_trg_field member for linking all such objects in trigger
    in one list.
  - Also setup_field() now returns void. If any error will occur we will
    report it at fix_fields() stage.
sql/mysql_priv.h:
  Added SQL_LIST::push_back() method which allows to add another SQL_LIST
  to the end of this SQL_LIST.
sql/sp_head.cc:
  sp_head::init()/reset_lex()/restore_lex():
   In order to fill global LEX::trg_table_fields (list of all 
   Item_trigger_field objects for trigger) we should init the same list
   in LEX of substatement before its parsing and merge it to global list
   after parsing.
sql/sp_head.h:
  sp_instr_trigger_field:
    Made trigger_field member public to be able to add it more easily to
    global list of all Item_trigger_field objects in trigger.
sql/sql_lex.cc:
  LEX::trg_table was removed.
sql/sql_lex.h:
  Now we are binding Item_trigger_field's to TABLE object by passing
  through specially constructed list of all such objects in this trigger
  instead of doing this during trigger definition parsing at table open.
  So we no longer need LEX::trg_table, we use LEX::trg_table_fields list
  instead.
sql/sql_parse.cc:
  mysql_execute_command():
    Since now we use trigger body for some checks in
    mysql_create_or_drop_trigger() we should destroy it only
    after calling this function.
sql/sql_trigger.cc:
  Now instead of binding Item_trigger_field to TABLE objects during
  trigger definition parsing at table open, we perform pass through
  special list of all such objects in trigger. This allows easily check
  all references to fields in old/new version of row in trigger during
  execution of CREATE TRIGGER statement (this is more courtesy for users
  since we can't check everything anyway).
  We also report that such reference is bad by returning error from
  Item_trigger_field::fix_fields() method (instead of setup_field())
  This means that if trigger is broken we will bark during trigger
  execution instead of trigger definition parsing at table open.
  (i.e. now we allow to open tables with broken triggers).
  
  Table_triggers_list::prepare_old_row_accessors() method was added to be
  able to reuse code creating Field objects referencing TABLE::record[1]
  buffer instead of TABLE::record[0].
sql/sql_trigger.h:
  Added Table_triggers_list::prepare_old_row_accessors() method to be
  able to reuse code creating Field objects referencing to TABLE::record[1]
  instead of record[0].
sql/sql_yacc.yy:
  Now instead of performing binding of Item_trigger_field objects
  to TABLE object during trigger definition parsing at table open,
  we perform this binding by passing through specially constructed
  list of all such items in trigger.
  We also check value returned from memory allocation functions.
2004-11-24 12:24:02 +03:00

192 lines
5.1 KiB
Text

drop table if exists t1, t2;
drop view if exists v1;
create table t1 (i int);
create trigger trg before insert on t1 for each row set @a:=1;
set @a:=0;
select @a;
@a
0
insert into t1 values (1);
select @a;
@a
1
drop trigger t1.trg;
create trigger trg before insert on t1 for each row set @a:=new.i;
insert into t1 values (123);
select @a;
@a
123
drop trigger t1.trg;
drop table t1;
create table t1 (i int not null, j int);
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|
i j
1 10
2 3
drop trigger t1.trg|
drop table t1|
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;
@a
2:3:4:5
drop trigger t1.trg;
drop table t1;
create table t1 (aid int not null primary key, balance int not null default 0);
insert into t1 values (1, 1000), (2,3000);
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|
@update_failed
Too big change for aid = 2
aid balance
1 1500
2 3000
drop trigger t1.trg|
drop table t1|
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;
@total_change
2
drop trigger t1.trg;
drop table t1;
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;
@del_sum
6
drop trigger t1.trg;
drop table t1;
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;
@del
1
drop trigger t1.trg;
drop table t1;
create table t1 (i int, j int);
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|
set @fired:="";
insert into t1 values (1,2),(2,3),(3,14);
select @fired;
@fired
select * from t1;
i j
1 2
2 3
3 10
update t1 set j= 20;
select @fired;
@fired
Yes
select * from t1;
i j
1 20
2 -1
3 20
drop trigger t1.trg1;
drop trigger t1.trg2;
drop trigger t1.trg3;
drop table t1;
create table t1 (i int);
create trigger trg before insert on t1 for each row set @a:= old.i;
ERROR HY000: There is no OLD row in on INSERT trigger
create trigger trg before delete on t1 for each row set @a:= new.i;
ERROR HY000: There is no NEW row in on DELETE trigger
create trigger trg before update on t1 for each row set old.i:=1;
ERROR HY000: Updating of OLD row is not allowed in trigger
create trigger trg before delete on t1 for each row set new.i:=1;
ERROR HY000: There is no NEW row in on DELETE trigger
create trigger trg after update on t1 for each row set new.i:=1;
ERROR HY000: Updating of NEW row is not allowed in after trigger
create trigger trg before update on t1 for each row set new.j:=1;
ERROR 42S22: Unknown column 'j' in 'NEW'
create trigger trg before update on t1 for each row set @a:=old.j;
ERROR 42S22: Unknown column 'j' in 'OLD'
create trigger trg before insert on t2 for each row set @a:=1;
ERROR 42S02: Table 'test.t2' doesn't exist
create trigger trg before insert on t1 for each row set @a:=1;
create trigger trg after insert on t1 for each row set @a:=1;
ERROR HY000: Trigger already exists
create trigger trg2 before insert on t1 for each row set @a:=1;
ERROR HY000: Trigger already exists
drop trigger t1.trg;
drop trigger t1.trg;
ERROR HY000: Trigger does not exist
create view v1 as select * from t1;
create trigger trg before insert on v1 for each row set @a:=1;
ERROR HY000: Trigger's 'v1' is view or temporary table
drop view v1;
drop table t1;
create temporary table t1 (i int);
create trigger trg before insert on t1 for each row set @a:=1;
ERROR HY000: Trigger's 't1' is view or temporary table
drop table t1;
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 t1.tx1;
drop table t1;
create table t1 (i int) engine=myisam;
insert into t1 values (1), (2);
create trigger trg1 before delete on t1 for each row set @del_before:= @del_before + old.i;
create trigger trg2 after delete on t1 for each row set @del_after:= @del_after + old.i;
set @del_before:=0, @del_after:= 0;
delete from t1;
select @del_before, @del_after;
@del_before @del_after
3 3
drop trigger t1.trg1;
drop trigger t1.trg2;
drop table t1;