diff options
author | gbichot@quadita2.mysql.com <> | 2005-05-06 18:52:19 +0200 |
---|---|---|
committer | gbichot@quadita2.mysql.com <> | 2005-05-06 18:52:19 +0200 |
commit | ea1bc59ed9e07cfd6047f0052f750b0f836f4e9b (patch) | |
tree | 4f486a352732a6b1f04e190b6cf3f4d62fc3a5df | |
parent | 5aa0edf34c4bf83eace609e2e60b448fcb9553fe (diff) | |
download | mariadb-git-ea1bc59ed9e07cfd6047f0052f750b0f836f4e9b.tar.gz |
Dmitri please review. Fix for BUG#10417 "CREATE TRIGGER not written to binlog":
writing DROP and CREATE TRIGGER to binlog, disabling binlogging
of substatements, testing.
-rw-r--r-- | mysql-test/r/rpl_sp.result | 35 | ||||
-rw-r--r-- | mysql-test/t/rpl_sp.test | 36 | ||||
-rw-r--r-- | sql/sql_trigger.cc | 26 | ||||
-rw-r--r-- | sql/sql_trigger.h | 8 |
4 files changed, 96 insertions, 9 deletions
diff --git a/mysql-test/r/rpl_sp.result b/mysql-test/r/rpl_sp.result index 6e5fccfe4e2..7b3249d553a 100644 --- a/mysql-test/r/rpl_sp.result +++ b/mysql-test/r/rpl_sp.result @@ -158,9 +158,6 @@ a select * from t2; a 3 -select if(compte<>3,"this is broken but documented","this unexpectedly works?") from (select count(*) as compte from t2) as aggreg; -if(compte<>3,"this is broken but documented","this unexpectedly works?") -this is broken but documented select * from mysql.proc where name="foo4" and db='mysqltest1'; db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment mysqltest1 foo4 PROCEDURE foo4 SQL CONTAINS_SQL YES INVOKER begin @@ -197,9 +194,6 @@ a select * from t1; a 21 -select if(compte<>1,"this is broken but documented","this unexpectedly works?") from (select count(*) as compte from t1 where a=20) as aggreg; -if(compte<>1,"this is broken but documented","this unexpectedly works?") -this is broken but documented select * from t2; a 23 @@ -230,6 +224,35 @@ db name type specific_name language sql_data_access is_deterministic security_ty mysqltest1 fn1 FUNCTION fn1 SQL CONTAINS_SQL YES DEFINER int(11) begin return unix_timestamp(); end @ # # +create trigger trg before insert on t1 for each row set new.a= 10; +ERROR 42000: Access denied; you need the SUPER privilege for this operation +flush logs; +delete from t1; +create trigger trg before insert on t1 for each row set new.a= 10; +insert into t1 values (1); +select * from t1; +a +10 +select * from t1; +a +10 +delete from t1; +drop trigger t1.trg; +insert into t1 values (1); +select * from t1; +a +1 +show binlog events in 'master-bin.000002' from 98; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000002 # Query 1 # use `mysqltest1`; delete from t1 +master-bin.000002 # Query 1 # use `mysqltest1`; create trigger trg before insert on t1 for each row set new.a= 10 +master-bin.000002 # Query 1 # use `mysqltest1`; insert into t1 values (1) +master-bin.000002 # Query 1 # use `mysqltest1`; delete from t1 +master-bin.000002 # Query 1 # use `mysqltest1`; drop trigger t1.trg +master-bin.000002 # Query 1 # use `mysqltest1`; insert into t1 values (1) +select * from t1; +a +1 drop function fn1; drop database mysqltest1; drop user "zedjzlcsjhd"@127.0.0.1; diff --git a/mysql-test/t/rpl_sp.test b/mysql-test/t/rpl_sp.test index b8dc381630b..e2a8982ebaa 100644 --- a/mysql-test/t/rpl_sp.test +++ b/mysql-test/t/rpl_sp.test @@ -157,7 +157,6 @@ select * from t2; sync_slave_with_master; select * from t1; select * from t2; -select if(compte<>3,"this is broken but documented","this unexpectedly works?") from (select count(*) as compte from t2) as aggreg; # Test of DROP PROCEDURE @@ -194,7 +193,6 @@ select * from t1; select * from t2; sync_slave_with_master; select * from t1; -select if(compte<>1,"this is broken but documented","this unexpectedly works?") from (select count(*) as compte from t1 where a=20) as aggreg; select * from t2; connection master; @@ -225,6 +223,40 @@ select * from t1; --replace_column 13 # 14 # select * from mysql.proc where db='mysqltest1'; +# And now triggers + +connection con1; +--error 1227; +create trigger trg before insert on t1 for each row set new.a= 10; + +connection master; +# fn1() above uses timestamps, so in !ps-protocol, the timezone will be +# binlogged, but in --ps-protocol it will not be (BUG#9359) so +# the binlog offsets get shifted which spoils SHOW BINLOG EVENTS. +# To be immune, we take a new binlog. +flush logs; +delete from t1; +# TODO: when triggers can contain an update, test that this update +# does not go into binlog. +# I'm not setting user vars in the trigger, because replication of user vars +# would take care of propagating the user var's value to slave, so even if +# the trigger was not executed on slave it would not be discovered. +create trigger trg before insert on t1 for each row set new.a= 10; +insert into t1 values (1); +select * from t1; +sync_slave_with_master; +select * from t1; + +connection master; +delete from t1; +drop trigger t1.trg; +insert into t1 values (1); +select * from t1; +--replace_column 2 # 5 # +show binlog events in 'master-bin.000002' from 98; +sync_slave_with_master; +select * from t1; + # Clean up connection master; diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 5b6f12eab52..ebf46a34896 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -98,6 +98,21 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) if (wait_if_global_read_lock(thd, 0, 0)) DBUG_RETURN(TRUE); + /* + There is no DETERMINISTIC clause for triggers, so can't check it. + But a trigger can in theory be used to do nasty things (if it supported + DROP for example) so we do the check for privileges. For now there is + already a stronger test above (see start of the function); but when this + stronger test will be removed, the test below will hold. + */ + if (!trust_routine_creators && mysql_bin_log.is_open() && + !(thd->master_access & SUPER_ACL)) + { + my_message(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER, + ER(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER), MYF(0)); + DBUG_RETURN(TRUE); + } + VOID(pthread_mutex_lock(&LOCK_open)); result= (create ? table->triggers->create_trigger(thd, tables): @@ -109,7 +124,16 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) start_waiting_global_read_lock(thd); if (!result) - send_ok(thd); + { + if (mysql_bin_log.is_open()) + { + thd->clear_error(); + /* Such a statement can always go directly to binlog, no trans cache */ + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + mysql_bin_log.write(&qinfo); + } + send_ok(thd); + } DBUG_RETURN(result); } diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index 7dd6734eb89..26cfb114cde 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -52,7 +52,15 @@ public: FIXME: We should juggle with security context here (because trigger should be invoked with creator rights). */ + /* + Guilhem puts code to disable binlogging, as in SP/functions, even + though currently triggers can't do updates. When triggers can do + updates, someone should add such a trigger to rpl_sp.test to verify + that the update does NOT go into binlog. + */ + tmp_disable_binlog(thd); res= bodies[event][time_type]->execute_function(thd, 0, 0, 0); + reenable_binlog(thd); #ifndef EMBEDDED_LIBRARY thd->net.no_send_ok= nsok; |