mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
WL#1218 "Triggers". Some very preliminary version of patch.
Mostly needed for Monty for him getting notion what needed for triggers from new .FRM format. Things to be done: - Right placement of trigger's invocations - Right handling of errors in triggers (including transaction rollback) - Support for priviliges - Right handling of DROP/RENAME table (hope that it will be handled automatically with merging of .TRG into .FRM file) - Saving/restoring some information critical for trigger creation and replication with their definitions (e.g. sql_mode, creator, ...) - Replication Already has some known bugs so probably not for general review. include/mysqld_error.h: Added trigger related error codes. sql/Makefile.am: Added sql_trigger.* files to list of sources from which mysqld is built. sql/item.cc: Added Item_trigger_field class representing field of new/old version of row which is inserted/updated/deleted and for which trigger is invoked. sql/item.h: Added enums for describing trigger properties. (Here because of dependencies). Added Item_trigger_field class representing field of new/old version of row which is inserted/updated/deleted and for which trigger is invoked. sql/item_func.cc: Added Item_func_set_user_var::print_as_stmt() for printing of assignment to ser variable from stored procedures. Added comment clarifying why we don't need set no_send_ok when calling stored functions. sql/item_func.h: Added Item_func_set_user_var::print_as_stmt() for printing of assignment to ser variable from stored procedures. sql/lex.h: Symbols used in statements defining triggers were added. sql/mysql_priv.h: Exported some functions needed for triggers implementation. sql/parse_file.cc: Cleaned up FILE_OPTIONS_STRLIST handling (needed for triggers). sql/parse_file.h: Cleaned up FILE_OPTIONS_STRLIST handling (needed for triggers). sql/share/czech/errmsg.txt: Added trigger related error messages. sql/share/danish/errmsg.txt: Added trigger related error messages. sql/share/dutch/errmsg.txt: Added trigger related error messages. sql/share/english/errmsg.txt: Added trigger related error messages. sql/share/estonian/errmsg.txt: Added trigger related error messages. sql/share/french/errmsg.txt: Added trigger related error messages. sql/share/german/errmsg.txt: Added trigger related error messages. sql/share/greek/errmsg.txt: Added trigger related error messages. sql/share/hungarian/errmsg.txt: Added trigger related error messages. sql/share/italian/errmsg.txt: Added trigger related error messages. sql/share/japanese/errmsg.txt: Added trigger related error messages. sql/share/korean/errmsg.txt: Added trigger related error messages. sql/share/norwegian-ny/errmsg.txt: Added trigger related error messages. sql/share/norwegian/errmsg.txt: Added trigger related error messages. sql/share/polish/errmsg.txt: Added trigger related error messages. sql/share/portuguese/errmsg.txt: Added trigger related error messages. sql/share/romanian/errmsg.txt: Added trigger related error messages. sql/share/russian/errmsg.txt: Added trigger related error messages. sql/share/serbian/errmsg.txt: Added trigger related error messages. sql/share/slovak/errmsg.txt: Added trigger related error messages. sql/share/spanish/errmsg.txt: Added trigger related error messages. sql/share/swedish/errmsg.txt: Added trigger related error messages. sql/share/ukrainian/errmsg.txt: Added trigger related error messages. sql/sp_head.cc: sp_head::init_strings(): added support for triggers (we don't have most of strings for them) sp_head::execute_function(): triggers don't require RETURN sp_head::reset_lex(): added propagation of trigger properties to LEX used for parsing of statements composing trigger body. Added two more SP instructions: - sp_instr_set_user_var for setting user variables in stored functions and triggers (we can't use sp_instr_stmt and "SET @a:=..." statement since it will close open tables and thus break execution of calling statement. - sp_instr_set_trigger_field for assignment to fields of row being updated/inserted in triggers sql/sp_head.h: Added new type of sp_head object - TYPE_ENUM_TRIGGER Added two more SP instructions: - sp_instr_set_user_var for setting user variables in stored functions and triggers (we can't use sp_instr_stmt and "SET @a:=..." statement since it will close open tables and thus break execution of calling statement. - sp_instr_set_trigger_field for assignment to fields of row being updated/inserted in triggers sql/sql_base.cc: Now freeing memory occupied by trigger related structures when closing tables. open_unireg_entry(): added loading of triggers for table. find_field_in_real_table() is now public since it required by Item_trigger_field in item.cc sql/sql_delete.cc: Added triggers invocation for DELETE (should be fixed for sure :)) sql/sql_insert.cc: Added triggers invocation for INSERT (should be fixed for sure :)) sql/sql_lex.cc: Added trg_new_row_fake_var variable pointer to which is used for distinguishing between assignment to NEW row field (when parsing trigger definition) and structured variable. Added initialization of LEX->trg_table to lex_start(). (When triggers are parsed during opening of table it points to table object.) sql/sql_lex.h: Added trigger related commands. Added st_trg_chistics structure describing properties of trigger being created (as struct and as LEX member). Added trg_new_row_fake_var variable pointer to which is used for distinguishing between assignment to NEW row field (when parsing trigger definition) and structured variable. Added LEX::trg_table which points to table being opened when we are parsing trigger definition while opening table. sql/sql_parse.cc: Added support for CREATE/DROP TRIGGER commands. sql/sql_table.cc: Cleanup. close_cached_table() always returns 0 and its result is not analyzed in most places so chenged its return type to void. sql/sql_update.cc: Added triggers invocation for UPDATE (should be fixed for sure :)) sql/sql_yacc.yy: Added support for CREATE/DROP TRIGGER statements. Added support for OLD/NEW row identifiers in trigger. Made assignment to user variables not to break execution of stored function or trigger. sql/table.h: Added TABLE::triggers member representing triggers for this table.
This commit is contained in:
171
mysql-test/r/trigger.result
Normal file
171
mysql-test/r/trigger.result
Normal file
@ -0,0 +1,171 @@
|
||||
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 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;
|
Reference in New Issue
Block a user