Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 67 additions & 2 deletions client/mysqldump.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
*/
#define FIRST_SEQUENCE_VERSION 100300

#define FIRST_SYS_TRIGGER_VERSION 130000

#include <my_global.h>
#include <my_sys.h>
#include <my_user.h>
Expand Down Expand Up @@ -133,7 +135,8 @@ static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0, opt_no_data_m
opt_events= 0, opt_comments_used= 0,
opt_alltspcs=0, opt_notspcs= 0, opt_logging,
opt_header=0, opt_update_history= 0,
opt_drop_trigger= 0, opt_dump_history= 0, opt_wildcards= 0;
opt_drop_trigger= 0, opt_dump_history= 0, opt_wildcards= 0,
opt_dump_sys_triggers= 0;
#define OPT_SYSTEM_ALL 1
#define OPT_SYSTEM_USERS 2
#define OPT_SYSTEM_PLUGINS 4
Expand Down Expand Up @@ -603,6 +606,9 @@ static struct my_option my_long_options[] =
{"triggers", 0, "Dump triggers for each dumped table.",
&opt_dump_triggers, &opt_dump_triggers, 0, GET_BOOL,
NO_ARG, 1, 0, 0, 0, 0, 0},
{"sys_triggers", 0, "Dump system triggers.",
&opt_dump_sys_triggers, &opt_dump_sys_triggers, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
{"tz-utc", 0,
"Set connection time zone to UTC before commencing the dump and add "
"SET TIME_ZONE=´+00:00´ to the top of the dump file.",
Expand Down Expand Up @@ -5595,12 +5601,26 @@ static int dump_all_databases()
MYSQL_ROW row;
MYSQL_RES *tableres;
int result=0;
char mysql_db[]= "mysql";

if (mysql_query_with_error_report(mysql, &tableres, "SHOW DATABASES"))
return 1;

/*
First dump mysql database since it contains the table mysql.event where
triggers' metadata stored
*/
if (dump_all_tables_in_db(mysql_db))
return 1;

while ((row= mysql_fetch_row(tableres)))
{
if (is_IS_or_PS(row[0]) || is_SyS(row[0]))
if (is_IS_or_PS(row[0]) || is_SyS(row[0]) ||
/*
Skip the `mysql` database since it is dumped before entering into
the while loop
*/
!cmp_database(row[0], mysql_db))
continue;

if (include_database(row[0]))
Expand Down Expand Up @@ -7587,6 +7607,44 @@ void dump_databases_wild(int n_patterns, char **db_patterns)
DBUG_VOID_RETURN;
}

static void dump_sys_triggers()
{
char query_buff[QUERY_LENGTH];
MYSQL_RES *triggers_list_rs= nullptr;

my_snprintf(query_buff, sizeof(query_buff),
"SELECT name FROM mysql.event WHERE kind IN "
"('STARTUP', 'SHUTDOWN')");
if (mysql_query_with_error_report(mysql, &triggers_list_rs, query_buff))
{
mysql_free_result(triggers_list_rs);
return;
}

if (mysql_num_rows(triggers_list_rs))
{
MYSQL_ROW row;
while ((row= mysql_fetch_row(triggers_list_rs)))
{
MYSQL_RES *show_create_trigger_rs;
char name_buff[NAME_LEN*4+3];

my_snprintf(query_buff, sizeof (query_buff), "SHOW CREATE TRIGGER %s",
quote_name(row[0], name_buff, TRUE));

if (mysql_query_with_error_report(mysql, &show_create_trigger_rs,
query_buff))
{
mysql_free_result(triggers_list_rs);
maybe_exit(EX_MYSQLERR);
}
dump_trigger(md_result_file, show_create_trigger_rs, "", "");
mysql_free_result(show_create_trigger_rs);
}
}
mysql_free_result(triggers_list_rs);
}


int main(int argc, char **argv)
{
Expand Down Expand Up @@ -7785,6 +7843,13 @@ int main(int argc, char **argv)
}
}

if (opt_dump_sys_triggers &&
mysql_get_server_version(mysql) >= FIRST_SYS_TRIGGER_VERSION)
{
DBUG_PRINT("info", ("Dumping system trigger"));
dump_sys_triggers();
}

if (opt_system & OPT_SYSTEM_PLUGINS)
dump_all_plugins();

Expand Down
2 changes: 2 additions & 0 deletions libmysqld/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/opt_hints.cc ../sql/opt_hints.h
../sql/opt_trace_ddl_info.cc ../sql/opt_trace_ddl_info.h
../sql/sql_path.cc
../sql/sql_sys_or_ddl_trigger.cc
../sql/event_common.cc
${GEN_SOURCES}
${MYSYS_LIBWRAP_SOURCE}
)
Expand Down
9 changes: 9 additions & 0 deletions mysql-test/main/mysql_upgrade-28915.result
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ event CREATE TABLE `event` (
`collation_connection` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
`db_collation` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
`body_utf8` longblob DEFAULT NULL,
`kind` set('SCHEDULE','STARTUP','SHUTDOWN','LOGON','LOGOFF','DDL') NOT NULL DEFAULT 'SCHEDULE',
`when` enum('BEFORE','AFTER') DEFAULT NULL,
`ddl_type` set('CREATE','ALTER','DROP','TRUNCATE','ANALYZE','RENAME','GRANT','REVOKE') DEFAULT NULL,
PRIMARY KEY (`db`,`name`)
) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Events'
Phase 1/8: Checking and upgrading mysql database
Expand Down Expand Up @@ -277,6 +280,9 @@ event CREATE TABLE `event` (
`collation_connection` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
`db_collation` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
`body_utf8` longblob DEFAULT NULL,
`kind` set('SCHEDULE','STARTUP','SHUTDOWN','LOGON','LOGOFF','DDL') NOT NULL DEFAULT 'SCHEDULE',
`when` enum('BEFORE','AFTER') DEFAULT NULL,
`ddl_type` set('CREATE','ALTER','DROP','TRUNCATE','ANALYZE','RENAME','GRANT','REVOKE') DEFAULT NULL,
PRIMARY KEY (`db`,`name`)
) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Events'
# Emulate that tables were created with utf8mb4 by an older version
Expand Down Expand Up @@ -544,6 +550,9 @@ Create Table CREATE TABLE `event` (
`collation_connection` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
`db_collation` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
`body_utf8` longblob DEFAULT NULL,
`kind` set('SCHEDULE','STARTUP','SHUTDOWN','LOGON','LOGOFF','DDL') NOT NULL DEFAULT 'SCHEDULE',
`when` enum('BEFORE','AFTER') DEFAULT NULL,
`ddl_type` set('CREATE','ALTER','DROP','TRUNCATE','ANALYZE','RENAME','GRANT','REVOKE') DEFAULT NULL,
PRIMARY KEY (`db`,`name`)
) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Events'
SET GLOBAL event_scheduler=OFF;
Expand Down
2 changes: 1 addition & 1 deletion mysql-test/main/sp2.test

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions mysql-test/main/system_mysql_db.result
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ event CREATE TABLE `event` (
`collation_connection` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
`db_collation` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
`body_utf8` longblob DEFAULT NULL,
`kind` set('SCHEDULE','STARTUP','SHUTDOWN','LOGON','LOGOFF','DDL') NOT NULL DEFAULT 'SCHEDULE',
`when` enum('BEFORE','AFTER') DEFAULT NULL,
`ddl_type` set('CREATE','ALTER','DROP','TRUNCATE','ANALYZE','RENAME','GRANT','REVOKE') DEFAULT NULL,
PRIMARY KEY (`db`,`name`)
) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Events'
show create table general_log;
Expand Down
3 changes: 3 additions & 0 deletions mysql-test/main/system_mysql_db_fix40123.result
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ event CREATE TABLE `event` (
`collation_connection` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
`db_collation` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
`body_utf8` longblob DEFAULT NULL,
`kind` set('SCHEDULE','STARTUP','SHUTDOWN','LOGON','LOGOFF','DDL') NOT NULL DEFAULT 'SCHEDULE',
`when` enum('BEFORE','AFTER') DEFAULT NULL,
`ddl_type` set('CREATE','ALTER','DROP','TRUNCATE','ANALYZE','RENAME','GRANT','REVOKE') DEFAULT NULL,
PRIMARY KEY (`db`,`name`)
) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Events'
show create table general_log;
Expand Down
3 changes: 3 additions & 0 deletions mysql-test/main/system_mysql_db_fix50030.result
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,9 @@ event CREATE TABLE `event` (
`collation_connection` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
`db_collation` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
`body_utf8` longblob DEFAULT NULL,
`kind` set('SCHEDULE','STARTUP','SHUTDOWN','LOGON','LOGOFF','DDL') NOT NULL DEFAULT 'SCHEDULE',
`when` enum('BEFORE','AFTER') DEFAULT NULL,
`ddl_type` set('CREATE','ALTER','DROP','TRUNCATE','ANALYZE','RENAME','GRANT','REVOKE') DEFAULT NULL,
PRIMARY KEY (`db`,`name`)
) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Events'
show create table general_log;
Expand Down
3 changes: 3 additions & 0 deletions mysql-test/main/system_mysql_db_fix50117.result
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,9 @@ event CREATE TABLE `event` (
`collation_connection` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
`db_collation` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
`body_utf8` longblob DEFAULT NULL,
`kind` set('SCHEDULE','STARTUP','SHUTDOWN','LOGON','LOGOFF','DDL') NOT NULL DEFAULT 'SCHEDULE',
`when` enum('BEFORE','AFTER') DEFAULT NULL,
`ddl_type` set('CREATE','ALTER','DROP','TRUNCATE','ANALYZE','RENAME','GRANT','REVOKE') DEFAULT NULL,
PRIMARY KEY (`db`,`name`)
) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Events'
show create table general_log;
Expand Down
3 changes: 3 additions & 0 deletions mysql-test/main/system_mysql_db_fix50568.result
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ event CREATE TABLE `event` (
`collation_connection` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
`db_collation` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL,
`body_utf8` longblob DEFAULT NULL,
`kind` set('SCHEDULE','STARTUP','SHUTDOWN','LOGON','LOGOFF','DDL') NOT NULL DEFAULT 'SCHEDULE',
`when` enum('BEFORE','AFTER') DEFAULT NULL,
`ddl_type` set('CREATE','ALTER','DROP','TRUNCATE','ANALYZE','RENAME','GRANT','REVOKE') DEFAULT NULL,
PRIMARY KEY (`db`,`name`)
) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Events'
show create table general_log;
Expand Down
2 changes: 1 addition & 1 deletion mysql-test/main/trigger.result
Original file line number Diff line number Diff line change
Expand Up @@ -2131,7 +2131,7 @@ insert into t2 values (1),(2);
delete from t1 where i=1;
show status like 'Opened_tables';
Variable_name Value
Opened_tables 6
Opened_tables 7
select * from t1;
i
2
Expand Down
182 changes: 182 additions & 0 deletions mysql-test/main/trigger_system.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
call mtr.add_suppression('Column count of mysql.event is wrong.');
call mtr.add_suppression('Event Scheduler: An error occurred when initializing system tables. Disabling the Event Scheduler.');
call mtr.add_suppression('An error occurred when loading data from the table mysql.event. System triggers not loaded');
call mtr.add_suppression('Aborting');
call mtr.add_suppression('Incorrect definition of table mysql.event: expected column');
#
# MDEV-30645: CREATE TRIGGER FOR { STARTUP | SHUTDOWN }
#
# Test 1: Check that AFTER STARTUP trigger and BEFORE SHUTDOWN trigger
# are fired at right time
CREATE TABLE t1 (a VARCHAR(100));
CREATE TRIGGER IF NOT EXISTS trg1 AFTER STARTUP INSERT INTO t1 VALUES('Startup');
# BEFORE SHUTDOWN should be in action just after it has been created.
# So, after restarting the server the record about server shutdown should
# be inserted into the table t1.
CREATE TRIGGER IF NOT EXISTS trg2 BEFORE SHUTDOWN INSERT INTO t1 VALUES('Shutdown');
# restart
SELECT * FROM t1;
a
Shutdown
Startup
# Clean up
DROP TABLE t1;
DROP TRIGGER trg1;
DROP TRIGGER trg2;
#
# Test 2: Check that ON STARTUP/ON SHUTDOWN can't be created
# w/o the SUPER privilege
#
# Check that ON STARTUP/ON SHUTDOWN can be created w/o the SUPER privilege
CREATE USER u1;
GRANT SELECT ON test.* TO u1;
connect con1, localhost, u1, , test;
# The following CREATE TRIGGER AFTER STARTUP statement should fail with
# the error ER_SPECIFIC_ACCESS_DENIED_ERROR since the user `u1` doesn't
# have the SUPER privilege
CREATE TRIGGER IF NOT EXISTS trg1 AFTER STARTUP SET @a=1;
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
# The following CREATE TRIGGER BEFORE SHUTDOWN statement should fail with
# the error ER_SPECIFIC_ACCESS_DENIED_ERROR since the user `u1` doesn't
# have the SUPER privilege
CREATE TRIGGER IF NOT EXISTS trg1 BEFORE SHUTDOWN SET @b=1;
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
connection default;
disconnect con1;
DROP USER u1;
#
# Test 3: Check that a user with the explicitly granted the SUPER privilege
# can create a system trigger on STARTUP/on SHUTDOWN
#
CREATE USER u1;
GRANT SELECT ON test.* TO u1;
GRANT SUPER ON *.* TO u1;
connect con1, localhost, u1, , test;
# The following CREATE TRIGGER AFTER STARTUP statement and
# CREATE TRIGGER BEFORE SHUTDOWN statement should succeed
# since the SUPER privilege is granted to the user `u1`
CREATE TRIGGER IF NOT EXISTS trg1 AFTER STARTUP INSERT INTO t1 VALUES('Startup');
CREATE TRIGGER IF NOT EXISTS trg2 BEFORE SHUTDOWN INSERT INTO t1 VALUES('Shutdown');
connection default;
disconnect con1;
# Clean up
DROP TRIGGER trg1;
DROP TRIGGER trg2;
DROP USER u1;
#
# Test 4: Check that it is not possible to create a System trigger
# and a DML trigger with the same name
#
CREATE TABLE t1 (a INT);
# First check that DML trigger can 't be created with the same name
# as the existing system trigger
CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW SET @a=1;
CREATE TRIGGER trg1 AFTER STARTUP SET @b=1;
ERROR HY000: Trigger 'test.trg1' already exists
DROP TRIGGER trg1;
# And then check in reverse order: a system trigger can't be created
# on presence of DML trigger with the same name
CREATE TRIGGER trg1 AFTER STARTUP SET @b=1;
CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW SET @a=1;
ERROR HY000: Trigger 'test.trg1' already exists
# Clean up
DROP TRIGGER trg1;
DROP TABLE t1;
#
# Test 5: Check that multiple triggers can be created on the same
# system event
#
CREATE TABLE t1 (a VARCHAR(100));
CREATE TRIGGER IF NOT EXISTS trg1_ast AFTER STARTUP INSERT INTO t1 VALUES('Startup: first action');
CREATE TRIGGER IF NOT EXISTS trg2_ast AFTER STARTUP INSERT INTO t1 VALUES('Startup: second action');
# BEFORE SHUTDOWN should be in action just after it has been created.
# So, after restarting the server the record about server shutdown should
# be inserted into the table t1.
CREATE TRIGGER IF NOT EXISTS trg3_bshd BEFORE SHUTDOWN INSERT INTO t1 VALUES('Shutdown: first action');
CREATE TRIGGER IF NOT EXISTS trg4_bshd BEFORE SHUTDOWN INSERT INTO t1 VALUES('Shutdown: second action');
# restart
SELECT * FROM t1;
a
Shutdown: first action
Shutdown: second action
Startup: first action
Startup: second action
# Clean up
DROP TABLE t1;
DROP TRIGGER trg1_ast;
DROP TRIGGER trg2_ast;
DROP TRIGGER trg3_bshd;
DROP TRIGGER trg4_bshd;
#
# Test 6: SHOW TRIGGERS on a system trigger
#
CREATE TRIGGER trg1 AFTER STARTUP SET @b=1;
SHOW TRIGGERS;
Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation
trg1 STARTUP SET @b=1 AFTER # STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION root@localhost latin1 latin1_swedish_ci utf8mb4_uca1400_ai_ci
# Clean up
DROP TRIGGER trg1;
#
# Test 7: SHOW CREATE TRIGGER on a system trigger
#
CREATE TRIGGER trg1 AFTER STARTUP SET @b=1;
SHOW CREATE TRIGGER trg1;
Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation Created
trg1 STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root`@`localhost` TRIGGER trg1 AFTER STARTUP SET @b=1 latin1 latin1_swedish_ci utf8mb4_uca1400_ai_ci #
# Clean up
DROP TRIGGER trg1;
#
# Test 8: Check that triggers and events have the same namespace
#
# Test 8.1 Check that attempt to create a trigger with the same name
# as existent event result in error
CREATE EVENT ev1 ON SCHEDULE EVERY 1 YEAR DO SET @aaa=1;
Warnings:
Warning 1105 Event scheduler is switched off, use SET GLOBAL event_scheduler=ON to enable it.
CREATE TRIGGER ev1 AFTER STARTUP SET @bbb=1;
ERROR HY000: Event with the same name 'ev1' already exists
# Clean up
DROP EVENT ev1;
# Test 8.2 Check that attempt to create an event with the same name as
# as existen trigger result in error
CREATE TRIGGER trg1 AFTER STARTUP SET @bbb=1;
CREATE EVENT trg1 ON SCHEDULE EVERY 1 YEAR DO SET @aaa=1;
ERROR HY000: Trigger with the same name 'trg1' already exists
# Clean up
DROP TRIGGER trg1;
#
# Test 9: Check that server can operate on database with
# broken table mysql.event.
CREATE TRIGGER trg1 AFTER STARTUP SET @bbb=1;
# Backup the mysql.event table
CREATE TABLE event_copy LIKE mysql.event;
INSERT INTO event_copy SELECT * FROM mysql.event;
# Drop column 'kind' in the table mysql.event to simulate a failure on
# loading triggers metadata from the table mysql.event
ALTER TABLE mysql.event DROP COLUMN kind;
# Shutdown server and restart it to see how it handle broken
# table mysql.event
# Restart server. Expect start up failure
# Force server start up even on broken data dictionary.
# restart: --skip-grant-tables
# Restore original mysql.event from backup
DROP TABLE mysql.event;
RENAME TABLE event_copy TO mysql.event;
# Restart server. Should be successful.
# restart
# Clean up
DROP TRIGGER trg1;
#
# Test 10: Check that server can be started up on the data dictionary
# having the table mysql.event from previous version of
# server (missing mandatory columns for support of system triggers)
#
RENAME TABLE mysql.event TO mysql.ev_bk;
# Copy event table's files from previous server version (12.3)
# that doesn't contain columns required for system triggers support
# restart
CREATE TRIGGER ev1 AFTER STARTUP SET @bbb=1;
ERROR HY000: The table mysql.event doesn't contain all mandatory columns required for support of system triggers. Operations with system triggers is disabled.
DROP TABLE mysql.event;
RENAME TABLE mysql.ev_bk TO mysql.event;
# End of Test 10.
Loading
Loading