summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcbell/Chuck@mysql_cab_desk. <>2007-03-16 09:56:57 -0400
committercbell/Chuck@mysql_cab_desk. <>2007-03-16 09:56:57 -0400
commit3e44599c11e90c2b6470e64dbe6d78bc6c5f9f10 (patch)
tree15f703b3b46120a527b00e8e328eb91286163cec
parent2763e9af9addbaea0d55c6653c36ee59803979d8 (diff)
downloadmariadb-git-3e44599c11e90c2b6470e64dbe6d78bc6c5f9f10.tar.gz
WL#3629 - Replication of Invocation and Invoked Features
This changeset adds replication of events and user-defined functions. There are several bug reports involved in this change: BUG#16421, BUG#17857, BUG#20384: This patch modifies the mysql.events table to permit the addition of another enum value for the status column. The column now has values of ('DISABLED','SLAVESIDE_DISABLED','ENABLED'). A status of SLAVESIDE_DISABLED is set on the slave during replication of events. This enables users to determine which events werereplicated from the master and to later enable them if they promote the slave to a master. The CREATE, ALTER, and DROP statements are binlogged. A new test was added for replication of events (rpl_events). BUG#17671: This patch modifies the code to permit logging of user-defined functions. Note: this is the CREATE FUNCTION ... SONAME variety. A more friendly error message to be displayed should a replicated user-defined function not be found in the loadable library or if the library is missing from the slave.The CREATE andDROP statements are binlogged. A new test was added for replication of user-defined functions (rpl_udf). The patch also adds a new column to the mysql.event table named 'originator' that is used to store the server_id of the server that the event originated on. This enables users to promote a slave to a master and later return the promoted slave to a slave and disable the replicated events.
-rw-r--r--mysql-test/include/rpl_events.inc101
-rw-r--r--mysql-test/include/rpl_udf.inc187
-rw-r--r--mysql-test/lib/init_db.sql3
-rw-r--r--mysql-test/r/events.result29
-rw-r--r--mysql-test/r/events_grant.result24
-rw-r--r--mysql-test/r/events_restart_phase1.result4
-rw-r--r--mysql-test/r/rpl_events.result133
-rw-r--r--mysql-test/r/rpl_udf.result310
-rw-r--r--mysql-test/r/system_mysql_db.result3
-rw-r--r--mysql-test/t/events.test2
-rw-r--r--mysql-test/t/events_restart_phase1.test4
-rw-r--r--mysql-test/t/rpl_events.test24
-rw-r--r--mysql-test/t/rpl_udf.test22
-rw-r--r--scripts/mysql_create_system_tables.sh3
-rw-r--r--scripts/mysql_fix_privilege_tables.sql5
-rw-r--r--sql/event_data_objects.cc52
-rw-r--r--sql/event_data_objects.h53
-rw-r--r--sql/event_db_repository.cc13
-rw-r--r--sql/event_db_repository.h3
-rw-r--r--sql/event_queue.cc6
-rw-r--r--sql/events.cc49
-rw-r--r--sql/lex.h1
-rw-r--r--sql/slave.cc19
-rw-r--r--sql/sql_parse.cc1
-rw-r--r--sql/sql_show.cc31
-rw-r--r--sql/sql_udf.cc34
-rw-r--r--sql/sql_yacc.yy15
27 files changed, 1041 insertions, 90 deletions
diff --git a/mysql-test/include/rpl_events.inc b/mysql-test/include/rpl_events.inc
new file mode 100644
index 00000000000..5f4cc3c6985
--- /dev/null
+++ b/mysql-test/include/rpl_events.inc
@@ -0,0 +1,101 @@
+##################################################################
+# Author: Giuseppe, Chuck Bell #
+# Date: 17-January-2007 #
+# Purpose: To test that event effects are replicated #
+# in both row based and statement based format #
+##################################################################
+
+--disable_warnings
+DROP EVENT IF EXISTS justonce;
+drop table if exists t1,t2;
+--enable_warnings
+
+# first, we need a table to record something from an event
+
+eval CREATE TABLE `t1` (
+ `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `c` VARCHAR(50) NOT NULL,
+ `ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
+CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`)
+) ENGINE=$engine_type DEFAULT CHARSET=utf8;
+
+INSERT INTO t1 (c) VALUES ('manually');
+
+# then, we create the event
+CREATE EVENT justonce ON SCHEDULE AT NOW() + INTERVAL 2 SECOND DO INSERT INTo t1
+(c) VALUES ('from justonce');
+
+# wait 3 seconds, so the event can trigger
+--real_sleep 3
+
+# check that table t1 contains something
+--echo "in the master"
+--enable_info
+--replace_column 3 TIMESTAMP
+SELECT * FROM t1;
+--disable_info
+
+sync_slave_with_master;
+connection slave;
+
+--echo "in the slave"
+--enable_info
+--replace_column 3 TIMESTAMP
+SELECT * FROM t1;
+--disable_info
+
+# Create an event on the slave and check to see what the originator is.
+--disable_warnings
+DROP EVENT IF EXISTS test.slave_once;
+--enable_warnings
+
+CREATE EVENT test.slave_once ON SCHEDULE EVERY 5 MINUTE DO
+INSERT INTO t1(c) VALUES ('from slave_once');
+SELECT db, name, status, originator FROM mysql.event;
+
+--disable_warnings
+DROP EVENT IF EXISTS test.slave_once;
+--enable_warnings
+
+connection master;
+
+# BUG#20384 - disable events on slave
+DROP EVENT IF EXISTS test.justonce;
+CREATE EVENT test.er ON SCHEDULE EVERY 3 SECOND DO
+INSERT INTO t1(c) VALUES ('from er');
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'er';
+
+sync_slave_with_master;
+connection slave;
+--echo "in the slave"
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'er';
+
+connection master;
+--echo "in the master"
+ALTER EVENT test.er ON SCHEDULE EVERY 5 SECOND DO INSERT into t1(c) VALUES ('from alter er');
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'er';
+
+sync_slave_with_master;
+connection slave;
+--echo "in the slave"
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'er';
+
+connection master;
+--echo "in the master"
+DROP EVENT test.er;
+--replace column 8 DATETIME
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'er';
+
+--disable_info
+
+sync_slave_with_master;
+connection slave;
+--echo "in the slave"
+--replace column 8 DATETIME
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'er';
+
+--echo "in the master"
+connection master;
+DROP TABLE t1;
+
diff --git a/mysql-test/include/rpl_udf.inc b/mysql-test/include/rpl_udf.inc
new file mode 100644
index 00000000000..ef20327078e
--- /dev/null
+++ b/mysql-test/include/rpl_udf.inc
@@ -0,0 +1,187 @@
+#####################################################################
+# Author: Chuck Bell #
+# Date: 2006-12-21 #
+# Purpose: To test that UDFs are replicated in both row based and #
+# statement based format. This tests work completed in WL#3629. #
+# #
+# This test is designed to exercise two of the three types of UDFs: #
+# 1) UDFs via loadable libraries, and 2) UDFs with a SQL body. #
+#####################################################################
+
+--source include/have_udf.inc
+
+#
+# To run this tests the "sql/udf_example.c" need to be compiled into
+# udf_example.so and LD_LIBRARY_PATH should be setup to point out where
+# the library are.
+#
+
+connection master;
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+#
+# Test 1) Test UDFs via loadable libraries
+#
+--echo "*** Test 1) Test UDFs via loadable libraries ***
+--echo "Running on the master"
+--enable_info
+--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
+eval CREATE FUNCTION myfunc_double RETURNS REAL SONAME "$UDF_EXAMPLE_LIB";
+--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
+eval CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "$UDF_EXAMPLE_LIB";
+--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
+--error ER_CANT_FIND_DL_ENTRY
+eval CREATE FUNCTION myfunc_nonexist RETURNS INTEGER SONAME "$UDF_EXAMPLE_LIB";
+SELECT * FROM mysql.func;
+--disable_info
+
+save_master_pos;
+connection slave;
+sync_with_master;
+
+# Check to see that UDF CREATE statements were replicated
+--echo "Running on the slave"
+--enable_info
+SELECT * FROM mysql.func;
+--disable_info
+
+connection master;
+
+# Use the UDFs to do something
+--echo "Running on the master"
+--enable_info
+eval CREATE TABLE t1(sum INT, price FLOAT(24)) ENGINE=$engine_type;
+INSERT INTO t1 VALUES(myfunc_int(100), myfunc_double(50.00));
+INSERT INTO t1 VALUES(myfunc_int(10), myfunc_double(5.00));
+INSERT INTO t1 VALUES(myfunc_int(200), myfunc_double(25.00));
+INSERT INTO t1 VALUES(myfunc_int(1), myfunc_double(500.00));
+SELECT * FROM t1 ORDER BY sum;
+--disable_info
+
+sync_slave_with_master;
+
+# Check to see if data was replicated
+--echo "Running on the slave"
+--enable_info
+SELECT * FROM t1 ORDER BY sum;
+
+# Check to see that the functions are available for execution on the slave
+SELECT myfunc_int(25);
+SELECT myfunc_double(75.00);
+--disable_info
+
+connection master;
+
+# Drop the functions
+--echo "Running on the master"
+--enable_info
+DROP FUNCTION myfunc_double;
+DROP FUNCTION myfunc_int;
+SELECT * FROM mysql.func;
+--disable_info
+
+sync_slave_with_master;
+
+# Check to see if the UDFs were dropped on the slave
+--echo "Running on the slave"
+--enable_info
+SELECT * FROM mysql.func;
+--disable_info
+
+connection master;
+
+# Cleanup
+--echo "Running on the master"
+--enable_info
+DROP TABLE t1;
+--disable_info
+
+#
+# Test 2) Test UDFs with SQL body
+#
+--echo "*** Test 2) Test UDFs with SQL body ***
+--echo "Running on the master"
+--enable_info
+CREATE FUNCTION myfuncsql_int(i INT) RETURNS INTEGER DETERMINISTIC RETURN i;
+CREATE FUNCTION myfuncsql_double(d DOUBLE) RETURNS INTEGER DETERMINISTIC RETURN d * 0.95;
+SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%';
+--disable_info
+
+sync_slave_with_master;
+
+# Check to see that UDF CREATE statements were replicated
+--echo "Running on the slave"
+--enable_info
+SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%';
+--disable_info
+
+connection master;
+
+# Use the UDFs to do something
+--echo "Running on the master"
+--enable_info
+eval CREATE TABLE t1(sum INT, price FLOAT(24)) ENGINE=$engine_type;
+INSERT INTO t1 VALUES(myfuncsql_int(100), myfuncsql_double(50.00));
+INSERT INTO t1 VALUES(myfuncsql_int(10), myfuncsql_double(5.00));
+INSERT INTO t1 VALUES(myfuncsql_int(200), myfuncsql_double(25.00));
+INSERT INTO t1 VALUES(myfuncsql_int(1), myfuncsql_double(500.00));
+SELECT * FROM t1 ORDER BY sum;
+--disable_info
+
+sync_slave_with_master;
+
+# Check to see if data was replicated
+--echo "Running on the slave"
+--enable_info
+SELECT * FROM t1 ORDER BY sum;
+--disable_info
+
+connection master;
+
+# Modify the UDFs to add a comment
+--echo "Running on the master"
+--enable_info
+ALTER FUNCTION myfuncsql_int COMMENT "This was altered.";
+ALTER FUNCTION myfuncsql_double COMMENT "This was altered.";
+SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%';
+--disable_info
+
+sync_slave_with_master;
+
+# Check to see if data was replicated
+--echo "Running on the slave"
+--enable_info
+SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%';
+
+# Check to see that the functions are available for execution on the slave
+SELECT myfuncsql_int(25);
+SELECT myfuncsql_double(75.00);
+--disable_info
+
+connection master;
+
+# Drop the functions
+--echo "Running on the master"
+--enable_info
+DROP FUNCTION myfuncsql_double;
+DROP FUNCTION myfuncsql_int;
+SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%';
+--disable_info
+
+sync_slave_with_master;
+
+# Check to see if the UDFs were dropped on the slave
+--echo "Running on the slave"
+--enable_info
+SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%';
+--disable_info
+
+connection master;
+
+# Cleanup
+--echo "Running on the master"
+--enable_info
+DROP TABLE t1;
+--disable_info
diff --git a/mysql-test/lib/init_db.sql b/mysql-test/lib/init_db.sql
index c6c0f1d81dd..14ff2603a84 100644
--- a/mysql-test/lib/init_db.sql
+++ b/mysql-test/lib/init_db.sql
@@ -610,7 +610,7 @@ CREATE TABLE event (
last_executed DATETIME default NULL,
starts DATETIME default NULL,
ends DATETIME default NULL,
- status ENUM('ENABLED','DISABLED') NOT NULL default 'ENABLED',
+ status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED',
on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP',
sql_mode set(
'REAL_AS_FLOAT',
@@ -645,6 +645,7 @@ CREATE TABLE event (
'HIGH_NOT_PRECEDENCE'
) DEFAULT '' NOT NULL,
comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
+ originator int(10) NOT NULL,
PRIMARY KEY (db, name)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
diff --git a/mysql-test/r/events.result b/mysql-test/r/events.result
index af864c57efa..3193f45d554 100644
--- a/mysql-test/r/events.result
+++ b/mysql-test/r/events.result
@@ -193,7 +193,7 @@ create event руут21 on schedule every '50:23:59:95' day_second COMMENT 'това е 1
SHOW CREATE EVENT руут21;
Event sql_mode Create Event
руут21 CREATE EVENT `руут21` ON SCHEDULE EVERY '51 0:0:35' DAY_SECOND ON COMPLETION NOT PRESERVE ENABLE COMMENT 'това е 1251 коментар' DO select 1
-insert into mysql.event (db, name, body, definer, interval_value, interval_field) values (database(), "root22", "select 1", user(), 100, "SECOND_MICROSECOND");
+insert into mysql.event (db, name, body, definer, interval_value, interval_field, originator) values (database(), "root22", "select 1", user(), 100, "SECOND_MICROSECOND", 1);
show create event root22;
ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
SHOW EVENTS;
@@ -225,18 +225,18 @@ drop event руут21;
set names latin1;
CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing";
SHOW EVENTS;
-Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
-events_test intact_check root@localhost RECURRING NULL 10 HOUR # # ENABLED
+Db Name Definer Type Execute at Interval value Interval field Starts Ends Status Originator
+events_test intact_check root@localhost RECURRING NULL 10 HOUR # # ENABLED 1
ALTER TABLE mysql.event ADD dummy INT FIRST;
SHOW EVENTS;
-ERROR HY000: Column count of mysql.event is wrong. Expected 16, found 17. Table probably corrupted
+ERROR HY000: Column count of mysql.event is wrong. Expected 17, found 18. Table probably corrupted
ALTER TABLE mysql.event DROP dummy, ADD dummy2 VARCHAR(64) FIRST;
SHOW EVENTS;
-ERROR HY000: Column count of mysql.event is wrong. Expected 16, found 17. Table probably corrupted
+ERROR HY000: Column count of mysql.event is wrong. Expected 17, found 18. Table probably corrupted
ALTER TABLE mysql.event DROP dummy2;
SHOW EVENTS;
-Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
-events_test intact_check root@localhost RECURRING NULL 10 HOUR # # ENABLED
+Db Name Definer Type Execute at Interval value Interval field Starts Ends Status Originator
+events_test intact_check root@localhost RECURRING NULL 10 HOUR # # ENABLED 1
CREATE TABLE event_like LIKE mysql.event;
INSERT INTO event_like SELECT * FROM mysql.event;
ALTER TABLE mysql.event MODIFY db char(64) character set cp1251 default '';
@@ -258,10 +258,11 @@ event CREATE TABLE `event` (
`last_executed` datetime DEFAULT NULL,
`starts` datetime DEFAULT NULL,
`ends` datetime DEFAULT NULL,
- `status` enum('ENABLED','DISABLED') NOT NULL DEFAULT 'ENABLED',
+ `status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED',
`on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP',
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE') NOT NULL DEFAULT '',
`comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
+ `originator` int(10) NOT NULL,
PRIMARY KEY (`db`,`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events'
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
@@ -269,8 +270,8 @@ ERROR HY000: Cannot load from mysql.event. Table probably corrupted. See error l
ALTER TABLE mysql.event MODIFY db char(64) character set utf8 collate utf8_bin default '';
"This should work"
SHOW EVENTS;
-Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
-events_test intact_check root@localhost RECURRING NULL 10 HOUR # # ENABLED
+Db Name Definer Type Execute at Interval value Interval field Starts Ends Status Originator
+events_test intact_check root@localhost RECURRING NULL 10 HOUR # # ENABLED 1
ALTER TABLE mysql.event MODIFY db char(64) character set cp1251 default '';
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
ERROR HY000: Cannot load from mysql.event. Table probably corrupted. See error log.
@@ -279,14 +280,14 @@ SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
ERROR HY000: Cannot load from mysql.event. Table probably corrupted. See error log.
ALTER TABLE mysql.event DROP comment, DROP starts;
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
-ERROR HY000: Column count of mysql.event is wrong. Expected 16, found 14. Table probably corrupted
+ERROR HY000: Column count of mysql.event is wrong. Expected 17, found 15. Table probably corrupted
DROP TABLE mysql.event;
CREATE TABLE mysql.event like event_like;
INSERT INTO mysql.event SELECT * FROM event_like;
DROP TABLE event_like;
SHOW EVENTS;
-Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
-events_test intact_check root@localhost RECURRING NULL 10 HOUR # # ENABLED
+Db Name Definer Type Execute at Interval value Interval field Starts Ends Status Originator
+events_test intact_check root@localhost RECURRING NULL 10 HOUR # # ENABLED 1
DROP EVENT intact_check;
create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5;
select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event;
@@ -399,5 +400,5 @@ ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
SHOW EVENTS FROM ``;
ERROR 42000: Incorrect database name ''
SHOW EVENTS FROM `events\\test`;
-Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
+Db Name Definer Type Execute at Interval value Interval field Starts Ends Status Originator
drop database events_test;
diff --git a/mysql-test/r/events_grant.result b/mysql-test/r/events_grant.result
index a28c30a9345..87906216e40 100644
--- a/mysql-test/r/events_grant.result
+++ b/mysql-test/r/events_grant.result
@@ -2,8 +2,8 @@ CREATE DATABASE IF NOT EXISTS events_test;
use events_test;
CREATE EVENT one_event ON SCHEDULE EVERY 10 SECOND DO SELECT 123;
SHOW EVENTS;
-Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
-events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED
+Db Name Definer Type Execute at Interval value Interval field Starts Ends Status Originator
+events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED 1
SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS ORDER BY EVENT_SCHEMA, EVENT_NAME;
EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT
NULL events_test one_event root@localhost SQL SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE
@@ -29,8 +29,8 @@ ERROR 42000: Access denied for user 'ev_test'@'localhost' to database 'events_te
USE events_test;
"We should see one event";
SHOW EVENTS;
-Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
-events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED
+Db Name Definer Type Execute at Interval value Interval field Starts Ends Status Originator
+events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED 1
SELECT CONCAT("Let's create some new events from the name of ", USER());
CONCAT("Let's create some new events from the name of ", USER())
Let's create some new events from the name of ev_test@localhost
@@ -40,18 +40,18 @@ CREATE EVENT two_event ON SCHEDULE EVERY 20 SECOND ON COMPLETION NOT PRESERVE CO
CREATE EVENT three_event ON SCHEDULE EVERY 20 SECOND ON COMPLETION PRESERVE COMMENT "three event" DO SELECT 123;
"Now we should see 3 events:";
SHOW EVENTS;
-Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
-events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED
-events_test three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
-events_test two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
+Db Name Definer Type Execute at Interval value Interval field Starts Ends Status Originator
+events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED 1
+events_test three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED 1
+events_test two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED 1
"This should show us only 2 events:";
SHOW EVENTS LIKE 't%event';
-Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
-events_test three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
-events_test two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
+Db Name Definer Type Execute at Interval value Interval field Starts Ends Status Originator
+events_test three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED 1
+events_test two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED 1
"This should show us no events:";
SHOW EVENTS FROM test LIKE '%';
-Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
+Db Name Definer Type Execute at Interval value Interval field Starts Ends Status Originator
GRANT EVENT ON events_test2.* TO ev_test@localhost;
USE events_test2;
CREATE EVENT four_event ON SCHEDULE EVERY 20 SECOND DO SELECT 42;
diff --git a/mysql-test/r/events_restart_phase1.result b/mysql-test/r/events_restart_phase1.result
index a7a46fa0ab1..2b0f4141c7c 100644
--- a/mysql-test/r/events_restart_phase1.result
+++ b/mysql-test/r/events_restart_phase1.result
@@ -7,6 +7,6 @@ create event abc2 on schedule every 1 second do insert into execution_log value(
create event abc3 on schedule every 1 second do insert into execution_log value('abc3');
select name from execution_log;
name
-insert into mysql.event values ('db1','bad','select 42','root@localhost',NULL,1000,'MICROSECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment1');
-insert into mysql.event values ('db1','bad2','sect','root@localhost',NULL,1000,'SECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment2');
+insert into mysql.event values ('db1','bad','select 42','root@localhost',NULL,1000,'MICROSECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment1',1);
+insert into mysql.event values ('db1','bad2','sect','root@localhost',NULL,1000,'SECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment2',1);
"Now we restart the server"
diff --git a/mysql-test/r/rpl_events.result b/mysql-test/r/rpl_events.result
new file mode 100644
index 00000000000..59bd16adbf6
--- /dev/null
+++ b/mysql-test/r/rpl_events.result
@@ -0,0 +1,133 @@
+set global event_scheduler=1;
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+set binlog_format=row;
+DROP EVENT IF EXISTS justonce;
+drop table if exists t1,t2;
+CREATE TABLE `t1` (
+`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+`c` VARCHAR(50) NOT NULL,
+`ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
+CURRENT_TIMESTAMP,
+PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+INSERT INTO t1 (c) VALUES ('manually');
+CREATE EVENT justonce ON SCHEDULE AT NOW() + INTERVAL 2 SECOND DO INSERT INTo t1
+(c) VALUES ('from justonce');
+"in the master"
+SELECT * FROM t1;
+id c ts
+1 manually TIMESTAMP
+2 from justonce TIMESTAMP
+affected rows: 2
+"in the slave"
+SELECT * FROM t1;
+id c ts
+1 manually TIMESTAMP
+2 from justonce TIMESTAMP
+affected rows: 2
+DROP EVENT IF EXISTS test.slave_once;
+CREATE EVENT test.slave_once ON SCHEDULE EVERY 5 MINUTE DO
+INSERT INTO t1(c) VALUES ('from slave_once');
+SELECT db, name, status, originator FROM mysql.event;
+db name status originator
+test justonce SLAVESIDE_DISABLED 1
+test slave_once ENABLED 2
+DROP EVENT IF EXISTS test.slave_once;
+DROP EVENT IF EXISTS test.justonce;
+Warnings:
+Note 1305 Event justonce does not exist
+CREATE EVENT test.er ON SCHEDULE EVERY 3 SECOND DO
+INSERT INTO t1(c) VALUES ('from er');
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'er';
+db name status originator
+test er ENABLED 1
+"in the slave"
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'er';
+db name status originator
+test er SLAVESIDE_DISABLED 1
+"in the master"
+ALTER EVENT test.er ON SCHEDULE EVERY 5 SECOND DO INSERT into t1(c) VALUES ('from alter er');
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'er';
+db name status originator
+test er ENABLED 1
+"in the slave"
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'er';
+db name status originator
+test er SLAVESIDE_DISABLED 1
+"in the master"
+DROP EVENT test.er;
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'er';
+db name status originator
+"in the slave"
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'er';
+db name status originator
+"in the master"
+DROP TABLE t1;
+set binlog_format=statement;
+DROP EVENT IF EXISTS justonce;
+drop table if exists t1,t2;
+CREATE TABLE `t1` (
+`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+`c` VARCHAR(50) NOT NULL,
+`ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
+CURRENT_TIMESTAMP,
+PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+INSERT INTO t1 (c) VALUES ('manually');
+CREATE EVENT justonce ON SCHEDULE AT NOW() + INTERVAL 2 SECOND DO INSERT INTo t1
+(c) VALUES ('from justonce');
+"in the master"
+SELECT * FROM t1;
+id c ts
+1 manually TIMESTAMP
+2 from justonce TIMESTAMP
+affected rows: 2
+"in the slave"
+SELECT * FROM t1;
+id c ts
+1 manually TIMESTAMP
+2 from justonce TIMESTAMP
+affected rows: 2
+DROP EVENT IF EXISTS test.slave_once;
+CREATE EVENT test.slave_once ON SCHEDULE EVERY 5 MINUTE DO
+INSERT INTO t1(c) VALUES ('from slave_once');
+SELECT db, name, status, originator FROM mysql.event;
+db name status originator
+test justonce SLAVESIDE_DISABLED 1
+test slave_once ENABLED 2
+DROP EVENT IF EXISTS test.slave_once;
+DROP EVENT IF EXISTS test.justonce;
+Warnings:
+Note 1305 Event justonce does not exist
+CREATE EVENT test.er ON SCHEDULE EVERY 3 SECOND DO
+INSERT INTO t1(c) VALUES ('from er');
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'er';
+db name status originator
+test er ENABLED 1
+"in the slave"
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'er';
+db name status originator
+test er SLAVESIDE_DISABLED 1
+"in the master"
+ALTER EVENT test.er ON SCHEDULE EVERY 5 SECOND DO INSERT into t1(c) VALUES ('from alter er');
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'er';
+db name status originator
+test er ENABLED 1
+"in the slave"
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'er';
+db name status originator
+test er SLAVESIDE_DISABLED 1
+"in the master"
+DROP EVENT test.er;
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'er';
+db name status originator
+"in the slave"
+SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'er';
+db name status originator
+"in the master"
+DROP TABLE t1;
diff --git a/mysql-test/r/rpl_udf.result b/mysql-test/r/rpl_udf.result
new file mode 100644
index 00000000000..156876d07de
--- /dev/null
+++ b/mysql-test/r/rpl_udf.result
@@ -0,0 +1,310 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+set binlog_format=row;
+drop table if exists t1;
+"*** Test 1) Test UDFs via loadable libraries ***
+"Running on the master"
+CREATE FUNCTION myfunc_double RETURNS REAL SONAME "UDF_EXAMPLE_LIB";
+affected rows: 0
+CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB";
+affected rows: 0
+CREATE FUNCTION myfunc_nonexist RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB";
+ERROR HY000: Can't find symbol 'myfunc_nonexist' in library
+SELECT * FROM mysql.func;
+name ret dl type
+myfunc_double 1 udf_example.dll function
+myfunc_int 2 udf_example.dll function
+affected rows: 2
+"Running on the slave"
+SELECT * FROM mysql.func;
+name ret dl type
+myfunc_double 1 udf_example.dll function
+myfunc_int 2 udf_example.dll function
+affected rows: 2
+"Running on the master"
+CREATE TABLE t1(sum INT, price FLOAT(24)) ENGINE=MyISAM;
+affected rows: 0
+INSERT INTO t1 VALUES(myfunc_int(100), myfunc_double(50.00));
+affected rows: 1
+INSERT INTO t1 VALUES(myfunc_int(10), myfunc_double(5.00));
+affected rows: 1
+INSERT INTO t1 VALUES(myfunc_int(200), myfunc_double(25.00));
+affected rows: 1
+INSERT INTO t1 VALUES(myfunc_int(1), myfunc_double(500.00));
+affected rows: 1
+SELECT * FROM t1 ORDER BY sum;
+sum price
+1 48.5
+10 48.75
+100 48.6
+200 49
+affected rows: 4
+"Running on the slave"
+SELECT * FROM t1 ORDER BY sum;
+sum price
+1 48.5
+10 48.75
+100 48.6
+200 49
+affected rows: 4
+SELECT myfunc_int(25);
+myfunc_int(25)
+25
+affected rows: 1
+SELECT myfunc_double(75.00);
+myfunc_double(75.00)
+50.00
+affected rows: 1
+"Running on the master"
+DROP FUNCTION myfunc_double;
+affected rows: 0
+DROP FUNCTION myfunc_int;
+affected rows: 0
+SELECT * FROM mysql.func;
+name ret dl type
+affected rows: 0
+"Running on the slave"
+SELECT * FROM mysql.func;
+name ret dl type
+affected rows: 0
+"Running on the master"
+DROP TABLE t1;
+affected rows: 0
+"*** Test 2) Test UDFs with SQL body ***
+"Running on the master"
+CREATE FUNCTION myfuncsql_int(i INT) RETURNS INTEGER DETERMINISTIC RETURN i;
+affected rows: 0
+CREATE FUNCTION myfuncsql_double(d DOUBLE) RETURNS INTEGER DETERMINISTIC RETURN d * 0.95;
+affected rows: 0
+SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%';
+db name type param_list body comment
+test myfuncsql_double FUNCTION d DOUBLE RETURN d * 0.95
+test myfuncsql_int FUNCTION i INT RETURN i
+affected rows: 2
+"Running on the slave"
+SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%';
+db name type param_list body comment
+test myfuncsql_double FUNCTION d DOUBLE RETURN d * 0.95
+test myfuncsql_int FUNCTION i INT RETURN i
+affected rows: 2
+"Running on the master"
+CREATE TABLE t1(sum INT, price FLOAT(24)) ENGINE=MyISAM;
+affected rows: 0
+INSERT INTO t1 VALUES(myfuncsql_int(100), myfuncsql_double(50.00));
+affected rows: 1
+INSERT INTO t1 VALUES(myfuncsql_int(10), myfuncsql_double(5.00));
+affected rows: 1
+INSERT INTO t1 VALUES(myfuncsql_int(200), myfuncsql_double(25.00));
+affected rows: 1
+INSERT INTO t1 VALUES(myfuncsql_int(1), myfuncsql_double(500.00));
+affected rows: 1
+SELECT * FROM t1 ORDER BY sum;
+sum price
+1 475
+10 5
+100 47
+200 24
+affected rows: 4
+"Running on the slave"
+SELECT * FROM t1 ORDER BY sum;
+sum price
+1 475
+10 5
+100 47
+200 24
+affected rows: 4
+"Running on the master"
+ALTER FUNCTION myfuncsql_int COMMENT "This was altered.";
+affected rows: 0
+ALTER FUNCTION myfuncsql_double COMMENT "This was altered.";
+affected rows: 0
+SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%';
+db name type param_list body comment
+test myfuncsql_double FUNCTION d DOUBLE RETURN d * 0.95 This was altered.
+test myfuncsql_int FUNCTION i INT RETURN i This was altered.
+affected rows: 2
+"Running on the slave"
+SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%';
+db name type param_list body comment
+test myfuncsql_double FUNCTION d DOUBLE RETURN d * 0.95 This was altered.
+test myfuncsql_int FUNCTION i INT RETURN i This was altered.
+affected rows: 2
+SELECT myfuncsql_int(25);
+myfuncsql_int(25)
+25
+affected rows: 1
+SELECT myfuncsql_double(75.00);
+myfuncsql_double(75.00)
+71
+affected rows: 1
+"Running on the master"
+DROP FUNCTION myfuncsql_double;
+affected rows: 0
+DROP FUNCTION myfuncsql_int;
+affected rows: 0
+SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%';
+db name type param_list body comment
+affected rows: 0
+"Running on the slave"
+SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%';
+db name type param_list body comment
+affected rows: 0
+"Running on the master"
+DROP TABLE t1;
+affected rows: 0
+set binlog_format=statement;
+drop table if exists t1;
+"*** Test 1) Test UDFs via loadable libraries ***
+"Running on the master"
+CREATE FUNCTION myfunc_double RETURNS REAL SONAME "UDF_EXAMPLE_LIB";
+affected rows: 0
+CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB";
+affected rows: 0
+CREATE FUNCTION myfunc_nonexist RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB";
+ERROR HY000: Can't find symbol 'myfunc_nonexist' in library
+SELECT * FROM mysql.func;
+name ret dl type
+myfunc_int 2 udf_example.dll function
+myfunc_double 1 udf_example.dll function
+affected rows: 2
+"Running on the slave"
+SELECT * FROM mysql.func;
+name ret dl type
+myfunc_int 2 udf_example.dll function
+myfunc_double 1 udf_example.dll function
+affected rows: 2
+"Running on the master"
+CREATE TABLE t1(sum INT, price FLOAT(24)) ENGINE=MyISAM;
+affected rows: 0
+INSERT INTO t1 VALUES(myfunc_int(100), myfunc_double(50.00));
+affected rows: 1
+INSERT INTO t1 VALUES(myfunc_int(10), myfunc_double(5.00));
+affected rows: 1
+INSERT INTO t1 VALUES(myfunc_int(200), myfunc_double(25.00));
+affected rows: 1
+INSERT INTO t1 VALUES(myfunc_int(1), myfunc_double(500.00));
+affected rows: 1
+SELECT * FROM t1 ORDER BY sum;
+sum price
+1 48.5
+10 48.75
+100 48.6
+200 49
+affected rows: 4
+"Running on the slave"
+SELECT * FROM t1 ORDER BY sum;
+sum price
+1 48.5
+10 48.75
+100 48.6
+200 49
+affected rows: 4
+SELECT myfunc_int(25);
+myfunc_int(25)
+25
+affected rows: 1
+SELECT myfunc_double(75.00);
+myfunc_double(75.00)
+50.00
+affected rows: 1
+"Running on the master"
+DROP FUNCTION myfunc_double;
+affected rows: 0
+DROP FUNCTION myfunc_int;
+affected rows: 0
+SELECT * FROM mysql.func;
+name ret dl type
+affected rows: 0
+"Running on the slave"
+SELECT * FROM mysql.func;
+name ret dl type
+affected rows: 0
+"Running on the master"
+DROP TABLE t1;
+affected rows: 0
+"*** Test 2) Test UDFs with SQL body ***
+"Running on the master"
+CREATE FUNCTION myfuncsql_int(i INT) RETURNS INTEGER DETERMINISTIC RETURN i;
+affected rows: 0
+CREATE FUNCTION myfuncsql_double(d DOUBLE) RETURNS INTEGER DETERMINISTIC RETURN d * 0.95;
+affected rows: 0
+SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%';
+db name type param_list body comment
+test myfuncsql_double FUNCTION d DOUBLE RETURN d * 0.95
+test myfuncsql_int FUNCTION i INT RETURN i
+affected rows: 2
+"Running on the slave"
+SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%';
+db name type param_list body comment
+test myfuncsql_double FUNCTION d DOUBLE RETURN d * 0.95
+test myfuncsql_int FUNCTION i INT RETURN i
+affected rows: 2
+"Running on the master"
+CREATE TABLE t1(sum INT, price FLOAT(24)) ENGINE=MyISAM;
+affected rows: 0
+INSERT INTO t1 VALUES(myfuncsql_int(100), myfuncsql_double(50.00));
+affected rows: 1
+INSERT INTO t1 VALUES(myfuncsql_int(10), myfuncsql_double(5.00));
+affected rows: 1
+INSERT INTO t1 VALUES(myfuncsql_int(200), myfuncsql_double(25.00));
+affected rows: 1
+INSERT INTO t1 VALUES(myfuncsql_int(1), myfuncsql_double(500.00));
+affected rows: 1
+SELECT * FROM t1 ORDER BY sum;
+sum price
+1 475
+10 5
+100 47
+200 24
+affected rows: 4
+"Running on the slave"
+SELECT * FROM t1 ORDER BY sum;
+sum price
+1 475
+10 5
+100 47
+200 24
+affected rows: 4
+"Running on the master"
+ALTER FUNCTION myfuncsql_int COMMENT "This was altered.";
+affected rows: 0
+ALTER FUNCTION myfuncsql_double COMMENT "This was altered.";
+affected rows: 0
+SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%';
+db name type param_list body comment
+test myfuncsql_double FUNCTION d DOUBLE RETURN d * 0.95 This was altered.
+test myfuncsql_int FUNCTION i INT RETURN i This was altered.
+affected rows: 2
+"Running on the slave"
+SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%';
+db name type param_list body comment
+test myfuncsql_double FUNCTION d DOUBLE RETURN d * 0.95 This was altered.
+test myfuncsql_int FUNCTION i INT RETURN i This was altered.
+affected rows: 2
+SELECT myfuncsql_int(25);
+myfuncsql_int(25)
+25
+affected rows: 1
+SELECT myfuncsql_double(75.00);
+myfuncsql_double(75.00)
+71
+affected rows: 1
+"Running on the master"
+DROP FUNCTION myfuncsql_double;
+affected rows: 0
+DROP FUNCTION myfuncsql_int;
+affected rows: 0
+SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%';
+db name type param_list body comment
+affected rows: 0
+"Running on the slave"
+SELECT db, name, type, param_list, body, comment FROM mysql.proc WHERE db = 'test' AND name LIKE 'myfuncsql%';
+db name type param_list body comment
+affected rows: 0
+"Running on the master"
+DROP TABLE t1;
+affected rows: 0
diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result
index c93fbfba6e2..a8ea6ffa19f 100644
--- a/mysql-test/r/system_mysql_db.result
+++ b/mysql-test/r/system_mysql_db.result
@@ -220,10 +220,11 @@ event CREATE TABLE `event` (
`last_executed` datetime DEFAULT NULL,
`starts` datetime DEFAULT NULL,
`ends` datetime DEFAULT NULL,
- `status` enum('ENABLED','DISABLED') NOT NULL DEFAULT 'ENABLED',
+ `status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED',
`on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP',
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE') NOT NULL DEFAULT '',
`comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
+ `originator` int(10) NOT NULL,
PRIMARY KEY (`db`,`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events'
show create table general_log;
diff --git a/mysql-test/t/events.test b/mysql-test/t/events.test
index 6eb514fc13c..d2444bbea68 100644
--- a/mysql-test/t/events.test
+++ b/mysql-test/t/events.test
@@ -160,7 +160,7 @@ SHOW CREATE EVENT root20;
set names cp1251;
create event руут21 on schedule every '50:23:59:95' day_second COMMENT 'това е 1251 коментар' do select 1;
SHOW CREATE EVENT руут21;
-insert into mysql.event (db, name, body, definer, interval_value, interval_field) values (database(), "root22", "select 1", user(), 100, "SECOND_MICROSECOND");
+insert into mysql.event (db, name, body, definer, interval_value, interval_field, originator) values (database(), "root22", "select 1", user(), 100, "SECOND_MICROSECOND", 1);
--error ER_NOT_SUPPORTED_YET
show create event root22;
--error ER_NOT_SUPPORTED_YET
diff --git a/mysql-test/t/events_restart_phase1.test b/mysql-test/t/events_restart_phase1.test
index 92783ddaef7..ce9b77d4ff0 100644
--- a/mysql-test/t/events_restart_phase1.test
+++ b/mysql-test/t/events_restart_phase1.test
@@ -14,6 +14,6 @@ create event abc3 on schedule every 1 second do insert into execution_log value(
--sleep 1.5
select name from execution_log;
-insert into mysql.event values ('db1','bad','select 42','root@localhost',NULL,1000,'MICROSECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment1');
-insert into mysql.event values ('db1','bad2','sect','root@localhost',NULL,1000,'SECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment2');
+insert into mysql.event values ('db1','bad','select 42','root@localhost',NULL,1000,'MICROSECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment1',1);
+insert into mysql.event values ('db1','bad2','sect','root@localhost',NULL,1000,'SECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment2',1);
--echo "Now we restart the server"
diff --git a/mysql-test/t/rpl_events.test b/mysql-test/t/rpl_events.test
new file mode 100644
index 00000000000..895e94c438b
--- /dev/null
+++ b/mysql-test/t/rpl_events.test
@@ -0,0 +1,24 @@
+##################################################################
+# Author: Giuseppe #
+# Date: 2006-12-20 #
+# Purpose: To test that event effects are replicated #
+# in both row based and statement based format #
+##################################################################
+
+set global event_scheduler=1;
+
+--source include/not_embedded.inc
+--source include/master-slave.inc
+
+let $engine_type= MyISAM;
+
+set binlog_format=row;
+
+# Embedded server doesn't support binlogging
+--source include/rpl_events.inc
+
+set binlog_format=statement;
+
+# Embedded server doesn't support binlogging
+--source include/rpl_events.inc
+
diff --git a/mysql-test/t/rpl_udf.test b/mysql-test/t/rpl_udf.test
new file mode 100644
index 00000000000..262ad04630c
--- /dev/null
+++ b/mysql-test/t/rpl_udf.test
@@ -0,0 +1,22 @@
+###################################################################
+# Author: Chuck Bell #
+# Date: 2006-12-21 #
+# Purpose: To test that UDFs are replicated in both row based and #
+# statement based format. This tests work completed in WL#3629. #
+###################################################################
+
+--source include/not_embedded.inc
+--source include/master-slave.inc
+
+let $engine_type= MyISAM;
+
+set binlog_format=row;
+
+# Embedded server doesn't support binlogging
+--source include/rpl_udf.inc
+
+set binlog_format=statement;
+
+# Embedded server doesn't support binlogging
+--source include/rpl_udf.inc
+
diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh
index cc86def1a5c..ddb90b55633 100644
--- a/scripts/mysql_create_system_tables.sh
+++ b/scripts/mysql_create_system_tables.sh
@@ -832,7 +832,7 @@ then
c_ev="$c_ev last_executed DATETIME default NULL,"
c_ev="$c_ev starts DATETIME default NULL,"
c_ev="$c_ev ends DATETIME default NULL,"
- c_ev="$c_ev status ENUM('ENABLED','DISABLED') NOT NULL default 'ENABLED',"
+ c_ev="$c_ev status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED',"
c_ev="$c_ev on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP',"
c_ev="$c_ev sql_mode set("
c_ev="$c_ev 'REAL_AS_FLOAT',"
@@ -867,6 +867,7 @@ then
c_ev="$c_ev 'HIGH_NOT_PRECEDENCE'"
c_ev="$c_ev ) DEFAULT '' NOT NULL,"
c_ev="$c_ev comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',"
+ c_ev="$c_ev originator int(10) NOT NULL,
c_ev="$c_ev PRIMARY KEY (db, name)"
c_ev="$c_ev ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';"
fi
diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql
index 9cdea507493..4d661dd8146 100644
--- a/scripts/mysql_fix_privilege_tables.sql
+++ b/scripts/mysql_fix_privilege_tables.sql
@@ -648,7 +648,7 @@ CREATE TABLE event (
last_executed DATETIME default NULL,
starts DATETIME default NULL,
ends DATETIME default NULL,
- status ENUM('ENABLED','DISABLED') NOT NULL default 'ENABLED',
+ status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED',
on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP',
sql_mode set(
'REAL_AS_FLOAT',
@@ -683,6 +683,7 @@ CREATE TABLE event (
'HIGH_NOT_PRECEDENCE'
) DEFAULT '' NOT NULL,
comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
+ originator int(10) NOT NULL,
PRIMARY KEY (db,name)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
@@ -737,6 +738,8 @@ ALTER TABLE event ADD sql_mode
UPDATE user SET Event_priv=Super_priv WHERE @hadEventPriv = 0;
ALTER TABLE event MODIFY name char(64) CHARACTER SET utf8 NOT NULL default '';
+ALTER TABLE event ADD COLUMN originator INT(10) NOT NULL;
+ALTER TABLE event MODIFY COLUMN status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED';
#
# TRIGGER privilege
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc
index 07575a6d33a..4c3524f47ac 100644
--- a/sql/event_data_objects.cc
+++ b/sql/event_data_objects.cc
@@ -58,7 +58,8 @@ Event_parse_data::new_instance(THD *thd)
*/
Event_parse_data::Event_parse_data()
- :on_completion(ON_COMPLETION_DROP), status(ENABLED),
+ :on_completion(Event_basic::ON_COMPLETION_DROP),
+ status(Event_basic::ENABLED),
item_starts(NULL), item_ends(NULL), item_execute_at(NULL),
starts_null(TRUE), ends_null(TRUE), execute_at_null(TRUE),
item_expression(NULL), expression(0)
@@ -550,9 +551,9 @@ Event_parse_data::check_parse_data(THD *thd)
init_name(thd, identifier);
init_definer(thd);
-
ret= init_execute_at(thd) || init_interval(thd) || init_starts(thd) ||
init_ends(thd);
+ check_originator_id(thd);
DBUG_RETURN(ret);
}
@@ -599,6 +600,30 @@ Event_parse_data::init_definer(THD *thd)
/*
+ Set the originator id of the event to the server_id if executing on
+ the master or set to the server_id of the master if executing on
+ the slave. If executing on slave, also set status to SLAVESIDE_DISABLED.
+
+ SYNOPSIS
+ Event_parse_data::check_originator_id()
+*/
+void Event_parse_data::check_originator_id(THD *thd)
+{
+ /* Disable replicated events on slave. */
+ if ((thd->system_thread == SYSTEM_THREAD_SLAVE_SQL) ||
+ (thd->system_thread == SYSTEM_THREAD_SLAVE_IO))
+ {
+ DBUG_PRINT("info", ("Invoked object status set to SLAVESIDE_DISABLED."));
+ if (status == Event_basic::ENABLED)
+ status = Event_basic::SLAVESIDE_DISABLED;
+ originator = thd->server_id;
+ }
+ else
+ originator = server_id;
+}
+
+
+/*
Constructor
SYNOPSIS
@@ -927,8 +952,23 @@ Event_queue_element::load_from_row(TABLE *table)
goto error;
DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", name.str, ptr));
- status= (ptr[0]=='E'? Event_queue_element::ENABLED:
- Event_queue_element::DISABLED);
+
+ /* Set event status (ENABLED | SLAVESIDE_DISABLED | DISABLED) */
+ switch (ptr[0])
+ {
+ case 'E' :
+ status = Event_queue_element::ENABLED;
+ break;
+ case 'S' :
+ status = Event_queue_element::SLAVESIDE_DISABLED;
+ break;
+ case 'D' :
+ status = Event_queue_element::DISABLED;
+ break;
+ }
+ if ((ptr= get_field(&mem_root, table->field[ET_FIELD_ORIGINATOR])) == NullS)
+ goto error;
+ originator = table->field[ET_FIELD_ORIGINATOR]->val_int();
/* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */
if ((ptr= get_field(&mem_root,
@@ -1199,7 +1239,7 @@ Event_queue_element::compute_next_execution_time()
(long) TIME_to_ulonglong_datetime(&last_executed),
(long) this));
- if (status == Event_queue_element::DISABLED)
+ if (status != Event_queue_element::ENABLED)
{
DBUG_PRINT("compute_next_execution_time",
("Event %s is DISABLED", name.str));
@@ -1601,6 +1641,8 @@ Event_timed::get_create_event(THD *thd, String *buf)
if (status == Event_timed::ENABLED)
buf->append(STRING_WITH_LEN("ENABLE"));
+ else if (status == Event_timed::SLAVESIDE_DISABLED)
+ buf->append(STRING_WITH_LEN("SLAVESIDE_DISABLE"));
else
buf->append(STRING_WITH_LEN("DISABLE"));
diff --git a/sql/event_data_objects.h b/sql/event_data_objects.h
index e00b0b94eaf..a63340e67c8 100644
--- a/sql/event_data_objects.h
+++ b/sql/event_data_objects.h
@@ -22,17 +22,33 @@
#define EVEX_BAD_PARAMS -5
#define EVEX_MICROSECOND_UNSUP -6
-
class sp_head;
class Sql_alloc;
-
class Event_basic
{
protected:
MEM_ROOT mem_root;
public:
+ /*
+ ENABLED = feature can function normally (is turned on)
+ SLAVESIDE_DISABLED = feature is turned off on slave
+ DISABLED = feature is turned off
+ */
+ enum enum_status
+ {
+ ENABLED = 1,
+ DISABLED,
+ SLAVESIDE_DISABLED
+ };
+
+ enum enum_on_completion
+ {
+ ON_COMPLETION_DROP = 1,
+ ON_COMPLETION_PRESERVE
+ };
+
LEX_STRING dbname;
LEX_STRING name;
LEX_STRING definer;// combination of user and host
@@ -57,20 +73,9 @@ protected:
bool last_executed_changed;
public:
- enum enum_status
- {
- ENABLED = 1,
- DISABLED
- };
-
- enum enum_on_completion
- {
- ON_COMPLETION_DROP = 1,
- ON_COMPLETION_PRESERVE
- };
-
- enum enum_on_completion on_completion;
- enum enum_status status;
+ int on_completion;
+ int status;
+ longlong originator;
TIME last_executed;
TIME execute_at;
@@ -194,19 +199,10 @@ private:
class Event_parse_data : public Sql_alloc
{
public:
- enum enum_status
- {
- ENABLED = 1,
- DISABLED
- };
- enum enum_on_completion
- {
- ON_COMPLETION_DROP = 1,
- ON_COMPLETION_PRESERVE
- };
- enum enum_on_completion on_completion;
- enum enum_status status;
+ int on_completion;
+ int status;
+ longlong originator;
const uchar *body_begin;
@@ -268,6 +264,7 @@ private:
report_bad_value(const char *item_name, Item *bad_item);
Event_parse_data(const Event_parse_data &); /* Prevent use of these */
+ void Event_parse_data::check_originator_id(THD *thd);
void operator=(Event_parse_data &);
};
diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc
index 940930ec4c6..1b001db984c 100644
--- a/sql/event_db_repository.cc
+++ b/sql/event_db_repository.cc
@@ -94,7 +94,7 @@ const TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] =
},
{
{ C_STRING_WITH_LEN("status") },
- { C_STRING_WITH_LEN("enum('ENABLED','DISABLED')") },
+ { C_STRING_WITH_LEN("enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')") },
{NULL, 0}
},
{
@@ -118,6 +118,11 @@ const TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] =
{ C_STRING_WITH_LEN("comment") },
{ C_STRING_WITH_LEN("char(64)") },
{ C_STRING_WITH_LEN("utf8") }
+ },
+ {
+ { C_STRING_WITH_LEN("originator") },
+ { C_STRING_WITH_LEN("int(10)") },
+ {NULL, 0}
}
};
@@ -170,6 +175,9 @@ mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et,
fields[ET_FIELD_STATUS]->store((longlong)et->status, TRUE);
+ fields[ET_FIELD_ORIGINATOR]->store((longlong)et->originator, TRUE);
+
+
/*
Change the SQL_MODE only if body was present in an ALTER EVENT and of course
always during CREATE EVENT.
@@ -535,7 +543,6 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
goto err;
}
-
DBUG_PRINT("info", ("name: %.*s", parse_data->name.length,
parse_data->name.str));
@@ -603,6 +610,8 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
if ((ret= mysql_event_fill_row(thd, table, parse_data, FALSE)))
goto err;
+ table->field[ET_FIELD_STATUS]->store((longlong)parse_data->status, TRUE);
+
/* Close active transaction only if We are going to modify disk */
if (end_active_trans(thd))
goto err;
diff --git a/sql/event_db_repository.h b/sql/event_db_repository.h
index 1457fb64e2e..ff23b1f5c85 100644
--- a/sql/event_db_repository.h
+++ b/sql/event_db_repository.h
@@ -19,7 +19,7 @@
enum enum_events_table_field
{
- ET_FIELD_DB = 0,
+ ET_FIELD_DB = 0,
ET_FIELD_NAME,
ET_FIELD_BODY,
ET_FIELD_DEFINER,
@@ -35,6 +35,7 @@ enum enum_events_table_field
ET_FIELD_ON_COMPLETION,
ET_FIELD_SQL_MODE,
ET_FIELD_COMMENT,
+ ET_FIELD_ORIGINATOR,
ET_FIELD_COUNT /* a cool trick to count the number of fields :) */
};
diff --git a/sql/event_queue.cc b/sql/event_queue.cc
index 068abbe3408..d951e926901 100644
--- a/sql/event_queue.cc
+++ b/sql/event_queue.cc
@@ -218,7 +218,8 @@ Event_queue::create_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
new_element= new Event_queue_element();
res= db_repository->load_named_event(thd, dbname, name, new_element);
- if (res || new_element->status == Event_queue_element::DISABLED)
+ if (res || new_element->status == Event_queue_element::DISABLED
+ || new_element->status == Event_queue_element::SLAVESIDE_DISABLED)
delete new_element;
else
{
@@ -231,7 +232,6 @@ Event_queue::create_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
pthread_cond_broadcast(&COND_queue_state);
UNLOCK_QUEUE_DATA();
}
-
DBUG_RETURN(res);
}
@@ -271,7 +271,7 @@ Event_queue::update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
delete new_element;
goto end;
}
- else if (new_element->status == Event_queue_element::DISABLED)
+ else if (new_element->status != Event_queue_element::ENABLED)
{
DBUG_PRINT("info", ("The event is disabled."));
/*
diff --git a/sql/events.cc b/sql/events.cc
index e6224915d6b..80ee613a6b9 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -347,7 +347,15 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, bool if_not_exists)
DBUG_RETURN(TRUE);
}
+ /*
+ Turn off row binlogging of this statement and use statement-based
+ so that all supporting tables are updated for CREATE EVENT command.
+ */
+ if (thd->current_stmt_binlog_row_based)
+ thd->clear_current_stmt_binlog_row_based();
+
pthread_mutex_lock(&LOCK_event_metadata);
+
/* On error conditions my_error() is called so no need to handle here */
if (!(ret= db_repository->create_event(thd, parse_data, if_not_exists)))
{
@@ -357,6 +365,15 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, bool if_not_exists)
DBUG_ASSERT(ret == OP_LOAD_ERROR);
my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0));
}
+ else /* Binlog the create event. */
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+ }
}
pthread_mutex_unlock(&LOCK_event_metadata);
@@ -396,7 +413,15 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, sp_name *rename_to)
DBUG_RETURN(TRUE);
}
+ /*
+ Turn off row binlogging of this statement and use statement-based
+ so that all supporting tables are updated for UPDATE EVENT command.
+ */
+ if (thd->current_stmt_binlog_row_based)
+ thd->clear_current_stmt_binlog_row_based();
+
pthread_mutex_lock(&LOCK_event_metadata);
+
/* On error conditions my_error() is called so no need to handle here */
if (!(ret= db_repository->update_event(thd, parse_data, new_dbname, new_name)))
{
@@ -406,6 +431,15 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, sp_name *rename_to)
DBUG_ASSERT(ret == OP_LOAD_ERROR);
my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0));
}
+ else /* Binlog the alter event. */
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+ }
}
pthread_mutex_unlock(&LOCK_event_metadata);
@@ -445,12 +479,27 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists,
DBUG_RETURN(TRUE);
}
+ /*
+ Turn off row binlogging of this statement and use statement-based so
+ that all supporting tables are updated for DROP EVENT command.
+ */
+ if (thd->current_stmt_binlog_row_based)
+ thd->clear_current_stmt_binlog_row_based();
+
pthread_mutex_lock(&LOCK_event_metadata);
/* On error conditions my_error() is called so no need to handle here */
if (!(ret= db_repository->drop_event(thd, dbname, name, if_exists)))
{
if (!only_from_disk)
event_queue->drop_event(thd, dbname, name);
+
+ /* Binlog the drop event. */
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
}
pthread_mutex_unlock(&LOCK_event_metadata);
DBUG_RETURN(ret);
diff --git a/sql/lex.h b/sql/lex.h
index 45155da7692..6e0f1c711f2 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -467,6 +467,7 @@ static SYMBOL symbols[] = {
{ "SIGNED", SYM(SIGNED_SYM)},
{ "SIMPLE", SYM(SIMPLE_SYM)},
{ "SLAVE", SYM(SLAVE)},
+ { "SLAVESIDE_DISABLE", SYM(SLAVESIDE_DISABLE_SYM)},
{ "SNAPSHOT", SYM(SNAPSHOT_SYM)},
{ "SMALLINT", SYM(SMALLINT)},
{ "SOCKET", SYM(SOCKET_SYM)},
diff --git a/sql/slave.cc b/sql/slave.cc
index 3a9cde42059..aa018f560ed 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -2387,10 +2387,25 @@ Slave SQL thread aborted. Can't execute init_slave query");
/* Print any warnings issued */
List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
MYSQL_ERROR *err;
+ /*
+ Added controlled slave thread cancel for replication
+ of user-defined variables.
+ */
+ bool udf_error = false;
while ((err= it++))
+ {
+ if (err->code == ER_CANT_OPEN_LIBRARY)
+ udf_error = true;
sql_print_warning("Slave: %s Error_code: %d",err->msg, err->code);
-
- sql_print_error("\
+ }
+ if (udf_error)
+ sql_print_error("Error loading user-defined library, slave SQL "
+ "thread aborted. Install the missing library, and restart the "
+ "slave SQL thread with \"SLAVE START\". We stopped at log '%s' "
+ "position %s", RPL_LOG_NAME, llstr(rli->group_master_log_pos,
+ llbuff));
+ else
+ sql_print_error("\
Error running query, slave SQL thread aborted. Fix the problem, and restart \
the slave SQL thread with \"SLAVE START\". We stopped at log \
'%s' position %s", RPL_LOG_NAME, llstr(rli->group_master_log_pos, llbuff));
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index ce7f34e3a06..de304976c0d 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3866,7 +3866,6 @@ create_sp_error:
if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0, 0))
goto error;
- /* Does NOT write to binlog */
if (!(res = mysql_drop_function(thd, &lex->spname->m_name)))
{
send_ok(thd);
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 881cf7dc6c4..6a6e7ce3225 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -52,7 +52,8 @@ enum enum_i_s_events_fields
ISE_CREATED,
ISE_LAST_ALTERED,
ISE_LAST_EXECUTED,
- ISE_EVENT_COMMENT
+ ISE_EVENT_COMMENT,
+ ISE_ORIGINATOR
};
@@ -4393,10 +4394,23 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
}
/* status */
- if (et.status == Event_timed::ENABLED)
- sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("ENABLED"), scs);
- else
- sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("DISABLED"), scs);
+
+ switch (et.status)
+ {
+ case Event_timed::ENABLED:
+ sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("ENABLED"), scs);
+ break;
+ case Event_timed::SLAVESIDE_DISABLED:
+ sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("SLAVESIDE_DISABLED"),
+ scs);
+ break;
+ case Event_timed::DISABLED:
+ sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("DISABLED"), scs);
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ sch_table->field[ISE_ORIGINATOR]->store(et.originator, TRUE);
/* on_completion */
if (et.on_completion == Event_timed::ON_COMPLETION_DROP)
@@ -4935,9 +4949,7 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
TABLE *table;
DBUG_ENTER("mysql_schema_table");
if (!(table= table_list->schema_table->create_table(thd, table_list)))
- {
DBUG_RETURN(1);
- }
table->s->tmp_table= SYSTEM_TMP_TABLE;
table->grant.privilege= SELECT_ACL;
/*
@@ -5429,13 +5441,14 @@ ST_FIELD_INFO events_fields_info[]=
{"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, 0},
{"STARTS", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Starts"},
{"ENDS", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Ends"},
- {"STATUS", 8, MYSQL_TYPE_STRING, 0, 0, "Status"},
+ {"STATUS", 18, MYSQL_TYPE_STRING, 0, 0, "Status"},
{"ON_COMPLETION", 12, MYSQL_TYPE_STRING, 0, 0, 0},
{"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0},
{"LAST_ALTERED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0},
{"LAST_EXECUTED", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, 0},
+ {"ORIGINATOR", 10, MYSQL_TYPE_LONG, 0, 0, "Originator"},
{"EVENT_COMMENT", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
- {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
};
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index 7dec58d9b6e..3ab161bb04f 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -403,6 +403,13 @@ int mysql_create_function(THD *thd,udf_func *udf)
DBUG_RETURN(1);
}
+ /*
+ Turn off row binlogging of this statement and use statement-based
+ so that all supporting tables are updated for CREATE FUNCTION command.
+ */
+ if (thd->current_stmt_binlog_row_based)
+ thd->clear_current_stmt_binlog_row_based();
+
rw_wrlock(&THR_LOCK_udf);
if ((hash_search(&udf_hash,(byte*) udf->name.str, udf->name.length)))
{
@@ -466,6 +473,15 @@ int mysql_create_function(THD *thd,udf_func *udf)
goto err;
}
rw_unlock(&THR_LOCK_udf);
+
+ /* Binlog the create function. */
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+
DBUG_RETURN(0);
err:
@@ -484,11 +500,20 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
char *exact_name_str;
uint exact_name_len;
DBUG_ENTER("mysql_drop_function");
+
if (!initialized)
{
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
DBUG_RETURN(1);
}
+
+ /*
+ Turn off row binlogging of this statement and use statement-based
+ so that all supporting tables are updated for DROP FUNCTION command.
+ */
+ if (thd->current_stmt_binlog_row_based)
+ thd->clear_current_stmt_binlog_row_based();
+
rw_wrlock(&THR_LOCK_udf);
if (!(udf=(udf_func*) hash_search(&udf_hash,(byte*) udf_name->str,
(uint) udf_name->length)))
@@ -525,6 +550,15 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
close_thread_tables(thd);
rw_unlock(&THR_LOCK_udf);
+
+ /* Binlog the drop function. */
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+
DBUG_RETURN(0);
err:
rw_unlock(&THR_LOCK_udf);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 9c062407921..67251159327 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -813,6 +813,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token SIGNED_SYM
%token SIMPLE_SYM /* SQL-2003-N */
%token SLAVE
+%token SLAVESIDE_DISABLE_SYM
%token SMALLINT /* SQL-2003-R */
%token SNAPSHOT_SYM
%token SOCKET_SYM
@@ -1632,12 +1633,17 @@ ev_schedule_time: EVERY_SYM expr interval
opt_ev_status: /* empty */ { $$= 0; }
| ENABLE_SYM
{
- Lex->event_parse_data->status= Event_parse_data::ENABLED;
+ Lex->event_parse_data->status= Event_basic::ENABLED;
+ $$= 1;
+ }
+ | SLAVESIDE_DISABLE_SYM
+ {
+ Lex->event_parse_data->status= Event_basic::SLAVESIDE_DISABLED;
$$= 1;
}
| DISABLE_SYM
{
- Lex->event_parse_data->status= Event_parse_data::DISABLED;
+ Lex->event_parse_data->status= Event_basic::DISABLED;
$$= 1;
}
;
@@ -1667,13 +1673,13 @@ ev_on_completion:
ON COMPLETION_SYM PRESERVE_SYM
{
Lex->event_parse_data->on_completion=
- Event_parse_data::ON_COMPLETION_PRESERVE;
+ Event_basic::ON_COMPLETION_PRESERVE;
$$= 1;
}
| ON COMPLETION_SYM NOT_SYM PRESERVE_SYM
{
Lex->event_parse_data->on_completion=
- Event_parse_data::ON_COMPLETION_DROP;
+ Event_basic::ON_COMPLETION_DROP;
$$= 1;
}
;
@@ -9832,6 +9838,7 @@ keyword_sp:
| SIMPLE_SYM {}
| SHARE_SYM {}
| SHUTDOWN {}
+ | SLAVESIDE_DISABLE_SYM {}
| SNAPSHOT_SYM {}
| SOUNDS_SYM {}
| SQL_CACHE_SYM {}