mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge bk-internal.mysql.com:/home/bk/mysql-5.1-runtime
into vajra.(none):/opt/local/work/mysql-5.1-c1 mysql-test/r/events_bugs.result: Auto merged mysql-test/r/events_scheduling.result: Auto merged mysql-test/t/events.test: Auto merged mysql-test/t/events_scheduling.test: Auto merged sql/event_data_objects.h: Auto merged sql/event_db_repository.h: Auto merged sql/mysqld.cc: Auto merged sql/set_var.cc: Auto merged sql/set_var.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_show.cc: Auto merged sql/table.h: Auto merged sql/share/errmsg.txt: Auto merged mysql-test/r/events.result: e Use local. mysql-test/r/events_restart_phase1.result: Use local mysql-test/r/events_time_zone.result: SCCS merged mysql-test/t/events_restart_phase1.test: Use local sql/event_data_objects.cc: Use local sql/event_db_repository.cc: Manual merge. sql/event_queue.cc: Manual merge. sql/events.cc: Manual merge.
This commit is contained in:
@ -1,4 +1,8 @@
|
|||||||
create database if not exists events_test;
|
drop database if exists events_test;
|
||||||
|
drop database if exists db_x;
|
||||||
|
drop database if exists mysqltest_db2;
|
||||||
|
drop database if exists mysqltest_no_such_database;
|
||||||
|
create database events_test;
|
||||||
use events_test;
|
use events_test;
|
||||||
CREATE USER pauline@localhost;
|
CREATE USER pauline@localhost;
|
||||||
CREATE DATABASE db_x;
|
CREATE DATABASE db_x;
|
||||||
@ -193,7 +197,7 @@ create event
|
|||||||
SHOW CREATE EVENT <20><><EFBFBD><EFBFBD>21;
|
SHOW CREATE EVENT <20><><EFBFBD><EFBFBD>21;
|
||||||
Event sql_mode time_zone Create Event
|
Event sql_mode time_zone Create Event
|
||||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>21 SYSTEM CREATE EVENT `<60><><EFBFBD><EFBFBD>21` ON SCHEDULE EVERY '51 0:0:35' DAY_SECOND STARTS '#' ON COMPLETION NOT PRESERVE ENABLE COMMENT '<27><><EFBFBD><EFBFBD> <20> 1251 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>' DO select 1
|
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>21 SYSTEM CREATE EVENT `<60><><EFBFBD><EFBFBD>21` ON SCHEDULE EVERY '51 0:0:35' DAY_SECOND STARTS '#' ON COMPLETION NOT PRESERVE ENABLE COMMENT '<27><><EFBFBD><EFBFBD> <20> 1251 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>' DO select 1
|
||||||
insert into mysql.event (db, name, body, definer, interval_value, interval_field, originator) values (database(), "root22", "select 1", user(), 100, "SECOND_MICROSECOND", 1);
|
insert into mysql.event (db, name, body, definer, interval_value, interval_field) values (database(), "root22", "select 1", user(), 100, "SECOND_MICROSECOND");
|
||||||
show create event root22;
|
show create event root22;
|
||||||
ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
|
ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
|
||||||
SHOW EVENTS;
|
SHOW EVENTS;
|
||||||
@ -223,73 +227,180 @@ drop event root19;
|
|||||||
drop event root20;
|
drop event root20;
|
||||||
drop event <20><><EFBFBD><EFBFBD>21;
|
drop event <20><><EFBFBD><EFBFBD>21;
|
||||||
set names latin1;
|
set names latin1;
|
||||||
|
Create a test event. Only event metadata is relevant,
|
||||||
|
the actual schedule and body are not.
|
||||||
CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing";
|
CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing";
|
||||||
SHOW EVENTS;
|
SHOW EVENTS;
|
||||||
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator
|
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
|
||||||
events_test intact_check root@localhost SYSTEM RECURRING NULL 10 # # NULL ENABLED 1
|
events_test intact_check root@localhost SYSTEM RECURRING NULL 10 # # NULL ENABLED
|
||||||
|
Try to alter mysql.event: the server should fail to load
|
||||||
|
event information after mysql.event was tampered with.
|
||||||
|
|
||||||
|
First, let's add a column to the end and make sure everything
|
||||||
|
works as before
|
||||||
|
|
||||||
|
ALTER TABLE mysql.event ADD dummy INT;
|
||||||
|
SHOW EVENTS;
|
||||||
|
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
|
||||||
|
events_test intact_check root@localhost SYSTEM RECURRING NULL 10 # # NULL ENABLED
|
||||||
|
SELECT event_name FROM INFORMATION_SCHEMA.events;
|
||||||
|
event_name
|
||||||
|
intact_check
|
||||||
|
SHOW CREATE EVENT intact_check;
|
||||||
|
Event sql_mode time_zone Create Event
|
||||||
|
intact_check SYSTEM CREATE EVENT `intact_check` ON SCHEDULE EVERY 10 HOUR STARTS '#' ON COMPLETION NOT PRESERVE ENABLE DO SELECT "nothing"
|
||||||
|
DROP EVENT no_such_event;
|
||||||
|
ERROR HY000: Unknown event 'no_such_event'
|
||||||
|
CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
|
||||||
|
ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
|
||||||
|
ALTER EVENT intact_check_1 RENAME TO intact_check_2;
|
||||||
|
DROP EVENT intact_check_1;
|
||||||
|
ERROR HY000: Unknown event 'intact_check_1'
|
||||||
|
DROP EVENT intact_check_2;
|
||||||
|
DROP EVENT intact_check;
|
||||||
|
DROP DATABASE IF EXISTS mysqltest_no_such_database;
|
||||||
|
Warnings:
|
||||||
|
Note 1008 Can't drop database 'mysqltest_no_such_database'; database doesn't exist
|
||||||
|
CREATE DATABASE mysqltest_db2;
|
||||||
|
DROP DATABASE mysqltest_db2;
|
||||||
|
SELECT @@event_scheduler;
|
||||||
|
@@event_scheduler
|
||||||
|
OFF
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
Variable_name Value
|
||||||
|
event_scheduler OFF
|
||||||
|
SET GLOBAL event_scheduler=OFF;
|
||||||
|
ALTER TABLE mysql.event DROP dummy;
|
||||||
|
CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing";
|
||||||
|
|
||||||
|
Now let's add a column to the first position: the server
|
||||||
|
expects to see event schema name there
|
||||||
|
|
||||||
ALTER TABLE mysql.event ADD dummy INT FIRST;
|
ALTER TABLE mysql.event ADD dummy INT FIRST;
|
||||||
SHOW EVENTS;
|
SHOW EVENTS;
|
||||||
ERROR HY000: Column count of mysql.event is wrong. Expected 18, found 19. The table is probably corrupted
|
ERROR HY000: Cannot load from mysql.event. The table is probably corrupted
|
||||||
ALTER TABLE mysql.event DROP dummy, ADD dummy2 VARCHAR(64) FIRST;
|
SELECT event_name FROM INFORMATION_SCHEMA.events;
|
||||||
SHOW EVENTS;
|
ERROR HY000: Cannot load from mysql.event. The table is probably corrupted
|
||||||
ERROR HY000: Column count of mysql.event is wrong. Expected 18, found 19. The table is probably corrupted
|
SHOW CREATE EVENT intact_check;
|
||||||
ALTER TABLE mysql.event DROP dummy2;
|
ERROR HY000: Unknown event 'intact_check'
|
||||||
SHOW EVENTS;
|
DROP EVENT no_such_event;
|
||||||
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator
|
ERROR HY000: Unknown event 'no_such_event'
|
||||||
events_test intact_check root@localhost SYSTEM RECURRING NULL 10 # # NULL ENABLED 1
|
CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
|
||||||
|
ERROR HY000: Cannot load from mysql.event. The table is probably corrupted
|
||||||
|
ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
|
||||||
|
ERROR HY000: Unknown event 'intact_check_1'
|
||||||
|
ALTER EVENT intact_check_1 RENAME TO intact_check_2;
|
||||||
|
ERROR HY000: Unknown event 'intact_check_1'
|
||||||
|
DROP EVENT intact_check_1;
|
||||||
|
ERROR HY000: Unknown event 'intact_check_1'
|
||||||
|
DROP EVENT intact_check_2;
|
||||||
|
ERROR HY000: Unknown event 'intact_check_2'
|
||||||
|
DROP EVENT intact_check;
|
||||||
|
ERROR HY000: Unknown event 'intact_check'
|
||||||
|
DROP DATABASE IF EXISTS mysqltest_no_such_database;
|
||||||
|
Warnings:
|
||||||
|
Note 1008 Can't drop database 'mysqltest_no_such_database'; database doesn't exist
|
||||||
|
CREATE DATABASE mysqltest_db2;
|
||||||
|
DROP DATABASE mysqltest_db2;
|
||||||
|
SELECT @@event_scheduler;
|
||||||
|
@@event_scheduler
|
||||||
|
OFF
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
Variable_name Value
|
||||||
|
event_scheduler OFF
|
||||||
|
SET GLOBAL event_scheduler=OFF;
|
||||||
|
Clean up
|
||||||
|
ALTER TABLE mysql.event DROP dummy;
|
||||||
|
DELETE FROM mysql.event;
|
||||||
|
CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing";
|
||||||
|
Back up the table, further changes are not reversible
|
||||||
CREATE TABLE event_like LIKE mysql.event;
|
CREATE TABLE event_like LIKE mysql.event;
|
||||||
INSERT INTO event_like SELECT * FROM mysql.event;
|
INSERT INTO event_like SELECT * FROM mysql.event;
|
||||||
ALTER TABLE mysql.event MODIFY db char(64) character set cp1251 default '';
|
|
||||||
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
Drop some columns and try more checks.
|
||||||
ERROR HY000: Cannot load from mysql.event. The table is probably corrupted. Please see the error log for details
|
|
||||||
ALTER TABLE mysql.event MODIFY db char(20) character set utf8 collate utf8_bin default '';
|
|
||||||
SHOW CREATE TABLE mysql.event;
|
|
||||||
Table Create Table
|
|
||||||
event CREATE TABLE `event` (
|
|
||||||
`db` char(20) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
|
|
||||||
`name` char(64) NOT NULL DEFAULT '',
|
|
||||||
`body` longblob NOT NULL,
|
|
||||||
`definer` char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
|
|
||||||
`execute_at` datetime DEFAULT NULL,
|
|
||||||
`interval_value` int(11) DEFAULT NULL,
|
|
||||||
`interval_field` enum('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') DEFAULT NULL,
|
|
||||||
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
||||||
`modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`last_executed` datetime DEFAULT NULL,
|
|
||||||
`starts` datetime DEFAULT NULL,
|
|
||||||
`ends` datetime DEFAULT NULL,
|
|
||||||
`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,
|
|
||||||
`time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM',
|
|
||||||
PRIMARY KEY (`db`,`name`)
|
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events'
|
|
||||||
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
|
||||||
ERROR HY000: Cannot load from mysql.event. The table is probably corrupted. Please see the error log for details
|
|
||||||
ALTER TABLE mysql.event MODIFY db char(64) character set utf8 collate utf8_bin default '';
|
|
||||||
"This should work"
|
|
||||||
SHOW EVENTS;
|
|
||||||
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator
|
|
||||||
events_test intact_check root@localhost SYSTEM RECURRING NULL 10 # # NULL 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. The table is probably corrupted. Please see the error log for details
|
|
||||||
ALTER TABLE mysql.event MODIFY db varchar(64) character set utf8 collate utf8_bin default '';
|
|
||||||
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
|
||||||
ERROR HY000: Cannot load from mysql.event. The table is probably corrupted. Please see the error log for details
|
|
||||||
ALTER TABLE mysql.event DROP comment, DROP starts;
|
ALTER TABLE mysql.event DROP comment, DROP starts;
|
||||||
|
SHOW EVENTS;
|
||||||
|
ERROR HY000: Cannot load from mysql.event. The table is probably corrupted
|
||||||
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
||||||
ERROR HY000: Column count of mysql.event is wrong. Expected 18, found 16. The table is probably corrupted
|
ERROR HY000: Cannot load from mysql.event. The table is probably corrupted
|
||||||
|
SHOW CREATE EVENT intact_check;
|
||||||
|
ERROR HY000: Cannot load from mysql.event. The table is probably corrupted
|
||||||
|
DROP EVENT no_such_event;
|
||||||
|
ERROR HY000: Unknown event 'no_such_event'
|
||||||
|
CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
|
||||||
|
ERROR HY000: Column count of mysql.event is wrong. Expected 17, found 15. The table is probably corrupted
|
||||||
|
ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
|
||||||
|
ERROR HY000: Unknown event 'intact_check_1'
|
||||||
|
ALTER EVENT intact_check_1 RENAME TO intact_check_2;
|
||||||
|
ERROR HY000: Unknown event 'intact_check_1'
|
||||||
|
DROP EVENT intact_check_1;
|
||||||
|
ERROR HY000: Unknown event 'intact_check_1'
|
||||||
|
DROP EVENT intact_check_2;
|
||||||
|
ERROR HY000: Unknown event 'intact_check_2'
|
||||||
|
DROP EVENT intact_check;
|
||||||
|
DROP DATABASE IF EXISTS mysqltest_no_such_database;
|
||||||
|
Warnings:
|
||||||
|
Note 1008 Can't drop database 'mysqltest_no_such_database'; database doesn't exist
|
||||||
|
CREATE DATABASE mysqltest_db2;
|
||||||
|
DROP DATABASE mysqltest_db2;
|
||||||
|
SELECT @@event_scheduler;
|
||||||
|
@@event_scheduler
|
||||||
|
OFF
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
Variable_name Value
|
||||||
|
event_scheduler OFF
|
||||||
|
SET GLOBAL event_scheduler=OFF;
|
||||||
|
|
||||||
|
Now drop the table, and test again
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE mysql.event;
|
DROP TABLE mysql.event;
|
||||||
|
SHOW EVENTS;
|
||||||
|
ERROR 42S02: Table 'mysql.event' doesn't exist
|
||||||
|
SELECT event_name FROM INFORMATION_SCHEMA.events;
|
||||||
|
ERROR 42S02: Table 'mysql.event' doesn't exist
|
||||||
|
SHOW CREATE EVENT intact_check;
|
||||||
|
ERROR 42S02: Table 'mysql.event' doesn't exist
|
||||||
|
DROP EVENT no_such_event;
|
||||||
|
ERROR 42S02: Table 'mysql.event' doesn't exist
|
||||||
|
CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
|
||||||
|
ERROR 42S02: Table 'mysql.event' doesn't exist
|
||||||
|
ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
|
||||||
|
ERROR 42S02: Table 'mysql.event' doesn't exist
|
||||||
|
ALTER EVENT intact_check_1 RENAME TO intact_check_2;
|
||||||
|
ERROR 42S02: Table 'mysql.event' doesn't exist
|
||||||
|
DROP EVENT intact_check_1;
|
||||||
|
ERROR 42S02: Table 'mysql.event' doesn't exist
|
||||||
|
DROP EVENT intact_check_2;
|
||||||
|
ERROR 42S02: Table 'mysql.event' doesn't exist
|
||||||
|
DROP EVENT intact_check;
|
||||||
|
ERROR 42S02: Table 'mysql.event' doesn't exist
|
||||||
|
DROP DATABASE IF EXISTS mysqltest_no_such_database;
|
||||||
|
Warnings:
|
||||||
|
Note 1008 Can't drop database 'mysqltest_no_such_database'; database doesn't exist
|
||||||
|
Error 1146 Table 'mysql.event' doesn't exist
|
||||||
|
CREATE DATABASE mysqltest_db2;
|
||||||
|
DROP DATABASE mysqltest_db2;
|
||||||
|
OK, there is an unnecessary warning about the non-existent table
|
||||||
|
but it's not easy to fix and no one complained about it.
|
||||||
|
A similar warning is printed if mysql.proc is missing.
|
||||||
|
SHOW WARNINGS;
|
||||||
|
Level Code Message
|
||||||
|
Error 1146 Table 'mysql.event' doesn't exist
|
||||||
|
SELECT @@event_scheduler;
|
||||||
|
@@event_scheduler
|
||||||
|
OFF
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
Variable_name Value
|
||||||
|
event_scheduler OFF
|
||||||
|
SET GLOBAL event_scheduler=OFF;
|
||||||
|
Restore the original table.
|
||||||
CREATE TABLE mysql.event like event_like;
|
CREATE TABLE mysql.event like event_like;
|
||||||
INSERT INTO mysql.event SELECT * FROM event_like;
|
|
||||||
DROP TABLE event_like;
|
DROP TABLE event_like;
|
||||||
SHOW EVENTS;
|
SHOW EVENTS;
|
||||||
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator
|
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
|
||||||
events_test intact_check root@localhost SYSTEM RECURRING NULL 10 # # NULL ENABLED 1
|
|
||||||
DROP EVENT intact_check;
|
|
||||||
create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5;
|
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;
|
select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event;
|
||||||
db name body definer convert_tz(execute_at, 'UTC', 'SYSTEM') on_completion
|
db name body definer convert_tz(execute_at, 'UTC', 'SYSTEM') on_completion
|
||||||
@ -401,5 +512,197 @@ ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
|||||||
SHOW EVENTS FROM ``;
|
SHOW EVENTS FROM ``;
|
||||||
ERROR 42000: Incorrect database name ''
|
ERROR 42000: Incorrect database name ''
|
||||||
SHOW EVENTS FROM `events\\test`;
|
SHOW EVENTS FROM `events\\test`;
|
||||||
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator
|
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
|
||||||
|
|
||||||
|
LOCK TABLES mode.
|
||||||
|
|
||||||
|
create table t1 (a int);
|
||||||
|
create event e1 on schedule every 10 hour do select 1;
|
||||||
|
lock table t1 read;
|
||||||
|
show create event e1;
|
||||||
|
Event sql_mode time_zone Create Event
|
||||||
|
e1 SYSTEM CREATE EVENT `e1` ON SCHEDULE EVERY 10 HOUR STARTS '#' ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
event_name
|
||||||
|
e1
|
||||||
|
create event e2 on schedule every 10 hour do select 1;
|
||||||
|
ERROR HY000: Table 'event' was not locked with LOCK TABLES
|
||||||
|
alter event e2 disable;
|
||||||
|
ERROR HY000: Table 'event' was not locked with LOCK TABLES
|
||||||
|
alter event e2 rename to e3;
|
||||||
|
ERROR HY000: Table 'event' was not locked with LOCK TABLES
|
||||||
|
drop event e2;
|
||||||
|
ERROR HY000: Table 'event' was not locked with LOCK TABLES
|
||||||
|
drop event e1;
|
||||||
|
ERROR HY000: Table 'event' was not locked with LOCK TABLES
|
||||||
|
unlock tables;
|
||||||
|
lock table t1 write;
|
||||||
|
show create event e1;
|
||||||
|
Event sql_mode time_zone Create Event
|
||||||
|
e1 SYSTEM CREATE EVENT `e1` ON SCHEDULE EVERY 10 HOUR STARTS '#' ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
event_name
|
||||||
|
e1
|
||||||
|
create event e2 on schedule every 10 hour do select 1;
|
||||||
|
ERROR HY000: Table 'event' was not locked with LOCK TABLES
|
||||||
|
alter event e2 disable;
|
||||||
|
ERROR HY000: Table 'event' was not locked with LOCK TABLES
|
||||||
|
alter event e2 rename to e3;
|
||||||
|
ERROR HY000: Table 'event' was not locked with LOCK TABLES
|
||||||
|
drop event e2;
|
||||||
|
ERROR HY000: Table 'event' was not locked with LOCK TABLES
|
||||||
|
drop event e1;
|
||||||
|
ERROR HY000: Table 'event' was not locked with LOCK TABLES
|
||||||
|
unlock tables;
|
||||||
|
lock table t1 read, mysql.event read;
|
||||||
|
show create event e1;
|
||||||
|
Event sql_mode time_zone Create Event
|
||||||
|
e1 SYSTEM CREATE EVENT `e1` ON SCHEDULE EVERY 10 HOUR STARTS '#' ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
event_name
|
||||||
|
e1
|
||||||
|
create event e2 on schedule every 10 hour do select 1;
|
||||||
|
ERROR HY000: Table 'event' was locked with a READ lock and can't be updated
|
||||||
|
alter event e2 disable;
|
||||||
|
ERROR HY000: Table 'event' was locked with a READ lock and can't be updated
|
||||||
|
alter event e2 rename to e3;
|
||||||
|
ERROR HY000: Table 'event' was locked with a READ lock and can't be updated
|
||||||
|
drop event e2;
|
||||||
|
ERROR HY000: Table 'event' was locked with a READ lock and can't be updated
|
||||||
|
drop event e1;
|
||||||
|
ERROR HY000: Table 'event' was locked with a READ lock and can't be updated
|
||||||
|
unlock tables;
|
||||||
|
lock table t1 write, mysql.event read;
|
||||||
|
show create event e1;
|
||||||
|
Event sql_mode time_zone Create Event
|
||||||
|
e1 SYSTEM CREATE EVENT `e1` ON SCHEDULE EVERY 10 HOUR STARTS '#' ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
event_name
|
||||||
|
e1
|
||||||
|
create event e2 on schedule every 10 hour do select 1;
|
||||||
|
ERROR HY000: Table 'event' was locked with a READ lock and can't be updated
|
||||||
|
alter event e2 disable;
|
||||||
|
ERROR HY000: Table 'event' was locked with a READ lock and can't be updated
|
||||||
|
alter event e2 rename to e3;
|
||||||
|
ERROR HY000: Table 'event' was locked with a READ lock and can't be updated
|
||||||
|
drop event e2;
|
||||||
|
ERROR HY000: Table 'event' was locked with a READ lock and can't be updated
|
||||||
|
drop event e1;
|
||||||
|
ERROR HY000: Table 'event' was locked with a READ lock and can't be updated
|
||||||
|
unlock tables;
|
||||||
|
lock table t1 read, mysql.event write;
|
||||||
|
ERROR HY000: You can't combine write-locking of system tables with other tables or lock types
|
||||||
|
lock table t1 write, mysql.event write;
|
||||||
|
ERROR HY000: You can't combine write-locking of system tables with other tables or lock types
|
||||||
|
lock table mysql.event write;
|
||||||
|
show create event e1;
|
||||||
|
Event sql_mode time_zone Create Event
|
||||||
|
e1 SYSTEM CREATE EVENT `e1` ON SCHEDULE EVERY 10 HOUR STARTS '#' ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
event_name
|
||||||
|
e1
|
||||||
|
create event e2 on schedule every 10 hour do select 1;
|
||||||
|
alter event e2 disable;
|
||||||
|
alter event e2 rename to e3;
|
||||||
|
drop event e3;
|
||||||
|
drop event e1;
|
||||||
|
unlock tables;
|
||||||
|
Make sure we have left no events
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
event_name
|
||||||
|
|
||||||
|
Events in sub-statements, events and prelocking
|
||||||
|
|
||||||
|
|
||||||
|
create event e1 on schedule every 10 hour do select 1;
|
||||||
|
create function f1() returns int
|
||||||
|
begin
|
||||||
|
show create event e1;
|
||||||
|
return 1;
|
||||||
|
end|
|
||||||
|
ERROR 0A000: Not allowed to return a result set from a function
|
||||||
|
create trigger trg before insert on t1 for each row
|
||||||
|
begin
|
||||||
|
show create event e1;
|
||||||
|
end|
|
||||||
|
ERROR 0A000: Not allowed to return a result set from a trigger
|
||||||
|
create function f1() returns int
|
||||||
|
begin
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
return 1;
|
||||||
|
end|
|
||||||
|
ERROR 0A000: Not allowed to return a result set from a function
|
||||||
|
create trigger trg before insert on t1 for each row
|
||||||
|
begin
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
end|
|
||||||
|
ERROR 0A000: Not allowed to return a result set from a trigger
|
||||||
|
create function f1() returns int
|
||||||
|
begin
|
||||||
|
create event e2 on schedule every 10 hour do select 1;
|
||||||
|
return 1;
|
||||||
|
end|
|
||||||
|
ERROR HY000: Recursion of EVENT DDL statements is forbidden when body is present
|
||||||
|
create function f1() returns int
|
||||||
|
begin
|
||||||
|
alter event e1 rename to e2;
|
||||||
|
return 1;
|
||||||
|
end|
|
||||||
|
ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
|
||||||
|
create function f1() returns int
|
||||||
|
begin
|
||||||
|
drop event e2;
|
||||||
|
return 1;
|
||||||
|
end|
|
||||||
|
ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
create trigger trg before insert on t1 for each row
|
||||||
|
begin
|
||||||
|
set new.a= f1();
|
||||||
|
end|
|
||||||
|
create function f1() returns int
|
||||||
|
begin
|
||||||
|
call p1();
|
||||||
|
return 0;
|
||||||
|
end|
|
||||||
|
create procedure p1()
|
||||||
|
begin
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
end|
|
||||||
|
insert into t1 (a) values (1)|
|
||||||
|
ERROR 0A000: Not allowed to return a result set from a trigger
|
||||||
|
drop procedure p1|
|
||||||
|
create procedure p1()
|
||||||
|
begin
|
||||||
|
show create event e1;
|
||||||
|
end|
|
||||||
|
insert into t1 (a) values (1)|
|
||||||
|
ERROR 0A000: Not allowed to return a result set from a trigger
|
||||||
|
drop procedure p1|
|
||||||
|
create procedure p1()
|
||||||
|
begin
|
||||||
|
create temporary table tmp select event_name from information_schema.events;
|
||||||
|
end|
|
||||||
|
expected to work, since we redirect the output into a tmp table
|
||||||
|
insert into t1 (a) values (1)|
|
||||||
|
select * from tmp|
|
||||||
|
event_name
|
||||||
|
e1
|
||||||
|
drop temporary table tmp|
|
||||||
|
drop procedure p1|
|
||||||
|
create procedure p1()
|
||||||
|
begin
|
||||||
|
alter event e1 rename to e2;
|
||||||
|
end|
|
||||||
|
insert into t1 (a) values (1)|
|
||||||
|
ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
|
||||||
|
drop procedure p1|
|
||||||
|
create procedure p1()
|
||||||
|
begin
|
||||||
|
drop event e1;
|
||||||
|
end|
|
||||||
|
insert into t1 (a) values (1)|
|
||||||
|
ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
|
||||||
|
drop table t1|
|
||||||
|
drop event e1|
|
||||||
drop database events_test;
|
drop database events_test;
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
create database if not exists events_test;
|
drop database if exists events_test;
|
||||||
|
drop database if exists mysqltest_db1;
|
||||||
|
drop database if exists mysqltest_db2;
|
||||||
|
create database events_test;
|
||||||
use events_test;
|
use events_test;
|
||||||
CREATE EVENT lower_case ON SCHEDULE EVERY 1 MINUTE DO SELECT 1;
|
CREATE EVENT lower_case ON SCHEDULE EVERY 1 MINUTE DO SELECT 1;
|
||||||
CREATE EVENT Lower_case ON SCHEDULE EVERY 2 MINUTE DO SELECT 2;
|
CREATE EVENT Lower_case ON SCHEDULE EVERY 2 MINUTE DO SELECT 2;
|
||||||
@ -381,4 +384,149 @@ ERROR 42000: Access denied; you need the SUPER privilege for this operation
|
|||||||
DROP EVENT e1;
|
DROP EVENT e1;
|
||||||
ERROR HY000: Unknown event 'e1'
|
ERROR HY000: Unknown event 'e1'
|
||||||
DROP USER mysqltest_u1@localhost;
|
DROP USER mysqltest_u1@localhost;
|
||||||
|
SET GLOBAL EVENT_SCHEDULER= OFF;
|
||||||
|
SET @save_time_zone= @@TIME_ZONE;
|
||||||
|
SET TIME_ZONE= '+00:00';
|
||||||
|
SET TIMESTAMP= UNIX_TIMESTAMP('2005-12-31 23:58:59');
|
||||||
|
CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
|
||||||
|
SHOW EVENTS;
|
||||||
|
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
|
||||||
|
events_test e1 root@localhost +00:00 RECURRING NULL 1 DAY 2005-12-31 23:58:59 NULL ENABLED
|
||||||
|
SET TIME_ZONE= '-01:00';
|
||||||
|
ALTER EVENT e1 ON SCHEDULE EVERY 1 DAY STARTS '2000-01-01 00:00:00';
|
||||||
|
SHOW EVENTS;
|
||||||
|
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
|
||||||
|
events_test e1 root@localhost -01:00 RECURRING NULL 1 DAY 2000-01-01 00:00:00 NULL ENABLED
|
||||||
|
SET TIME_ZONE= '+02:00';
|
||||||
|
ALTER EVENT e1 ON SCHEDULE AT '2000-01-02 00:00:00'
|
||||||
|
ON COMPLETION PRESERVE DISABLE;
|
||||||
|
SHOW EVENTS;
|
||||||
|
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
|
||||||
|
events_test e1 root@localhost +02:00 ONE TIME 2000-01-02 00:00:00 NULL NULL NULL NULL DISABLED
|
||||||
|
SET TIME_ZONE= '-03:00';
|
||||||
|
ALTER EVENT e1 ON SCHEDULE EVERY 1 DAY ENDS '2030-01-03 00:00:00'
|
||||||
|
ON COMPLETION PRESERVE DISABLE;
|
||||||
|
SHOW EVENTS;
|
||||||
|
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
|
||||||
|
events_test e1 root@localhost -03:00 RECURRING NULL 1 DAY 2005-12-31 20:58:59 2030-01-03 00:00:00 DISABLED
|
||||||
|
SET TIME_ZONE= '+04:00';
|
||||||
|
ALTER EVENT e1 DO SELECT 2;
|
||||||
|
SHOW EVENTS;
|
||||||
|
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
|
||||||
|
events_test e1 root@localhost -03:00 RECURRING NULL 1 DAY 2005-12-31 20:58:59 2030-01-03 00:00:00 ENABLED
|
||||||
|
DROP EVENT e1;
|
||||||
|
SET TIME_ZONE='+05:00';
|
||||||
|
CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
|
||||||
|
SELECT 1;
|
||||||
|
SET TIMESTAMP= @@TIMESTAMP + 1;
|
||||||
|
SET TIME_ZONE='-05:00';
|
||||||
|
CREATE EVENT e2 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
|
||||||
|
SELECT 1;
|
||||||
|
SET TIMESTAMP= @@TIMESTAMP + 1;
|
||||||
|
SET TIME_ZONE='+00:00';
|
||||||
|
CREATE EVENT e3 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
|
||||||
|
SELECT 1;
|
||||||
|
SELECT * FROM INFORMATION_SCHEMA.EVENTS ORDER BY event_name;
|
||||||
|
EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER TIME_ZONE EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD SQL_MODE STARTS ENDS STATUS ON_COMPLETION CREATED LAST_ALTERED LAST_EXECUTED EVENT_COMMENT
|
||||||
|
NULL events_test e1 root@localhost +05:00 SQL SELECT 1 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED NOT PRESERVE 2005-12-31 23:58:59 2005-12-31 23:58:59 NULL
|
||||||
|
NULL events_test e2 root@localhost -05:00 SQL SELECT 1 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED NOT PRESERVE 2005-12-31 23:59:00 2005-12-31 23:59:00 NULL
|
||||||
|
NULL events_test e3 root@localhost +00:00 SQL SELECT 1 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED NOT PRESERVE 2005-12-31 23:59:01 2005-12-31 23:59:01 NULL
|
||||||
|
SHOW EVENTS;
|
||||||
|
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
|
||||||
|
events_test e1 root@localhost +05:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED
|
||||||
|
events_test e2 root@localhost -05:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED
|
||||||
|
events_test e3 root@localhost +00:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED
|
||||||
|
SHOW CREATE EVENT e1;
|
||||||
|
Event sql_mode time_zone Create Event
|
||||||
|
e1 +05:00 CREATE EVENT `e1` ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' ON COMPLETION NOT PRESERVE ENABLE DO SELECT 1
|
||||||
|
SHOW CREATE EVENT e2;
|
||||||
|
Event sql_mode time_zone Create Event
|
||||||
|
e2 -05:00 CREATE EVENT `e2` ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' ON COMPLETION NOT PRESERVE ENABLE DO SELECT 1
|
||||||
|
SHOW CREATE EVENT e3;
|
||||||
|
Event sql_mode time_zone Create Event
|
||||||
|
e3 +00:00 CREATE EVENT `e3` ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' ON COMPLETION NOT PRESERVE ENABLE DO SELECT 1
|
||||||
|
The following should fail, and nothing should be altered.
|
||||||
|
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||||
|
ENDS '1999-01-02 00:00:00';
|
||||||
|
ERROR HY000: Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been altered
|
||||||
|
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||||
|
ENDS '1999-01-02 00:00:00' DISABLE;
|
||||||
|
ERROR HY000: Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been altered
|
||||||
|
The following should give warnings, and nothing should be created.
|
||||||
|
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||||
|
ENDS '1999-01-02 00:00:00'
|
||||||
|
DO
|
||||||
|
SELECT 1;
|
||||||
|
Warnings:
|
||||||
|
Note 1584 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been created
|
||||||
|
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||||
|
ENDS '1999-01-02 00:00:00' DISABLE
|
||||||
|
DO
|
||||||
|
SELECT 1;
|
||||||
|
Warnings:
|
||||||
|
Note 1584 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been created
|
||||||
|
CREATE EVENT e4 ON SCHEDULE AT '1999-01-01 00:00:00' DO
|
||||||
|
SELECT 1;
|
||||||
|
Warnings:
|
||||||
|
Note 1584 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been created
|
||||||
|
CREATE EVENT e4 ON SCHEDULE AT '1999-01-01 00:00:00' DISABLE
|
||||||
|
DO
|
||||||
|
SELECT 1;
|
||||||
|
Warnings:
|
||||||
|
Note 1584 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been created
|
||||||
|
SHOW EVENTS;
|
||||||
|
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
|
||||||
|
events_test e1 root@localhost +05:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED
|
||||||
|
events_test e2 root@localhost -05:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED
|
||||||
|
events_test e3 root@localhost +00:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED
|
||||||
|
The following should succeed giving a warning.
|
||||||
|
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||||
|
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE;
|
||||||
|
Warnings:
|
||||||
|
Note 1533 Event execution time is in the past. Event has been disabled
|
||||||
|
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||||
|
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE
|
||||||
|
DO
|
||||||
|
SELECT 1;
|
||||||
|
Warnings:
|
||||||
|
Note 1533 Event execution time is in the past. Event has been disabled
|
||||||
|
CREATE EVENT e5 ON SCHEDULE AT '1999-01-01 00:00:00'
|
||||||
|
ON COMPLETION PRESERVE
|
||||||
|
DO
|
||||||
|
SELECT 1;
|
||||||
|
Warnings:
|
||||||
|
Note 1533 Event execution time is in the past. Event has been disabled
|
||||||
|
The following should succeed without warnings.
|
||||||
|
ALTER EVENT e2 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00';
|
||||||
|
ALTER EVENT e3 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||||
|
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE DISABLE;
|
||||||
|
CREATE EVENT e6 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00' DO
|
||||||
|
SELECT 1;
|
||||||
|
CREATE EVENT e7 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||||
|
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE DISABLE
|
||||||
|
DO
|
||||||
|
SELECT 1;
|
||||||
|
CREATE EVENT e8 ON SCHEDULE AT '1999-01-01 00:00:00'
|
||||||
|
ON COMPLETION PRESERVE DISABLE
|
||||||
|
DO
|
||||||
|
SELECT 1;
|
||||||
|
SHOW EVENTS;
|
||||||
|
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
|
||||||
|
events_test e1 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 1999-01-02 00:00:00 DISABLED
|
||||||
|
events_test e2 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 NULL ENABLED
|
||||||
|
events_test e3 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 1999-01-02 00:00:00 DISABLED
|
||||||
|
events_test e4 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 1999-01-02 00:00:00 DISABLED
|
||||||
|
events_test e5 root@localhost +00:00 ONE TIME 1999-01-01 00:00:00 NULL NULL NULL NULL DISABLED
|
||||||
|
events_test e6 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 NULL ENABLED
|
||||||
|
events_test e7 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 1999-01-02 00:00:00 DISABLED
|
||||||
|
events_test e8 root@localhost +00:00 ONE TIME 1999-01-01 00:00:00 NULL NULL NULL NULL DISABLED
|
||||||
|
DROP EVENT e8;
|
||||||
|
DROP EVENT e7;
|
||||||
|
DROP EVENT e6;
|
||||||
|
DROP EVENT e5;
|
||||||
|
DROP EVENT e4;
|
||||||
|
DROP EVENT e3;
|
||||||
|
DROP EVENT e2;
|
||||||
|
DROP EVENT e1;
|
||||||
|
SET TIME_ZONE=@save_time_zone;
|
||||||
drop database events_test;
|
drop database events_test;
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
create database if not exists mysqltest_events_test;
|
|
||||||
use mysqltest_events_test;
|
|
||||||
set global event_scheduler=off;
|
set global event_scheduler=off;
|
||||||
|
drop database if exists events_test;
|
||||||
|
create database events_test;
|
||||||
|
use events_test;
|
||||||
create table execution_log(name char(10));
|
create table execution_log(name char(10));
|
||||||
create event abc1 on schedule every 1 second do insert into execution_log value('abc1');
|
create event abc1 on schedule every 1 second do
|
||||||
create event abc2 on schedule every 1 second do insert into execution_log value('abc2');
|
insert into execution_log value('abc1');
|
||||||
create event abc3 on schedule every 1 second do insert into execution_log value('abc3');
|
create event abc2 on schedule every 1 second do
|
||||||
select name from execution_log;
|
insert into execution_log value('abc2');
|
||||||
name
|
create event abc3 on schedule every 1 second do
|
||||||
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,'SYSTEM');
|
insert into execution_log value('abc3');
|
||||||
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,'SYSTEM');
|
create table event_like like mysql.event;
|
||||||
|
insert into event_like select * from mysql.event;
|
||||||
|
alter table mysql.event
|
||||||
|
change column body body longtext character set utf8 collate utf8_bin;
|
||||||
"Now we restart the server"
|
"Now we restart the server"
|
||||||
|
@ -1,6 +1,42 @@
|
|||||||
use mysqltest_events_test;
|
use events_test;
|
||||||
"Should get 0 rows because the queue aborted run
|
select @@event_scheduler;
|
||||||
select distinct name from execution_log order by name;
|
@@event_scheduler
|
||||||
name
|
DISABLED
|
||||||
delete from mysql.event where name like 'bad%';
|
show events;
|
||||||
"Now restart the server again"
|
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
|
||||||
|
show create event intact_check;
|
||||||
|
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
|
||||||
|
drop event no_such_event;
|
||||||
|
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
|
||||||
|
create event intact_check_1 on schedule every 5 hour do select 5;
|
||||||
|
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
|
||||||
|
alter event intact_check_1 on schedule every 8 hour do select 8;
|
||||||
|
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
|
||||||
|
alter event intact_check_1 rename to intact_check_2;
|
||||||
|
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
|
||||||
|
drop event intact_check_1;
|
||||||
|
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
|
||||||
|
drop event intact_check_2;
|
||||||
|
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
|
||||||
|
drop event intact_check;
|
||||||
|
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
|
||||||
|
set global event_scheduler=on;
|
||||||
|
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
|
||||||
|
set global event_scheduler=off;
|
||||||
|
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
|
||||||
|
show variables like 'event_scheduler';
|
||||||
|
Variable_name Value
|
||||||
|
event_scheduler DISABLED
|
||||||
|
Make sure that we still can create and drop databases,
|
||||||
|
and no warnings are produced.
|
||||||
|
drop database if exists mysqltest_database_not_exists;
|
||||||
|
Warnings:
|
||||||
|
Note 1008 Can't drop database 'mysqltest_database_not_exists'; database doesn't exist
|
||||||
|
create database mysqltest_db1;
|
||||||
|
drop database mysqltest_db1;
|
||||||
|
Restore the original mysql.event table
|
||||||
|
drop table mysql.event;
|
||||||
|
rename table event_like to mysql.event;
|
||||||
|
Now let's restart the server again
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use mysqltest_events_test;
|
use events_test;
|
||||||
|
select @@event_scheduler;
|
||||||
|
@@event_scheduler
|
||||||
|
ON
|
||||||
"Should get 3 rows : abc1, abc2, abc3
|
"Should get 3 rows : abc1, abc2, abc3
|
||||||
select distinct name from execution_log order by name;
|
select distinct name from execution_log order by name;
|
||||||
name
|
name
|
||||||
abc1
|
abc1
|
||||||
abc2
|
abc2
|
||||||
abc3
|
abc3
|
||||||
drop event abc1;
|
|
||||||
drop event abc2;
|
|
||||||
drop event abc3;
|
|
||||||
drop table execution_log;
|
drop table execution_log;
|
||||||
drop database mysqltest_events_test;
|
drop database events_test;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
CREATE DATABASE IF NOT EXISTS events_test;
|
CREATE DATABASE IF NOT EXISTS events_test;
|
||||||
USE events_test;
|
USE events_test;
|
||||||
SET GLOBAL event_scheduler=OFF;
|
SET GLOBAL event_scheduler=OFF;
|
||||||
|
Try agian to make sure it's allowed
|
||||||
|
SET GLOBAL event_scheduler=OFF;
|
||||||
SHOW VARIABLES LIKE 'event_scheduler';
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
event_scheduler OFF
|
event_scheduler OFF
|
||||||
@ -13,6 +15,8 @@ SHOW VARIABLES LIKE 'event_scheduler';
|
|||||||
Variable_name Value
|
Variable_name Value
|
||||||
event_scheduler OFF
|
event_scheduler OFF
|
||||||
SET GLOBAL event_scheduler=ON;
|
SET GLOBAL event_scheduler=ON;
|
||||||
|
Try again to make sure it's allowed
|
||||||
|
SET GLOBAL event_scheduler=ON;
|
||||||
SHOW VARIABLES LIKE 'event_scheduler';
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
event_scheduler ON
|
event_scheduler ON
|
||||||
|
@ -3,148 +3,6 @@ CREATE DATABASE mysqltest_db1;
|
|||||||
USE mysqltest_db1;
|
USE mysqltest_db1;
|
||||||
SET GLOBAL EVENT_SCHEDULER= OFF;
|
SET GLOBAL EVENT_SCHEDULER= OFF;
|
||||||
SET @save_time_zone= @@TIME_ZONE;
|
SET @save_time_zone= @@TIME_ZONE;
|
||||||
SET TIME_ZONE= '+00:00';
|
|
||||||
SET TIMESTAMP= UNIX_TIMESTAMP('2005-12-31 23:58:59');
|
|
||||||
CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
|
|
||||||
SHOW EVENTS;
|
|
||||||
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator
|
|
||||||
mysqltest_db1 e1 root@localhost +00:00 RECURRING NULL 1 DAY 2005-12-31 23:58:59 NULL ENABLED 1
|
|
||||||
SET TIME_ZONE= '-01:00';
|
|
||||||
ALTER EVENT e1 ON SCHEDULE EVERY 1 DAY STARTS '2000-01-01 00:00:00';
|
|
||||||
SHOW EVENTS;
|
|
||||||
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator
|
|
||||||
mysqltest_db1 e1 root@localhost -01:00 RECURRING NULL 1 DAY 2000-01-01 00:00:00 NULL ENABLED 1
|
|
||||||
SET TIME_ZONE= '+02:00';
|
|
||||||
ALTER EVENT e1 ON SCHEDULE AT '2000-01-02 00:00:00'
|
|
||||||
ON COMPLETION PRESERVE DISABLE;
|
|
||||||
SHOW EVENTS;
|
|
||||||
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator
|
|
||||||
mysqltest_db1 e1 root@localhost +02:00 ONE TIME 2000-01-02 00:00:00 NULL NULL NULL NULL DISABLED 1
|
|
||||||
SET TIME_ZONE= '-03:00';
|
|
||||||
ALTER EVENT e1 ON SCHEDULE EVERY 1 DAY ENDS '2030-01-03 00:00:00'
|
|
||||||
ON COMPLETION PRESERVE DISABLE;
|
|
||||||
SHOW EVENTS;
|
|
||||||
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator
|
|
||||||
mysqltest_db1 e1 root@localhost -03:00 RECURRING NULL 1 DAY 2005-12-31 20:58:59 2030-01-03 00:00:00 DISABLED 1
|
|
||||||
SET TIME_ZONE= '+04:00';
|
|
||||||
ALTER EVENT e1 DO SELECT 2;
|
|
||||||
SHOW EVENTS;
|
|
||||||
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator
|
|
||||||
mysqltest_db1 e1 root@localhost -03:00 RECURRING NULL 1 DAY 2005-12-31 20:58:59 2030-01-03 00:00:00 ENABLED 1
|
|
||||||
DROP EVENT e1;
|
|
||||||
SET TIME_ZONE='+05:00';
|
|
||||||
CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
|
|
||||||
SELECT 1;
|
|
||||||
SET TIMESTAMP= @@TIMESTAMP + 1;
|
|
||||||
SET TIME_ZONE='-05:00';
|
|
||||||
CREATE EVENT e2 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
|
|
||||||
SELECT 1;
|
|
||||||
SET TIMESTAMP= @@TIMESTAMP + 1;
|
|
||||||
SET TIME_ZONE='+00:00';
|
|
||||||
CREATE EVENT e3 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
|
|
||||||
SELECT 1;
|
|
||||||
SELECT * FROM INFORMATION_SCHEMA.EVENTS;
|
|
||||||
EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER TIME_ZONE EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD SQL_MODE STARTS ENDS STATUS ON_COMPLETION CREATED LAST_ALTERED LAST_EXECUTED EVENT_COMMENT ORIGINATOR
|
|
||||||
NULL mysqltest_db1 e1 root@localhost +05:00 SQL SELECT 1 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED NOT PRESERVE 2005-12-31 23:58:59 2005-12-31 23:58:59 NULL 1
|
|
||||||
NULL mysqltest_db1 e2 root@localhost -05:00 SQL SELECT 1 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED NOT PRESERVE 2005-12-31 23:59:00 2005-12-31 23:59:00 NULL 1
|
|
||||||
NULL mysqltest_db1 e3 root@localhost +00:00 SQL SELECT 1 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED NOT PRESERVE 2005-12-31 23:59:01 2005-12-31 23:59:01 NULL 1
|
|
||||||
SHOW EVENTS;
|
|
||||||
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator
|
|
||||||
mysqltest_db1 e1 root@localhost +05:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED 1
|
|
||||||
mysqltest_db1 e2 root@localhost -05:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED 1
|
|
||||||
mysqltest_db1 e3 root@localhost +00:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED 1
|
|
||||||
SHOW CREATE EVENT e1;
|
|
||||||
Event sql_mode time_zone Create Event
|
|
||||||
e1 +05:00 CREATE EVENT `e1` ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' ON COMPLETION NOT PRESERVE ENABLE DO SELECT 1
|
|
||||||
SHOW CREATE EVENT e2;
|
|
||||||
Event sql_mode time_zone Create Event
|
|
||||||
e2 -05:00 CREATE EVENT `e2` ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' ON COMPLETION NOT PRESERVE ENABLE DO SELECT 1
|
|
||||||
SHOW CREATE EVENT e3;
|
|
||||||
Event sql_mode time_zone Create Event
|
|
||||||
e3 +00:00 CREATE EVENT `e3` ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' ON COMPLETION NOT PRESERVE ENABLE DO SELECT 1
|
|
||||||
The following should fail, and nothing should be altered.
|
|
||||||
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
|
||||||
ENDS '1999-01-02 00:00:00';
|
|
||||||
ERROR HY000: Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been altered
|
|
||||||
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
|
||||||
ENDS '1999-01-02 00:00:00' DISABLE;
|
|
||||||
ERROR HY000: Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been altered
|
|
||||||
The following should give warnings, and nothing should be created.
|
|
||||||
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
|
||||||
ENDS '1999-01-02 00:00:00'
|
|
||||||
DO
|
|
||||||
SELECT 1;
|
|
||||||
Warnings:
|
|
||||||
Note 1584 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been created
|
|
||||||
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
|
||||||
ENDS '1999-01-02 00:00:00' DISABLE
|
|
||||||
DO
|
|
||||||
SELECT 1;
|
|
||||||
Warnings:
|
|
||||||
Note 1584 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been created
|
|
||||||
CREATE EVENT e4 ON SCHEDULE AT '1999-01-01 00:00:00' DO
|
|
||||||
SELECT 1;
|
|
||||||
Warnings:
|
|
||||||
Note 1584 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been created
|
|
||||||
CREATE EVENT e4 ON SCHEDULE AT '1999-01-01 00:00:00' DISABLE
|
|
||||||
DO
|
|
||||||
SELECT 1;
|
|
||||||
Warnings:
|
|
||||||
Note 1584 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been created
|
|
||||||
SHOW EVENTS;
|
|
||||||
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator
|
|
||||||
mysqltest_db1 e1 root@localhost +05:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED 1
|
|
||||||
mysqltest_db1 e2 root@localhost -05:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED 1
|
|
||||||
mysqltest_db1 e3 root@localhost +00:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED 1
|
|
||||||
The following should succeed giving a warning.
|
|
||||||
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
|
||||||
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE;
|
|
||||||
Warnings:
|
|
||||||
Note 1533 Event execution time is in the past. Event has been disabled
|
|
||||||
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
|
||||||
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE
|
|
||||||
DO
|
|
||||||
SELECT 1;
|
|
||||||
Warnings:
|
|
||||||
Note 1533 Event execution time is in the past. Event has been disabled
|
|
||||||
CREATE EVENT e5 ON SCHEDULE AT '1999-01-01 00:00:00'
|
|
||||||
ON COMPLETION PRESERVE
|
|
||||||
DO
|
|
||||||
SELECT 1;
|
|
||||||
Warnings:
|
|
||||||
Note 1533 Event execution time is in the past. Event has been disabled
|
|
||||||
The following should succeed without warnings.
|
|
||||||
ALTER EVENT e2 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00';
|
|
||||||
ALTER EVENT e3 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
|
||||||
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE DISABLE;
|
|
||||||
CREATE EVENT e6 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00' DO
|
|
||||||
SELECT 1;
|
|
||||||
CREATE EVENT e7 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
|
||||||
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE DISABLE
|
|
||||||
DO
|
|
||||||
SELECT 1;
|
|
||||||
CREATE EVENT e8 ON SCHEDULE AT '1999-01-01 00:00:00'
|
|
||||||
ON COMPLETION PRESERVE DISABLE
|
|
||||||
DO
|
|
||||||
SELECT 1;
|
|
||||||
SHOW EVENTS;
|
|
||||||
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator
|
|
||||||
mysqltest_db1 e1 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 1999-01-02 00:00:00 DISABLED 1
|
|
||||||
mysqltest_db1 e2 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 NULL ENABLED 1
|
|
||||||
mysqltest_db1 e3 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 1999-01-02 00:00:00 DISABLED 1
|
|
||||||
mysqltest_db1 e4 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 1999-01-02 00:00:00 DISABLED 1
|
|
||||||
mysqltest_db1 e5 root@localhost +00:00 ONE TIME 1999-01-01 00:00:00 NULL NULL NULL NULL DISABLED 1
|
|
||||||
mysqltest_db1 e6 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 NULL ENABLED 1
|
|
||||||
mysqltest_db1 e7 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 1999-01-02 00:00:00 DISABLED 1
|
|
||||||
mysqltest_db1 e8 root@localhost +00:00 ONE TIME 1999-01-01 00:00:00 NULL NULL NULL NULL DISABLED 1
|
|
||||||
DROP EVENT e8;
|
|
||||||
DROP EVENT e7;
|
|
||||||
DROP EVENT e6;
|
|
||||||
DROP EVENT e5;
|
|
||||||
DROP EVENT e4;
|
|
||||||
DROP EVENT e3;
|
|
||||||
DROP EVENT e2;
|
|
||||||
DROP EVENT e1;
|
|
||||||
CREATE TABLE t_step (step INT);
|
CREATE TABLE t_step (step INT);
|
||||||
INSERT INTO t_step VALUES (@step);
|
INSERT INTO t_step VALUES (@step);
|
||||||
CREATE FUNCTION round_to_step(i INT, n INT) RETURNS INT
|
CREATE FUNCTION round_to_step(i INT, n INT) RETURNS INT
|
||||||
|
159
mysql-test/r/events_trans.result
Normal file
159
mysql-test/r/events_trans.result
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
drop database if exists events_test;
|
||||||
|
drop database if exists mysqltest_db2;
|
||||||
|
drop database if exists mysqltest_no_such_database;
|
||||||
|
create database events_test;
|
||||||
|
use events_test;
|
||||||
|
|
||||||
|
Test that Events DDL issue an implicit COMMIT
|
||||||
|
|
||||||
|
|
||||||
|
set autocommit=off;
|
||||||
|
select @@autocommit;
|
||||||
|
@@autocommit
|
||||||
|
0
|
||||||
|
create table t1 (a varchar(255)) engine=innodb;
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: create event");
|
||||||
|
create event e1 on schedule every 1 day do select 1;
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
a
|
||||||
|
OK: create event
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: alter event");
|
||||||
|
alter event e1 on schedule every 2 day do select 2;
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
a
|
||||||
|
OK: alter event
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: alter event rename");
|
||||||
|
alter event e1 rename to e2;
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
a
|
||||||
|
OK: alter event rename
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: drop event");
|
||||||
|
drop event e2;
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
a
|
||||||
|
OK: drop event
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: drop event if exists");
|
||||||
|
drop event if exists e2;
|
||||||
|
Warnings:
|
||||||
|
Note 1305 Event e2 does not exist
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
a
|
||||||
|
OK: drop event if exists
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
create event e1 on schedule every 1 day do select 1;
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: create event if not exists");
|
||||||
|
create event if not exists e1 on schedule every 2 day do select 2;
|
||||||
|
Warnings:
|
||||||
|
Note 1526 Event 'e1' already exists
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
a
|
||||||
|
OK: create event if not exists
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
|
||||||
|
Now check various error conditions: make sure we issue an
|
||||||
|
implicit commit anyway
|
||||||
|
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: create event: event already exists");
|
||||||
|
create event e1 on schedule every 2 day do select 2;
|
||||||
|
ERROR HY000: Event 'e1' already exists
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
a
|
||||||
|
OK: create event: event already exists
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: alter event rename: rename to same name");
|
||||||
|
alter event e1 rename to e1;
|
||||||
|
ERROR HY000: Same old and new event name
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
a
|
||||||
|
OK: alter event rename: rename to same name
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
create event e2 on schedule every 3 day do select 3;
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: alter event rename: destination exists");
|
||||||
|
alter event e2 rename to e1;
|
||||||
|
ERROR HY000: Event 'e1' already exists
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
a
|
||||||
|
OK: alter event rename: destination exists
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: create event: database does not exist");
|
||||||
|
create event mysqltest_no_such_database.e1 on schedule every 1 day do select 1;
|
||||||
|
ERROR 42000: Unknown database 'mysqltest_no_such_database'
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
a
|
||||||
|
OK: create event: database does not exist
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
grant create, insert, select, delete on mysqltest_db2.*
|
||||||
|
to mysqltest_user1@localhost;
|
||||||
|
create database mysqltest_db2;
|
||||||
|
set autocommit=off;
|
||||||
|
select @@autocommit;
|
||||||
|
@@autocommit
|
||||||
|
0
|
||||||
|
create table t1 (a varchar(255)) engine=innodb;
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: create event: insufficient privileges");
|
||||||
|
create event e1 on schedule every 1 day do select 1;
|
||||||
|
ERROR 42000: Access denied for user 'mysqltest_user1'@'localhost' to database 'mysqltest_db2'
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
a
|
||||||
|
OK: create event: insufficient privileges
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: alter event: insufficient privileges");
|
||||||
|
alter event e1 on schedule every 1 day do select 1;
|
||||||
|
ERROR 42000: Access denied for user 'mysqltest_user1'@'localhost' to database 'mysqltest_db2'
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
a
|
||||||
|
OK: alter event: insufficient privileges
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: drop event: insufficient privileges");
|
||||||
|
drop event e1;
|
||||||
|
ERROR 42000: Access denied for user 'mysqltest_user1'@'localhost' to database 'mysqltest_db2'
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
a
|
||||||
|
OK: drop event: insufficient privileges
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
drop user mysqltest_user1@localhost;
|
||||||
|
drop database mysqltest_db2;
|
||||||
|
drop database events_test;
|
@ -1,7 +1,13 @@
|
|||||||
# Can't test with embedded server that doesn't support grants
|
# Can't test with embedded server that doesn't support grants
|
||||||
-- source include/not_embedded.inc
|
-- source include/not_embedded.inc
|
||||||
|
|
||||||
create database if not exists events_test;
|
--disable_warnings
|
||||||
|
drop database if exists events_test;
|
||||||
|
drop database if exists db_x;
|
||||||
|
drop database if exists mysqltest_db2;
|
||||||
|
drop database if exists mysqltest_no_such_database;
|
||||||
|
--enable_warnings
|
||||||
|
create database events_test;
|
||||||
use events_test;
|
use events_test;
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -215,62 +221,161 @@ set names latin1;
|
|||||||
#
|
#
|
||||||
|
|
||||||
#
|
#
|
||||||
# mysql.event intact checking start
|
# mysql.event intact checking
|
||||||
|
# Check that the server does not crash if
|
||||||
|
# one has destroyed or tampered with the event table.
|
||||||
|
# Please see see for events_restart_phase* tests to
|
||||||
|
# see the server behavior at start up with bad mysql.event
|
||||||
|
# table.
|
||||||
#
|
#
|
||||||
# There should be at least 1 second between the ALTERs or we can't catch the change of create_time!!
|
#
|
||||||
|
--echo Create a test event. Only event metadata is relevant,
|
||||||
|
--echo the actual schedule and body are not.
|
||||||
#
|
#
|
||||||
CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing";
|
CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing";
|
||||||
--replace_column 8 # 9 #
|
--replace_column 8 # 9 #
|
||||||
SHOW EVENTS;
|
SHOW EVENTS;
|
||||||
ALTER TABLE mysql.event ADD dummy INT FIRST;
|
#
|
||||||
--error ER_COL_COUNT_DOESNT_MATCH_CORRUPTED
|
--echo Try to alter mysql.event: the server should fail to load
|
||||||
SHOW EVENTS;
|
--echo event information after mysql.event was tampered with.
|
||||||
ALTER TABLE mysql.event DROP dummy, ADD dummy2 VARCHAR(64) FIRST;
|
--echo
|
||||||
--error ER_COL_COUNT_DOESNT_MATCH_CORRUPTED
|
--echo First, let's add a column to the end and make sure everything
|
||||||
SHOW EVENTS;
|
--echo works as before
|
||||||
ALTER TABLE mysql.event DROP dummy2;
|
--echo
|
||||||
|
ALTER TABLE mysql.event ADD dummy INT;
|
||||||
--replace_column 8 # 9 #
|
--replace_column 8 # 9 #
|
||||||
SHOW EVENTS;
|
SHOW EVENTS;
|
||||||
|
SELECT event_name FROM INFORMATION_SCHEMA.events;
|
||||||
|
--replace_regex /STARTS '[^']+'/STARTS '#'/
|
||||||
|
SHOW CREATE EVENT intact_check;
|
||||||
|
--error ER_EVENT_DOES_NOT_EXIST
|
||||||
|
DROP EVENT no_such_event;
|
||||||
|
CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
|
||||||
|
ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
|
||||||
|
ALTER EVENT intact_check_1 RENAME TO intact_check_2;
|
||||||
|
--error ER_EVENT_DOES_NOT_EXIST
|
||||||
|
DROP EVENT intact_check_1;
|
||||||
|
DROP EVENT intact_check_2;
|
||||||
|
DROP EVENT intact_check;
|
||||||
|
DROP DATABASE IF EXISTS mysqltest_no_such_database;
|
||||||
|
CREATE DATABASE mysqltest_db2;
|
||||||
|
DROP DATABASE mysqltest_db2;
|
||||||
|
SELECT @@event_scheduler;
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
SET GLOBAL event_scheduler=OFF;
|
||||||
|
# Clean up
|
||||||
|
ALTER TABLE mysql.event DROP dummy;
|
||||||
|
CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing";
|
||||||
|
--echo
|
||||||
|
--echo Now let's add a column to the first position: the server
|
||||||
|
--echo expects to see event schema name there
|
||||||
|
--echo
|
||||||
|
ALTER TABLE mysql.event ADD dummy INT FIRST;
|
||||||
|
--error ER_CANNOT_LOAD_FROM_TABLE
|
||||||
|
SHOW EVENTS;
|
||||||
|
--error ER_CANNOT_LOAD_FROM_TABLE
|
||||||
|
SELECT event_name FROM INFORMATION_SCHEMA.events;
|
||||||
|
--error ER_EVENT_DOES_NOT_EXIST
|
||||||
|
SHOW CREATE EVENT intact_check;
|
||||||
|
--error ER_EVENT_DOES_NOT_EXIST
|
||||||
|
DROP EVENT no_such_event;
|
||||||
|
--error ER_CANNOT_LOAD_FROM_TABLE
|
||||||
|
CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
|
||||||
|
--error ER_EVENT_DOES_NOT_EXIST
|
||||||
|
ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
|
||||||
|
--error ER_EVENT_DOES_NOT_EXIST
|
||||||
|
ALTER EVENT intact_check_1 RENAME TO intact_check_2;
|
||||||
|
--error ER_EVENT_DOES_NOT_EXIST
|
||||||
|
DROP EVENT intact_check_1;
|
||||||
|
--error ER_EVENT_DOES_NOT_EXIST
|
||||||
|
DROP EVENT intact_check_2;
|
||||||
|
--error ER_EVENT_DOES_NOT_EXIST
|
||||||
|
DROP EVENT intact_check;
|
||||||
|
# Should work OK
|
||||||
|
DROP DATABASE IF EXISTS mysqltest_no_such_database;
|
||||||
|
CREATE DATABASE mysqltest_db2;
|
||||||
|
DROP DATABASE mysqltest_db2;
|
||||||
|
SELECT @@event_scheduler;
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
SET GLOBAL event_scheduler=OFF;
|
||||||
|
--echo Clean up
|
||||||
|
ALTER TABLE mysql.event DROP dummy;
|
||||||
|
DELETE FROM mysql.event;
|
||||||
|
CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing";
|
||||||
|
--echo Back up the table, further changes are not reversible
|
||||||
CREATE TABLE event_like LIKE mysql.event;
|
CREATE TABLE event_like LIKE mysql.event;
|
||||||
INSERT INTO event_like SELECT * FROM mysql.event;
|
INSERT INTO event_like SELECT * FROM mysql.event;
|
||||||
#sleep a bit or we won't catch the change of time
|
--echo
|
||||||
--sleep 1.1
|
--echo Drop some columns and try more checks.
|
||||||
ALTER TABLE mysql.event MODIFY db char(64) character set cp1251 default '';
|
--echo
|
||||||
--error ER_CANNOT_LOAD_FROM_TABLE
|
--echo
|
||||||
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
|
||||||
ALTER TABLE mysql.event MODIFY db char(20) character set utf8 collate utf8_bin default '';
|
|
||||||
#wait a bit or we won't see the difference because of seconds resolution
|
|
||||||
--sleep 1.1
|
|
||||||
SHOW CREATE TABLE mysql.event;
|
|
||||||
--error ER_CANNOT_LOAD_FROM_TABLE
|
|
||||||
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
|
||||||
--sleep 1.1
|
|
||||||
ALTER TABLE mysql.event MODIFY db char(64) character set utf8 collate utf8_bin default '';
|
|
||||||
--sleep 1.1
|
|
||||||
--echo "This should work"
|
|
||||||
--replace_column 8 # 9 #
|
|
||||||
SHOW EVENTS;
|
|
||||||
--sleep 1.1
|
|
||||||
ALTER TABLE mysql.event MODIFY db char(64) character set cp1251 default '';
|
|
||||||
--error ER_CANNOT_LOAD_FROM_TABLE
|
|
||||||
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
|
||||||
--sleep 1.1
|
|
||||||
ALTER TABLE mysql.event MODIFY db varchar(64) character set utf8 collate utf8_bin default '';
|
|
||||||
--sleep 1.1
|
|
||||||
--error ER_CANNOT_LOAD_FROM_TABLE
|
|
||||||
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
|
||||||
--sleep 1.1
|
|
||||||
ALTER TABLE mysql.event DROP comment, DROP starts;
|
ALTER TABLE mysql.event DROP comment, DROP starts;
|
||||||
--sleep 1.1
|
--error ER_CANNOT_LOAD_FROM_TABLE
|
||||||
--error ER_COL_COUNT_DOESNT_MATCH_CORRUPTED
|
SHOW EVENTS;
|
||||||
|
--error ER_CANNOT_LOAD_FROM_TABLE
|
||||||
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
||||||
|
--error ER_CANNOT_LOAD_FROM_TABLE
|
||||||
|
SHOW CREATE EVENT intact_check;
|
||||||
|
--error ER_EVENT_DOES_NOT_EXIST
|
||||||
|
DROP EVENT no_such_event;
|
||||||
|
--error ER_COL_COUNT_DOESNT_MATCH_CORRUPTED
|
||||||
|
CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
|
||||||
|
--error ER_EVENT_DOES_NOT_EXIST
|
||||||
|
ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
|
||||||
|
--error ER_EVENT_DOES_NOT_EXIST
|
||||||
|
ALTER EVENT intact_check_1 RENAME TO intact_check_2;
|
||||||
|
--error ER_EVENT_DOES_NOT_EXIST
|
||||||
|
DROP EVENT intact_check_1;
|
||||||
|
--error ER_EVENT_DOES_NOT_EXIST
|
||||||
|
DROP EVENT intact_check_2;
|
||||||
|
# Should succeed
|
||||||
|
DROP EVENT intact_check;
|
||||||
|
DROP DATABASE IF EXISTS mysqltest_no_such_database;
|
||||||
|
CREATE DATABASE mysqltest_db2;
|
||||||
|
DROP DATABASE mysqltest_db2;
|
||||||
|
SELECT @@event_scheduler;
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
SET GLOBAL event_scheduler=OFF;
|
||||||
|
--echo
|
||||||
|
--echo Now drop the table, and test again
|
||||||
|
--echo
|
||||||
|
--echo
|
||||||
DROP TABLE mysql.event;
|
DROP TABLE mysql.event;
|
||||||
|
--error ER_NO_SUCH_TABLE
|
||||||
|
SHOW EVENTS;
|
||||||
|
--error ER_NO_SUCH_TABLE
|
||||||
|
SELECT event_name FROM INFORMATION_SCHEMA.events;
|
||||||
|
--error ER_NO_SUCH_TABLE
|
||||||
|
SHOW CREATE EVENT intact_check;
|
||||||
|
--error ER_NO_SUCH_TABLE
|
||||||
|
DROP EVENT no_such_event;
|
||||||
|
--error ER_NO_SUCH_TABLE
|
||||||
|
CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
|
||||||
|
--error ER_NO_SUCH_TABLE
|
||||||
|
ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
|
||||||
|
--error ER_NO_SUCH_TABLE
|
||||||
|
ALTER EVENT intact_check_1 RENAME TO intact_check_2;
|
||||||
|
--error ER_NO_SUCH_TABLE
|
||||||
|
DROP EVENT intact_check_1;
|
||||||
|
--error ER_NO_SUCH_TABLE
|
||||||
|
DROP EVENT intact_check_2;
|
||||||
|
--error ER_NO_SUCH_TABLE
|
||||||
|
DROP EVENT intact_check;
|
||||||
|
DROP DATABASE IF EXISTS mysqltest_no_such_database;
|
||||||
|
CREATE DATABASE mysqltest_db2;
|
||||||
|
DROP DATABASE mysqltest_db2;
|
||||||
|
--echo OK, there is an unnecessary warning about the non-existent table
|
||||||
|
--echo but it's not easy to fix and no one complained about it.
|
||||||
|
--echo A similar warning is printed if mysql.proc is missing.
|
||||||
|
SHOW WARNINGS;
|
||||||
|
SELECT @@event_scheduler;
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
SET GLOBAL event_scheduler=OFF;
|
||||||
|
--echo Restore the original table.
|
||||||
CREATE TABLE mysql.event like event_like;
|
CREATE TABLE mysql.event like event_like;
|
||||||
INSERT INTO mysql.event SELECT * FROM event_like;
|
|
||||||
DROP TABLE event_like;
|
DROP TABLE event_like;
|
||||||
--replace_column 8 # 9 #
|
--replace_column 8 # 9 #
|
||||||
SHOW EVENTS;
|
SHOW EVENTS;
|
||||||
DROP EVENT intact_check;
|
|
||||||
#
|
#
|
||||||
# mysql.event intact checking end
|
# mysql.event intact checking end
|
||||||
#
|
#
|
||||||
@ -424,5 +529,200 @@ SHOW EVENTS FROM aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
|||||||
SHOW EVENTS FROM ``;
|
SHOW EVENTS FROM ``;
|
||||||
|
|
||||||
SHOW EVENTS FROM `events\\test`;
|
SHOW EVENTS FROM `events\\test`;
|
||||||
|
#
|
||||||
|
# A check for events SQL under LOCK TABLES and in pre-locked mode.
|
||||||
|
#
|
||||||
|
--echo
|
||||||
|
--echo LOCK TABLES mode.
|
||||||
|
--echo
|
||||||
|
#
|
||||||
|
# SHOW CREATE EVENT and INFORMATION_SCHEMA.events are available and
|
||||||
|
# cause an implicit lock/unlock of mysql.event table, regardless of the
|
||||||
|
# currently locked tables.
|
||||||
|
#
|
||||||
|
create table t1 (a int);
|
||||||
|
create event e1 on schedule every 10 hour do select 1;
|
||||||
|
#
|
||||||
|
lock table t1 read;
|
||||||
|
#
|
||||||
|
--replace_regex /STARTS '[^']+'/STARTS '#'/
|
||||||
|
show create event e1;
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
--error ER_TABLE_NOT_LOCKED
|
||||||
|
create event e2 on schedule every 10 hour do select 1;
|
||||||
|
--error ER_TABLE_NOT_LOCKED
|
||||||
|
alter event e2 disable;
|
||||||
|
--error ER_TABLE_NOT_LOCKED
|
||||||
|
alter event e2 rename to e3;
|
||||||
|
--error ER_TABLE_NOT_LOCKED
|
||||||
|
drop event e2;
|
||||||
|
--error ER_TABLE_NOT_LOCKED
|
||||||
|
drop event e1;
|
||||||
|
unlock tables;
|
||||||
|
#
|
||||||
|
lock table t1 write;
|
||||||
|
#
|
||||||
|
--replace_regex /STARTS '[^']+'/STARTS '#'/
|
||||||
|
show create event e1;
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
--error ER_TABLE_NOT_LOCKED
|
||||||
|
create event e2 on schedule every 10 hour do select 1;
|
||||||
|
--error ER_TABLE_NOT_LOCKED
|
||||||
|
alter event e2 disable;
|
||||||
|
--error ER_TABLE_NOT_LOCKED
|
||||||
|
alter event e2 rename to e3;
|
||||||
|
--error ER_TABLE_NOT_LOCKED
|
||||||
|
drop event e2;
|
||||||
|
--error ER_TABLE_NOT_LOCKED
|
||||||
|
drop event e1;
|
||||||
|
unlock tables;
|
||||||
|
#
|
||||||
|
lock table t1 read, mysql.event read;
|
||||||
|
#
|
||||||
|
--replace_regex /STARTS '[^']+'/STARTS '#'/
|
||||||
|
show create event e1;
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
|
||||||
|
create event e2 on schedule every 10 hour do select 1;
|
||||||
|
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
|
||||||
|
alter event e2 disable;
|
||||||
|
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
|
||||||
|
alter event e2 rename to e3;
|
||||||
|
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
|
||||||
|
drop event e2;
|
||||||
|
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
|
||||||
|
drop event e1;
|
||||||
|
unlock tables;
|
||||||
|
#
|
||||||
|
lock table t1 write, mysql.event read;
|
||||||
|
#
|
||||||
|
--replace_regex /STARTS '[^']+'/STARTS '#'/
|
||||||
|
show create event e1;
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
|
||||||
|
create event e2 on schedule every 10 hour do select 1;
|
||||||
|
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
|
||||||
|
alter event e2 disable;
|
||||||
|
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
|
||||||
|
alter event e2 rename to e3;
|
||||||
|
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
|
||||||
|
drop event e2;
|
||||||
|
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
|
||||||
|
drop event e1;
|
||||||
|
unlock tables;
|
||||||
|
#
|
||||||
|
--error ER_WRONG_LOCK_OF_SYSTEM_TABLE
|
||||||
|
lock table t1 read, mysql.event write;
|
||||||
|
#
|
||||||
|
--error ER_WRONG_LOCK_OF_SYSTEM_TABLE
|
||||||
|
lock table t1 write, mysql.event write;
|
||||||
|
#
|
||||||
|
lock table mysql.event write;
|
||||||
|
--replace_regex /STARTS '[^']+'/STARTS '#'/
|
||||||
|
show create event e1;
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
create event e2 on schedule every 10 hour do select 1;
|
||||||
|
alter event e2 disable;
|
||||||
|
alter event e2 rename to e3;
|
||||||
|
drop event e3;
|
||||||
|
drop event e1;
|
||||||
|
unlock tables;
|
||||||
|
--echo Make sure we have left no events
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
--echo
|
||||||
|
--echo Events in sub-statements, events and prelocking
|
||||||
|
--echo
|
||||||
|
--echo
|
||||||
|
create event e1 on schedule every 10 hour do select 1;
|
||||||
|
delimiter |;
|
||||||
|
--error ER_SP_NO_RETSET
|
||||||
|
create function f1() returns int
|
||||||
|
begin
|
||||||
|
show create event e1;
|
||||||
|
return 1;
|
||||||
|
end|
|
||||||
|
--error ER_SP_NO_RETSET
|
||||||
|
create trigger trg before insert on t1 for each row
|
||||||
|
begin
|
||||||
|
show create event e1;
|
||||||
|
end|
|
||||||
|
--error ER_SP_NO_RETSET
|
||||||
|
create function f1() returns int
|
||||||
|
begin
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
return 1;
|
||||||
|
end|
|
||||||
|
--error ER_SP_NO_RETSET
|
||||||
|
create trigger trg before insert on t1 for each row
|
||||||
|
begin
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
end|
|
||||||
|
--error ER_EVENT_RECURSION_FORBIDDEN
|
||||||
|
create function f1() returns int
|
||||||
|
begin
|
||||||
|
create event e2 on schedule every 10 hour do select 1;
|
||||||
|
return 1;
|
||||||
|
end|
|
||||||
|
--error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
|
||||||
|
create function f1() returns int
|
||||||
|
begin
|
||||||
|
alter event e1 rename to e2;
|
||||||
|
return 1;
|
||||||
|
end|
|
||||||
|
--error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
|
||||||
|
create function f1() returns int
|
||||||
|
begin
|
||||||
|
drop event e2;
|
||||||
|
return 1;
|
||||||
|
end|
|
||||||
|
--echo ----------------------------------------------------------------------
|
||||||
|
create trigger trg before insert on t1 for each row
|
||||||
|
begin
|
||||||
|
set new.a= f1();
|
||||||
|
end|
|
||||||
|
create function f1() returns int
|
||||||
|
begin
|
||||||
|
call p1();
|
||||||
|
return 0;
|
||||||
|
end|
|
||||||
|
create procedure p1()
|
||||||
|
begin
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
end|
|
||||||
|
--error ER_SP_NO_RETSET
|
||||||
|
insert into t1 (a) values (1)|
|
||||||
|
drop procedure p1|
|
||||||
|
create procedure p1()
|
||||||
|
begin
|
||||||
|
show create event e1;
|
||||||
|
end|
|
||||||
|
--error ER_SP_NO_RETSET
|
||||||
|
insert into t1 (a) values (1)|
|
||||||
|
drop procedure p1|
|
||||||
|
create procedure p1()
|
||||||
|
begin
|
||||||
|
create temporary table tmp select event_name from information_schema.events;
|
||||||
|
end|
|
||||||
|
--echo expected to work, since we redirect the output into a tmp table
|
||||||
|
insert into t1 (a) values (1)|
|
||||||
|
select * from tmp|
|
||||||
|
drop temporary table tmp|
|
||||||
|
drop procedure p1|
|
||||||
|
create procedure p1()
|
||||||
|
begin
|
||||||
|
alter event e1 rename to e2;
|
||||||
|
end|
|
||||||
|
--error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
|
||||||
|
insert into t1 (a) values (1)|
|
||||||
|
drop procedure p1|
|
||||||
|
create procedure p1()
|
||||||
|
begin
|
||||||
|
drop event e1;
|
||||||
|
end|
|
||||||
|
--error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
|
||||||
|
insert into t1 (a) values (1)|
|
||||||
|
drop table t1|
|
||||||
|
drop event e1|
|
||||||
|
delimiter ;|
|
||||||
|
|
||||||
drop database events_test;
|
drop database events_test;
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
# Can't test with embedded server that doesn't support grants
|
# Can't test with embedded server that doesn't support grants
|
||||||
-- source include/not_embedded.inc
|
-- source include/not_embedded.inc
|
||||||
|
|
||||||
create database if not exists events_test;
|
--disable_warnings
|
||||||
|
drop database if exists events_test;
|
||||||
|
drop database if exists mysqltest_db1;
|
||||||
|
drop database if exists mysqltest_db2;
|
||||||
|
--enable_warnings
|
||||||
|
create database events_test;
|
||||||
use events_test;
|
use events_test;
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -429,6 +434,184 @@ DROP USER mysqltest_u1@localhost;
|
|||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
# BUG#16420: Events: timestamps become UTC
|
||||||
|
# BUG#26429: SHOW CREATE EVENT is incorrect for an event that
|
||||||
|
# STARTS NOW()
|
||||||
|
# BUG#26431: Impossible to re-create an event from backup if its
|
||||||
|
# STARTS clause is in the past
|
||||||
|
# WL#3698: Events: execution in local time zone
|
||||||
|
#
|
||||||
|
# Here we only check non-concurrent aspects of the patch.
|
||||||
|
# For the actual tests of time zones please see events_time_zone.test
|
||||||
|
#
|
||||||
|
SET GLOBAL EVENT_SCHEDULER= OFF;
|
||||||
|
SET @save_time_zone= @@TIME_ZONE;
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
# We will use a separate connection because SET TIMESTAMP will stop
|
||||||
|
# the clock in that connection.
|
||||||
|
|
||||||
|
SET TIME_ZONE= '+00:00';
|
||||||
|
SET TIMESTAMP= UNIX_TIMESTAMP('2005-12-31 23:58:59');
|
||||||
|
|
||||||
|
|
||||||
|
# Test when event time zone is updated on ALTER EVENT.
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
|
||||||
|
SHOW EVENTS;
|
||||||
|
|
||||||
|
# Test storing and updating of the event time zone.
|
||||||
|
#
|
||||||
|
SET TIME_ZONE= '-01:00';
|
||||||
|
ALTER EVENT e1 ON SCHEDULE EVERY 1 DAY STARTS '2000-01-01 00:00:00';
|
||||||
|
SHOW EVENTS;
|
||||||
|
|
||||||
|
# This will update event time zone.
|
||||||
|
SET TIME_ZONE= '+02:00';
|
||||||
|
ALTER EVENT e1 ON SCHEDULE AT '2000-01-02 00:00:00'
|
||||||
|
ON COMPLETION PRESERVE DISABLE;
|
||||||
|
SHOW EVENTS;
|
||||||
|
|
||||||
|
# This will update event time zone.
|
||||||
|
SET TIME_ZONE= '-03:00';
|
||||||
|
ALTER EVENT e1 ON SCHEDULE EVERY 1 DAY ENDS '2030-01-03 00:00:00'
|
||||||
|
ON COMPLETION PRESERVE DISABLE;
|
||||||
|
SHOW EVENTS;
|
||||||
|
|
||||||
|
# This will not update event time zone, as no time is being adjusted.
|
||||||
|
SET TIME_ZONE= '+04:00';
|
||||||
|
ALTER EVENT e1 DO SELECT 2;
|
||||||
|
SHOW EVENTS;
|
||||||
|
|
||||||
|
DROP EVENT e1;
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Create some events.
|
||||||
|
SET TIME_ZONE='+05:00';
|
||||||
|
CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
|
||||||
|
SELECT 1;
|
||||||
|
|
||||||
|
SET TIMESTAMP= @@TIMESTAMP + 1;
|
||||||
|
|
||||||
|
SET TIME_ZONE='-05:00';
|
||||||
|
CREATE EVENT e2 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
|
||||||
|
SELECT 1;
|
||||||
|
|
||||||
|
SET TIMESTAMP= @@TIMESTAMP + 1;
|
||||||
|
|
||||||
|
SET TIME_ZONE='+00:00';
|
||||||
|
CREATE EVENT e3 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
|
||||||
|
SELECT 1;
|
||||||
|
|
||||||
|
|
||||||
|
# Test INFORMATION_SCHEMA.EVENTS.
|
||||||
|
#
|
||||||
|
|
||||||
|
SELECT * FROM INFORMATION_SCHEMA.EVENTS ORDER BY event_name;
|
||||||
|
|
||||||
|
|
||||||
|
# Test SHOW EVENTS.
|
||||||
|
#
|
||||||
|
|
||||||
|
SHOW EVENTS;
|
||||||
|
|
||||||
|
|
||||||
|
# Test SHOW CREATE EVENT.
|
||||||
|
#
|
||||||
|
|
||||||
|
SHOW CREATE EVENT e1;
|
||||||
|
SHOW CREATE EVENT e2;
|
||||||
|
SHOW CREATE EVENT e3;
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Test times in the past.
|
||||||
|
#
|
||||||
|
|
||||||
|
--echo The following should fail, and nothing should be altered.
|
||||||
|
|
||||||
|
--error ER_EVENT_CANNOT_ALTER_IN_THE_PAST
|
||||||
|
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||||
|
ENDS '1999-01-02 00:00:00';
|
||||||
|
|
||||||
|
--error ER_EVENT_CANNOT_ALTER_IN_THE_PAST
|
||||||
|
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||||
|
ENDS '1999-01-02 00:00:00' DISABLE;
|
||||||
|
|
||||||
|
--echo The following should give warnings, and nothing should be created.
|
||||||
|
|
||||||
|
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||||
|
ENDS '1999-01-02 00:00:00'
|
||||||
|
DO
|
||||||
|
SELECT 1;
|
||||||
|
|
||||||
|
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||||
|
ENDS '1999-01-02 00:00:00' DISABLE
|
||||||
|
DO
|
||||||
|
SELECT 1;
|
||||||
|
|
||||||
|
CREATE EVENT e4 ON SCHEDULE AT '1999-01-01 00:00:00' DO
|
||||||
|
SELECT 1;
|
||||||
|
|
||||||
|
CREATE EVENT e4 ON SCHEDULE AT '1999-01-01 00:00:00' DISABLE
|
||||||
|
DO
|
||||||
|
SELECT 1;
|
||||||
|
|
||||||
|
SHOW EVENTS;
|
||||||
|
|
||||||
|
--echo The following should succeed giving a warning.
|
||||||
|
|
||||||
|
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||||
|
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE;
|
||||||
|
|
||||||
|
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||||
|
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE
|
||||||
|
DO
|
||||||
|
SELECT 1;
|
||||||
|
|
||||||
|
CREATE EVENT e5 ON SCHEDULE AT '1999-01-01 00:00:00'
|
||||||
|
ON COMPLETION PRESERVE
|
||||||
|
DO
|
||||||
|
SELECT 1;
|
||||||
|
|
||||||
|
--echo The following should succeed without warnings.
|
||||||
|
|
||||||
|
ALTER EVENT e2 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00';
|
||||||
|
|
||||||
|
ALTER EVENT e3 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||||
|
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE DISABLE;
|
||||||
|
|
||||||
|
CREATE EVENT e6 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00' DO
|
||||||
|
SELECT 1;
|
||||||
|
|
||||||
|
CREATE EVENT e7 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
||||||
|
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE DISABLE
|
||||||
|
DO
|
||||||
|
SELECT 1;
|
||||||
|
|
||||||
|
CREATE EVENT e8 ON SCHEDULE AT '1999-01-01 00:00:00'
|
||||||
|
ON COMPLETION PRESERVE DISABLE
|
||||||
|
DO
|
||||||
|
SELECT 1;
|
||||||
|
|
||||||
|
SHOW EVENTS;
|
||||||
|
|
||||||
|
|
||||||
|
DROP EVENT e8;
|
||||||
|
DROP EVENT e7;
|
||||||
|
DROP EVENT e6;
|
||||||
|
DROP EVENT e5;
|
||||||
|
DROP EVENT e4;
|
||||||
|
DROP EVENT e3;
|
||||||
|
DROP EVENT e2;
|
||||||
|
DROP EVENT e1;
|
||||||
|
|
||||||
|
SET TIME_ZONE=@save_time_zone;
|
||||||
|
|
||||||
|
#
|
||||||
# End of tests
|
# End of tests
|
||||||
#
|
#
|
||||||
drop database events_test;
|
drop database events_test;
|
||||||
|
@ -1,19 +1,43 @@
|
|||||||
# Can't test with embedded server that doesn't support grants
|
# Can't test with embedded server that doesn't support grants
|
||||||
-- source include/not_embedded.inc
|
-- source include/not_embedded.inc
|
||||||
|
#
|
||||||
|
# Test that when the server is restarted, it checks mysql.event table,
|
||||||
|
# and disables the scheduler if it's not up to date.
|
||||||
|
#
|
||||||
|
|
||||||
|
# Switch off the scheduler for now.
|
||||||
|
set global event_scheduler=off;
|
||||||
|
|
||||||
--disable_warnings
|
--disable_warnings
|
||||||
create database if not exists mysqltest_events_test;
|
drop database if exists events_test;
|
||||||
--enable_warnings
|
--enable_warnings
|
||||||
|
create database events_test;
|
||||||
use mysqltest_events_test;
|
use events_test;
|
||||||
set global event_scheduler=off;
|
|
||||||
create table execution_log(name char(10));
|
create table execution_log(name char(10));
|
||||||
create event abc1 on schedule every 1 second do insert into execution_log value('abc1');
|
|
||||||
create event abc2 on schedule every 1 second do insert into execution_log value('abc2');
|
|
||||||
create event abc3 on schedule every 1 second do insert into execution_log value('abc3');
|
|
||||||
--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',1,'SYSTEM');
|
create event abc1 on schedule every 1 second do
|
||||||
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,'SYSTEM');
|
insert into execution_log value('abc1');
|
||||||
|
create event abc2 on schedule every 1 second do
|
||||||
|
insert into execution_log value('abc2');
|
||||||
|
create event abc3 on schedule every 1 second do
|
||||||
|
insert into execution_log value('abc3');
|
||||||
|
#
|
||||||
|
# There are various conditions when a server would regard mysql.event
|
||||||
|
# table as damaged:
|
||||||
|
# - the table has more column than specified in the compiled in value, but
|
||||||
|
# the version of the server which created the table is the same
|
||||||
|
# - the column count in the table is less than the compiled in value
|
||||||
|
# - some column has an incompatible type specification (for what is an
|
||||||
|
# incompatible type specification please refer to the comments in the source
|
||||||
|
#
|
||||||
|
# Unfortunately, in order to test a condition, we need to restart the
|
||||||
|
# server. Therefore, here we test only one simple case: changing the data
|
||||||
|
# type of the 'body' field to blob.
|
||||||
|
#
|
||||||
|
# First, let's do a backup to not depend on actual definition of mysql.event
|
||||||
|
create table event_like like mysql.event;
|
||||||
|
insert into event_like select * from mysql.event;
|
||||||
|
# Now let's alter the table and restart the server
|
||||||
|
alter table mysql.event
|
||||||
|
change column body body longtext character set utf8 collate utf8_bin;
|
||||||
--echo "Now we restart the server"
|
--echo "Now we restart the server"
|
||||||
|
@ -1,9 +1,41 @@
|
|||||||
# Can't test with embedded server that doesn't support grants
|
# Can't test with embedded server that doesn't support grants
|
||||||
-- source include/not_embedded.inc
|
-- source include/not_embedded.inc
|
||||||
|
|
||||||
use mysqltest_events_test;
|
use events_test;
|
||||||
--sleep 1.5
|
# Event scheduler should be disabled: the system tables are damaged
|
||||||
--echo "Should get 0 rows because the queue aborted run
|
select @@event_scheduler;
|
||||||
select distinct name from execution_log order by name;
|
# Try various Event Scheduler operation and check the output.
|
||||||
delete from mysql.event where name like 'bad%';
|
--error ER_EVENTS_DB_ERROR
|
||||||
--echo "Now restart the server again"
|
show events;
|
||||||
|
--error ER_EVENTS_DB_ERROR
|
||||||
|
select event_name from information_schema.events;
|
||||||
|
--error ER_EVENTS_DB_ERROR
|
||||||
|
show create event intact_check;
|
||||||
|
--error ER_EVENTS_DB_ERROR
|
||||||
|
drop event no_such_event;
|
||||||
|
--error ER_EVENTS_DB_ERROR
|
||||||
|
create event intact_check_1 on schedule every 5 hour do select 5;
|
||||||
|
--error ER_EVENTS_DB_ERROR
|
||||||
|
alter event intact_check_1 on schedule every 8 hour do select 8;
|
||||||
|
--error ER_EVENTS_DB_ERROR
|
||||||
|
alter event intact_check_1 rename to intact_check_2;
|
||||||
|
--error ER_EVENTS_DB_ERROR
|
||||||
|
drop event intact_check_1;
|
||||||
|
--error ER_EVENTS_DB_ERROR
|
||||||
|
drop event intact_check_2;
|
||||||
|
--error ER_EVENTS_DB_ERROR
|
||||||
|
drop event intact_check;
|
||||||
|
--error ER_EVENTS_DB_ERROR
|
||||||
|
set global event_scheduler=on;
|
||||||
|
--error ER_EVENTS_DB_ERROR
|
||||||
|
set global event_scheduler=off;
|
||||||
|
show variables like 'event_scheduler';
|
||||||
|
--echo Make sure that we still can create and drop databases,
|
||||||
|
--echo and no warnings are produced.
|
||||||
|
drop database if exists mysqltest_database_not_exists;
|
||||||
|
create database mysqltest_db1;
|
||||||
|
drop database mysqltest_db1;
|
||||||
|
--echo Restore the original mysql.event table
|
||||||
|
drop table mysql.event;
|
||||||
|
rename table event_like to mysql.event;
|
||||||
|
--echo Now let's restart the server again
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
# Can't test with embedded server that doesn't support grants
|
# Can't test with embedded server that doesn't support grants
|
||||||
-- source include/not_embedded.inc
|
-- source include/not_embedded.inc
|
||||||
|
#
|
||||||
use mysqltest_events_test;
|
# We need this file primarily to make sure that the scheduler is restarted
|
||||||
--sleep 2
|
# and enabled after we have restored mysql.event table.
|
||||||
|
# This is the final step of the "cleanup".
|
||||||
|
#
|
||||||
|
# Make sure also that events are executed OK after restart, just in case.
|
||||||
|
use events_test;
|
||||||
|
# Make sure the scheduler was started successfully
|
||||||
|
select @@event_scheduler;
|
||||||
|
let $wait_condition=select count(distinct name)=3 from execution_log;
|
||||||
|
--source include/wait_condition.inc
|
||||||
--echo "Should get 3 rows : abc1, abc2, abc3
|
--echo "Should get 3 rows : abc1, abc2, abc3
|
||||||
select distinct name from execution_log order by name;
|
select distinct name from execution_log order by name;
|
||||||
|
|
||||||
drop event abc1;
|
|
||||||
drop event abc2;
|
|
||||||
drop event abc3;
|
|
||||||
drop table execution_log;
|
drop table execution_log;
|
||||||
|
# Will drop all events
|
||||||
drop database mysqltest_events_test;
|
drop database events_test;
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
CREATE DATABASE IF NOT EXISTS events_test;
|
CREATE DATABASE IF NOT EXISTS events_test;
|
||||||
USE events_test;
|
USE events_test;
|
||||||
|
|
||||||
|
SET GLOBAL event_scheduler=OFF;
|
||||||
|
--echo Try agian to make sure it's allowed
|
||||||
SET GLOBAL event_scheduler=OFF;
|
SET GLOBAL event_scheduler=OFF;
|
||||||
SHOW VARIABLES LIKE 'event_scheduler';
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
SET GLOBAL event_scheduler=1;
|
SET GLOBAL event_scheduler=1;
|
||||||
@ -12,6 +14,8 @@ SHOW VARIABLES LIKE 'event_scheduler';
|
|||||||
SET GLOBAL event_scheduler=0;
|
SET GLOBAL event_scheduler=0;
|
||||||
SHOW VARIABLES LIKE 'event_scheduler';
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
SET GLOBAL event_scheduler=ON;
|
SET GLOBAL event_scheduler=ON;
|
||||||
|
--echo Try again to make sure it's allowed
|
||||||
|
SET GLOBAL event_scheduler=ON;
|
||||||
SHOW VARIABLES LIKE 'event_scheduler';
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
--error ER_WRONG_VALUE_FOR_VAR
|
--error ER_WRONG_VALUE_FOR_VAR
|
||||||
SET GLOBAL event_scheduler=DISABLED;
|
SET GLOBAL event_scheduler=DISABLED;
|
||||||
|
@ -20,6 +20,7 @@ let $old_db= `SELECT DATABASE()`;
|
|||||||
USE mysqltest_db1;
|
USE mysqltest_db1;
|
||||||
|
|
||||||
SET GLOBAL EVENT_SCHEDULER= OFF;
|
SET GLOBAL EVENT_SCHEDULER= OFF;
|
||||||
|
SET @save_time_zone= @@TIME_ZONE;
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -31,176 +32,6 @@ SET GLOBAL EVENT_SCHEDULER= OFF;
|
|||||||
# WL#3698: Events: execution in local time zone
|
# WL#3698: Events: execution in local time zone
|
||||||
#
|
#
|
||||||
|
|
||||||
SET @save_time_zone= @@TIME_ZONE;
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
|
|
||||||
# We will use a separate connection because SET TIMESTAMP will stop
|
|
||||||
# the clock in that connection.
|
|
||||||
|
|
||||||
connect (conn1, localhost, root, , mysqltest_db1);
|
|
||||||
|
|
||||||
SET TIME_ZONE= '+00:00';
|
|
||||||
SET TIMESTAMP= UNIX_TIMESTAMP('2005-12-31 23:58:59');
|
|
||||||
|
|
||||||
|
|
||||||
# Test when event time zone is updated on ALTER EVENT.
|
|
||||||
#
|
|
||||||
|
|
||||||
CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
|
|
||||||
SHOW EVENTS;
|
|
||||||
|
|
||||||
# Test storing and updating of the event time zone.
|
|
||||||
#
|
|
||||||
SET TIME_ZONE= '-01:00';
|
|
||||||
ALTER EVENT e1 ON SCHEDULE EVERY 1 DAY STARTS '2000-01-01 00:00:00';
|
|
||||||
SHOW EVENTS;
|
|
||||||
|
|
||||||
# This will update event time zone.
|
|
||||||
SET TIME_ZONE= '+02:00';
|
|
||||||
ALTER EVENT e1 ON SCHEDULE AT '2000-01-02 00:00:00'
|
|
||||||
ON COMPLETION PRESERVE DISABLE;
|
|
||||||
SHOW EVENTS;
|
|
||||||
|
|
||||||
# This will update event time zone.
|
|
||||||
SET TIME_ZONE= '-03:00';
|
|
||||||
ALTER EVENT e1 ON SCHEDULE EVERY 1 DAY ENDS '2030-01-03 00:00:00'
|
|
||||||
ON COMPLETION PRESERVE DISABLE;
|
|
||||||
SHOW EVENTS;
|
|
||||||
|
|
||||||
# This will not update event time zone, as no time is being adjusted.
|
|
||||||
SET TIME_ZONE= '+04:00';
|
|
||||||
ALTER EVENT e1 DO SELECT 2;
|
|
||||||
SHOW EVENTS;
|
|
||||||
|
|
||||||
DROP EVENT e1;
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
|
|
||||||
# Create some events.
|
|
||||||
SET TIME_ZONE='+05:00';
|
|
||||||
CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
|
|
||||||
SELECT 1;
|
|
||||||
|
|
||||||
SET TIMESTAMP= @@TIMESTAMP + 1;
|
|
||||||
|
|
||||||
SET TIME_ZONE='-05:00';
|
|
||||||
CREATE EVENT e2 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
|
|
||||||
SELECT 1;
|
|
||||||
|
|
||||||
SET TIMESTAMP= @@TIMESTAMP + 1;
|
|
||||||
|
|
||||||
SET TIME_ZONE='+00:00';
|
|
||||||
CREATE EVENT e3 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
|
|
||||||
SELECT 1;
|
|
||||||
|
|
||||||
|
|
||||||
# Test INFORMATION_SCHEMA.EVENTS.
|
|
||||||
#
|
|
||||||
|
|
||||||
SELECT * FROM INFORMATION_SCHEMA.EVENTS;
|
|
||||||
|
|
||||||
|
|
||||||
# Test SHOW EVENTS.
|
|
||||||
#
|
|
||||||
|
|
||||||
SHOW EVENTS;
|
|
||||||
|
|
||||||
|
|
||||||
# Test SHOW CREATE EVENT.
|
|
||||||
#
|
|
||||||
|
|
||||||
SHOW CREATE EVENT e1;
|
|
||||||
SHOW CREATE EVENT e2;
|
|
||||||
SHOW CREATE EVENT e3;
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
|
|
||||||
# Test times in the past.
|
|
||||||
#
|
|
||||||
|
|
||||||
--echo The following should fail, and nothing should be altered.
|
|
||||||
|
|
||||||
--error ER_EVENT_CANNOT_ALTER_IN_THE_PAST
|
|
||||||
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
|
||||||
ENDS '1999-01-02 00:00:00';
|
|
||||||
|
|
||||||
--error ER_EVENT_CANNOT_ALTER_IN_THE_PAST
|
|
||||||
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
|
||||||
ENDS '1999-01-02 00:00:00' DISABLE;
|
|
||||||
|
|
||||||
--echo The following should give warnings, and nothing should be created.
|
|
||||||
|
|
||||||
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
|
||||||
ENDS '1999-01-02 00:00:00'
|
|
||||||
DO
|
|
||||||
SELECT 1;
|
|
||||||
|
|
||||||
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
|
||||||
ENDS '1999-01-02 00:00:00' DISABLE
|
|
||||||
DO
|
|
||||||
SELECT 1;
|
|
||||||
|
|
||||||
CREATE EVENT e4 ON SCHEDULE AT '1999-01-01 00:00:00' DO
|
|
||||||
SELECT 1;
|
|
||||||
|
|
||||||
CREATE EVENT e4 ON SCHEDULE AT '1999-01-01 00:00:00' DISABLE
|
|
||||||
DO
|
|
||||||
SELECT 1;
|
|
||||||
|
|
||||||
SHOW EVENTS;
|
|
||||||
|
|
||||||
--echo The following should succeed giving a warning.
|
|
||||||
|
|
||||||
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
|
||||||
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE;
|
|
||||||
|
|
||||||
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
|
||||||
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE
|
|
||||||
DO
|
|
||||||
SELECT 1;
|
|
||||||
|
|
||||||
CREATE EVENT e5 ON SCHEDULE AT '1999-01-01 00:00:00'
|
|
||||||
ON COMPLETION PRESERVE
|
|
||||||
DO
|
|
||||||
SELECT 1;
|
|
||||||
|
|
||||||
--echo The following should succeed without warnings.
|
|
||||||
|
|
||||||
ALTER EVENT e2 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00';
|
|
||||||
|
|
||||||
ALTER EVENT e3 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
|
||||||
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE DISABLE;
|
|
||||||
|
|
||||||
CREATE EVENT e6 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00' DO
|
|
||||||
SELECT 1;
|
|
||||||
|
|
||||||
CREATE EVENT e7 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
|
|
||||||
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE DISABLE
|
|
||||||
DO
|
|
||||||
SELECT 1;
|
|
||||||
|
|
||||||
CREATE EVENT e8 ON SCHEDULE AT '1999-01-01 00:00:00'
|
|
||||||
ON COMPLETION PRESERVE DISABLE
|
|
||||||
DO
|
|
||||||
SELECT 1;
|
|
||||||
|
|
||||||
SHOW EVENTS;
|
|
||||||
|
|
||||||
|
|
||||||
DROP EVENT e8;
|
|
||||||
DROP EVENT e7;
|
|
||||||
DROP EVENT e6;
|
|
||||||
DROP EVENT e5;
|
|
||||||
DROP EVENT e4;
|
|
||||||
DROP EVENT e3;
|
|
||||||
DROP EVENT e2;
|
|
||||||
DROP EVENT e1;
|
|
||||||
|
|
||||||
|
|
||||||
disconnect conn1;
|
|
||||||
connection default;
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
# Create rounding function.
|
# Create rounding function.
|
||||||
|
159
mysql-test/t/events_trans.test
Normal file
159
mysql-test/t/events_trans.test
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
#
|
||||||
|
# Tests that require transactions
|
||||||
|
#
|
||||||
|
-- source include/have_innodb.inc
|
||||||
|
--disable_warnings
|
||||||
|
drop database if exists events_test;
|
||||||
|
drop database if exists mysqltest_db2;
|
||||||
|
drop database if exists mysqltest_no_such_database;
|
||||||
|
--enable_warnings
|
||||||
|
create database events_test;
|
||||||
|
use events_test;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
--echo Test that Events DDL issue an implicit COMMIT
|
||||||
|
--echo
|
||||||
|
--echo
|
||||||
|
set autocommit=off;
|
||||||
|
# Sanity check
|
||||||
|
select @@autocommit;
|
||||||
|
create table t1 (a varchar(255)) engine=innodb;
|
||||||
|
# Basic: check that successful Events DDL commits pending transaction
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: create event");
|
||||||
|
create event e1 on schedule every 1 day do select 1;
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
#
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: alter event");
|
||||||
|
alter event e1 on schedule every 2 day do select 2;
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
#
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: alter event rename");
|
||||||
|
alter event e1 rename to e2;
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
#
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: drop event");
|
||||||
|
drop event e2;
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
#
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: drop event if exists");
|
||||||
|
drop event if exists e2;
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
#
|
||||||
|
create event e1 on schedule every 1 day do select 1;
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: create event if not exists");
|
||||||
|
create event if not exists e1 on schedule every 2 day do select 2;
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
--echo
|
||||||
|
--echo Now check various error conditions: make sure we issue an
|
||||||
|
--echo implicit commit anyway
|
||||||
|
--echo
|
||||||
|
#
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: create event: event already exists");
|
||||||
|
--error ER_EVENT_ALREADY_EXISTS
|
||||||
|
create event e1 on schedule every 2 day do select 2;
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
#
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: alter event rename: rename to same name");
|
||||||
|
--error ER_EVENT_SAME_NAME
|
||||||
|
alter event e1 rename to e1;
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
#
|
||||||
|
create event e2 on schedule every 3 day do select 3;
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: alter event rename: destination exists");
|
||||||
|
--error ER_EVENT_ALREADY_EXISTS
|
||||||
|
alter event e2 rename to e1;
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
#
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: create event: database does not exist");
|
||||||
|
--error ER_BAD_DB_ERROR
|
||||||
|
create event mysqltest_no_such_database.e1 on schedule every 1 day do select 1;
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
#
|
||||||
|
# Privilege checks
|
||||||
|
#
|
||||||
|
grant create, insert, select, delete on mysqltest_db2.*
|
||||||
|
to mysqltest_user1@localhost;
|
||||||
|
create database mysqltest_db2;
|
||||||
|
connect (conn1,localhost,mysqltest_user1,,mysqltest_db2);
|
||||||
|
set autocommit=off;
|
||||||
|
# Sanity check
|
||||||
|
select @@autocommit;
|
||||||
|
create table t1 (a varchar(255)) engine=innodb;
|
||||||
|
# Not enough privileges to CREATE EVENT
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: create event: insufficient privileges");
|
||||||
|
--error ER_DBACCESS_DENIED_ERROR
|
||||||
|
create event e1 on schedule every 1 day do select 1;
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
# Not enough privileges to ALTER EVENT
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: alter event: insufficient privileges");
|
||||||
|
--error ER_DBACCESS_DENIED_ERROR
|
||||||
|
alter event e1 on schedule every 1 day do select 1;
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
# Not enough privileges to DROP EVENT
|
||||||
|
begin work;
|
||||||
|
insert into t1 (a) values ("OK: drop event: insufficient privileges");
|
||||||
|
--error ER_DBACCESS_DENIED_ERROR
|
||||||
|
drop event e1;
|
||||||
|
rollback work;
|
||||||
|
select * from t1;
|
||||||
|
delete from t1;
|
||||||
|
commit work;
|
||||||
|
# Cleanup
|
||||||
|
disconnect conn1;
|
||||||
|
connection default;
|
||||||
|
drop user mysqltest_user1@localhost;
|
||||||
|
drop database mysqltest_db2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Cleanup
|
||||||
|
#
|
||||||
|
drop database events_test;
|
||||||
|
|
@ -20,8 +20,6 @@
|
|||||||
#include "event_db_repository.h"
|
#include "event_db_repository.h"
|
||||||
#include "sp_head.h"
|
#include "sp_head.h"
|
||||||
|
|
||||||
/* That's a provisional solution */
|
|
||||||
extern Event_db_repository events_event_db_repository;
|
|
||||||
|
|
||||||
#define EVEX_MAX_INTERVAL_VALUE 1000000000L
|
#define EVEX_MAX_INTERVAL_VALUE 1000000000L
|
||||||
|
|
||||||
@ -101,8 +99,7 @@ Event_parse_data::new_instance(THD *thd)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Event_parse_data::Event_parse_data()
|
Event_parse_data::Event_parse_data()
|
||||||
:on_completion(Event_basic::ON_COMPLETION_DROP),
|
:on_completion(ON_COMPLETION_DROP), status(ENABLED), do_not_create(FALSE),
|
||||||
status(Event_basic::ENABLED), do_not_create(FALSE),
|
|
||||||
item_starts(NULL), item_ends(NULL), item_execute_at(NULL),
|
item_starts(NULL), item_ends(NULL), item_execute_at(NULL),
|
||||||
starts_null(TRUE), ends_null(TRUE), execute_at_null(TRUE),
|
starts_null(TRUE), ends_null(TRUE), execute_at_null(TRUE),
|
||||||
item_expression(NULL), expression(0)
|
item_expression(NULL), expression(0)
|
||||||
@ -216,7 +213,7 @@ Event_parse_data::init_body(THD *thd)
|
|||||||
++body_begin;
|
++body_begin;
|
||||||
--body.length;
|
--body.length;
|
||||||
}
|
}
|
||||||
body.str= thd->strmake((char *)body_begin, body.length);
|
body.str= thd->strmake(body_begin, body.length);
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -244,7 +241,7 @@ Event_parse_data::check_if_in_the_past(THD *thd, my_time_t ltime_utc)
|
|||||||
if (ltime_utc >= (my_time_t) thd->query_start())
|
if (ltime_utc >= (my_time_t) thd->query_start())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (on_completion == Event_basic::ON_COMPLETION_DROP)
|
if (on_completion == ON_COMPLETION_DROP)
|
||||||
{
|
{
|
||||||
switch (thd->lex->sql_command) {
|
switch (thd->lex->sql_command) {
|
||||||
case SQLCOM_CREATE_EVENT:
|
case SQLCOM_CREATE_EVENT:
|
||||||
@ -261,9 +258,9 @@ Event_parse_data::check_if_in_the_past(THD *thd, my_time_t ltime_utc)
|
|||||||
|
|
||||||
do_not_create= TRUE;
|
do_not_create= TRUE;
|
||||||
}
|
}
|
||||||
else if (status == Event_basic::ENABLED)
|
else if (status == ENABLED)
|
||||||
{
|
{
|
||||||
status= Event_basic::DISABLED;
|
status= DISABLED;
|
||||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||||
ER_EVENT_EXEC_TIME_IN_THE_PAST,
|
ER_EVENT_EXEC_TIME_IN_THE_PAST,
|
||||||
ER(ER_EVENT_EXEC_TIME_IN_THE_PAST));
|
ER(ER_EVENT_EXEC_TIME_IN_THE_PAST));
|
||||||
@ -589,9 +586,9 @@ Event_parse_data::check_parse_data(THD *thd)
|
|||||||
init_name(thd, identifier);
|
init_name(thd, identifier);
|
||||||
|
|
||||||
init_definer(thd);
|
init_definer(thd);
|
||||||
|
|
||||||
ret= init_execute_at(thd) || init_interval(thd) || init_starts(thd) ||
|
ret= init_execute_at(thd) || init_interval(thd) || init_starts(thd) ||
|
||||||
init_ends(thd);
|
init_ends(thd);
|
||||||
check_originator_id(thd);
|
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -638,31 +635,6 @@ 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::DISABLED))
|
|
||||||
status = Event_basic::SLAVESIDE_DISABLED;
|
|
||||||
originator = thd->server_id;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
originator = server_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Constructor
|
Constructor
|
||||||
|
|
||||||
@ -720,7 +692,7 @@ Event_basic::load_string_fields(Field **fields, ...)
|
|||||||
|
|
||||||
va_start(args, fields);
|
va_start(args, fields);
|
||||||
field_name= (enum enum_events_table_field) va_arg(args, int);
|
field_name= (enum enum_events_table_field) va_arg(args, int);
|
||||||
while (field_name != ET_FIELD_COUNT)
|
while (field_name < ET_FIELD_COUNT)
|
||||||
{
|
{
|
||||||
field_value= va_arg(args, LEX_STRING *);
|
field_value= va_arg(args, LEX_STRING *);
|
||||||
if ((field_value->str= get_field(&mem_root, fields[field_name])) == NullS)
|
if ((field_value->str= get_field(&mem_root, fields[field_name])) == NullS)
|
||||||
@ -884,13 +856,19 @@ Event_job_data::load_from_row(THD *thd, TABLE *table)
|
|||||||
if (!table)
|
if (!table)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (table->s->fields != ET_FIELD_COUNT)
|
if (table->s->fields < ET_FIELD_COUNT)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
LEX_STRING tz_name;
|
LEX_STRING tz_name;
|
||||||
load_string_fields(table->field, ET_FIELD_DB, &dbname, ET_FIELD_NAME, &name,
|
if (load_string_fields(table->field,
|
||||||
ET_FIELD_BODY, &body, ET_FIELD_DEFINER, &definer,
|
ET_FIELD_DB, &dbname,
|
||||||
ET_FIELD_TIME_ZONE, &tz_name, ET_FIELD_COUNT);
|
ET_FIELD_NAME, &name,
|
||||||
|
ET_FIELD_BODY, &body,
|
||||||
|
ET_FIELD_DEFINER, &definer,
|
||||||
|
ET_FIELD_TIME_ZONE, &tz_name,
|
||||||
|
ET_FIELD_COUNT))
|
||||||
|
goto error;
|
||||||
|
|
||||||
if (load_time_zone(thd, tz_name))
|
if (load_time_zone(thd, tz_name))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -936,19 +914,24 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
|
|||||||
{
|
{
|
||||||
char *ptr;
|
char *ptr;
|
||||||
TIME time;
|
TIME time;
|
||||||
|
LEX_STRING tz_name;
|
||||||
|
|
||||||
DBUG_ENTER("Event_queue_element::load_from_row");
|
DBUG_ENTER("Event_queue_element::load_from_row");
|
||||||
|
|
||||||
if (!table)
|
if (!table)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (table->s->fields != ET_FIELD_COUNT)
|
if (table->s->fields < ET_FIELD_COUNT)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (load_string_fields(table->field,
|
||||||
|
ET_FIELD_DB, &dbname,
|
||||||
|
ET_FIELD_NAME, &name,
|
||||||
|
ET_FIELD_DEFINER, &definer,
|
||||||
|
ET_FIELD_TIME_ZONE, &tz_name,
|
||||||
|
ET_FIELD_COUNT))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
LEX_STRING tz_name;
|
|
||||||
load_string_fields(table->field, ET_FIELD_DB, &dbname, ET_FIELD_NAME, &name,
|
|
||||||
ET_FIELD_DEFINER, &definer,
|
|
||||||
ET_FIELD_TIME_ZONE, &tz_name, ET_FIELD_COUNT);
|
|
||||||
if (load_time_zone(thd, tz_name))
|
if (load_time_zone(thd, tz_name))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -1021,23 +1004,8 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", name.str, ptr));
|
DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", name.str, ptr));
|
||||||
|
status= (ptr[0]=='E'? Event_queue_element::ENABLED:
|
||||||
/* Set event status (ENABLED | SLAVESIDE_DISABLED | DISABLED) */
|
Event_queue_element::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 */
|
/* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */
|
||||||
if ((ptr= get_field(&mem_root,
|
if ((ptr= get_field(&mem_root,
|
||||||
@ -1080,7 +1048,11 @@ Event_timed::load_from_row(THD *thd, TABLE *table)
|
|||||||
if (Event_queue_element::load_from_row(thd, table))
|
if (Event_queue_element::load_from_row(thd, table))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
load_string_fields(table->field, ET_FIELD_BODY, &body, ET_FIELD_COUNT);
|
if (load_string_fields(table->field,
|
||||||
|
ET_FIELD_BODY, &body,
|
||||||
|
ET_FIELD_COUNT))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
|
||||||
ptr= strchr(definer.str, '@');
|
ptr= strchr(definer.str, '@');
|
||||||
|
|
||||||
@ -1384,7 +1356,7 @@ Event_queue_element::compute_next_execution_time()
|
|||||||
(long) starts, (long) ends, (long) last_executed,
|
(long) starts, (long) ends, (long) last_executed,
|
||||||
(long) this));
|
(long) this));
|
||||||
|
|
||||||
if (status != Event_queue_element::ENABLED)
|
if (status == Event_queue_element::DISABLED)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("compute_next_execution_time",
|
DBUG_PRINT("compute_next_execution_time",
|
||||||
("Event %s is DISABLED", name.str));
|
("Event %s is DISABLED", name.str));
|
||||||
@ -1635,10 +1607,8 @@ Event_queue_element::mark_last_executed(THD *thd)
|
|||||||
bool
|
bool
|
||||||
Event_queue_element::update_timing_fields(THD *thd)
|
Event_queue_element::update_timing_fields(THD *thd)
|
||||||
{
|
{
|
||||||
TABLE *table;
|
Event_db_repository *db_repository= Events::get_db_repository();
|
||||||
Field **fields;
|
int ret;
|
||||||
Open_tables_state backup;
|
|
||||||
int ret= FALSE;
|
|
||||||
|
|
||||||
DBUG_ENTER("Event_queue_element::update_timing_fields");
|
DBUG_ENTER("Event_queue_element::update_timing_fields");
|
||||||
|
|
||||||
@ -1648,53 +1618,13 @@ Event_queue_element::update_timing_fields(THD *thd)
|
|||||||
if (!(status_changed || last_executed_changed))
|
if (!(status_changed || last_executed_changed))
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
thd->reset_n_backup_open_tables_state(&backup);
|
ret= db_repository->update_timing_fields_for_event(thd,
|
||||||
|
dbname, name,
|
||||||
if (events_event_db_repository.open_event_table(thd, TL_WRITE, &table))
|
last_executed_changed,
|
||||||
{
|
last_executed,
|
||||||
ret= TRUE;
|
status_changed,
|
||||||
goto done;
|
(ulonglong) status);
|
||||||
}
|
last_executed_changed= status_changed= FALSE;
|
||||||
fields= table->field;
|
|
||||||
if ((ret= events_event_db_repository.
|
|
||||||
find_named_event(thd, dbname, name, table)))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
store_record(table,record[1]);
|
|
||||||
/* Don't update create on row update. */
|
|
||||||
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
|
|
||||||
|
|
||||||
if (last_executed_changed)
|
|
||||||
{
|
|
||||||
TIME time;
|
|
||||||
my_tz_UTC->gmt_sec_to_TIME(&time, last_executed);
|
|
||||||
|
|
||||||
fields[ET_FIELD_LAST_EXECUTED]->set_notnull();
|
|
||||||
fields[ET_FIELD_LAST_EXECUTED]->store_time(&time,
|
|
||||||
MYSQL_TIMESTAMP_DATETIME);
|
|
||||||
last_executed_changed= FALSE;
|
|
||||||
}
|
|
||||||
if (status_changed)
|
|
||||||
{
|
|
||||||
fields[ET_FIELD_STATUS]->set_notnull();
|
|
||||||
fields[ET_FIELD_STATUS]->store((longlong)status, TRUE);
|
|
||||||
status_changed= FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Turn off row binlogging of event timing updates. These are not used
|
|
||||||
for RBR of events replicated to the slave.
|
|
||||||
*/
|
|
||||||
if (thd->current_stmt_binlog_row_based)
|
|
||||||
thd->clear_current_stmt_binlog_row_based();
|
|
||||||
|
|
||||||
if ((table->file->ha_update_row(table->record[1], table->record[0])))
|
|
||||||
ret= TRUE;
|
|
||||||
|
|
||||||
done:
|
|
||||||
close_thread_tables(thd);
|
|
||||||
thd->restore_backup_open_tables_state(&backup);
|
|
||||||
|
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1778,8 +1708,6 @@ Event_timed::get_create_event(THD *thd, String *buf)
|
|||||||
|
|
||||||
if (status == Event_timed::ENABLED)
|
if (status == Event_timed::ENABLED)
|
||||||
buf->append(STRING_WITH_LEN("ENABLE"));
|
buf->append(STRING_WITH_LEN("ENABLE"));
|
||||||
else if (status == Event_timed::SLAVESIDE_DISABLED)
|
|
||||||
buf->append(STRING_WITH_LEN("SLAVESIDE_DISABLE"));
|
|
||||||
else
|
else
|
||||||
buf->append(STRING_WITH_LEN("DISABLE"));
|
buf->append(STRING_WITH_LEN("DISABLE"));
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
#define EVEX_GET_FIELD_FAILED -2
|
#define EVEX_GET_FIELD_FAILED -2
|
||||||
#define EVEX_COMPILE_ERROR -3
|
#define EVEX_COMPILE_ERROR -3
|
||||||
#define EVEX_GENERAL_ERROR -4
|
|
||||||
#define EVEX_BAD_PARAMS -5
|
#define EVEX_BAD_PARAMS -5
|
||||||
#define EVEX_MICROSECOND_UNSUP -6
|
#define EVEX_MICROSECOND_UNSUP -6
|
||||||
|
|
||||||
@ -178,8 +177,6 @@ public:
|
|||||||
|
|
||||||
ulong sql_mode;
|
ulong sql_mode;
|
||||||
|
|
||||||
uint execution_count;
|
|
||||||
|
|
||||||
Event_job_data();
|
Event_job_data();
|
||||||
virtual ~Event_job_data();
|
virtual ~Event_job_data();
|
||||||
|
|
||||||
|
@ -18,12 +18,6 @@
|
|||||||
#include "event_data_objects.h"
|
#include "event_data_objects.h"
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
#include "sql_show.h"
|
#include "sql_show.h"
|
||||||
#include "sp.h"
|
|
||||||
#include "sp_head.h"
|
|
||||||
|
|
||||||
|
|
||||||
static
|
|
||||||
time_t mysql_event_last_create_time= 0L;
|
|
||||||
|
|
||||||
static
|
static
|
||||||
const TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] =
|
const TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] =
|
||||||
@ -132,26 +126,21 @@ const TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Puts some data common to CREATE and ALTER EVENT into a row.
|
Puts some data common to CREATE and ALTER EVENT into a row.
|
||||||
|
|
||||||
SYNOPSIS
|
Used both when an event is created and when it is altered.
|
||||||
mysql_event_fill_row()
|
|
||||||
thd THD
|
|
||||||
table The row to fill out
|
|
||||||
et Event's data
|
|
||||||
is_update CREATE EVENT or ALTER EVENT
|
|
||||||
|
|
||||||
RETURN VALUE
|
@param thd THD
|
||||||
0 OK
|
@param table The row to fill out
|
||||||
EVEX_GENERAL_ERROR Bad data
|
@param et Event's data
|
||||||
EVEX_GET_FIELD_FAILED Field count does not match. table corrupted?
|
@param is_update CREATE EVENT or ALTER EVENT
|
||||||
|
|
||||||
DESCRIPTION
|
@retval FALSE success
|
||||||
Used both when an event is created and when it is altered.
|
@retval TRUE error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static bool
|
||||||
mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et,
|
mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et,
|
||||||
my_bool is_update)
|
my_bool is_update)
|
||||||
{
|
{
|
||||||
@ -165,6 +154,17 @@ mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et,
|
|||||||
DBUG_PRINT("info", ("name =[%s]", et->name.str));
|
DBUG_PRINT("info", ("name =[%s]", et->name.str));
|
||||||
DBUG_PRINT("info", ("body =[%s]", et->body.str));
|
DBUG_PRINT("info", ("body =[%s]", et->body.str));
|
||||||
|
|
||||||
|
if (table->s->fields < ET_FIELD_COUNT)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Safety: this can only happen if someone started the server
|
||||||
|
and then altered mysql.event.
|
||||||
|
*/
|
||||||
|
my_error(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED, MYF(0), table->alias,
|
||||||
|
(int) ET_FIELD_COUNT, table->s->fields);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
if (fields[f_num= ET_FIELD_DEFINER]->
|
if (fields[f_num= ET_FIELD_DEFINER]->
|
||||||
store(et->definer.str, et->definer.length, scs))
|
store(et->definer.str, et->definer.length, scs))
|
||||||
goto err_truncate;
|
goto err_truncate;
|
||||||
@ -271,11 +271,11 @@ mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et,
|
|||||||
goto err_truncate;
|
goto err_truncate;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(FALSE);
|
||||||
|
|
||||||
err_truncate:
|
err_truncate:
|
||||||
my_error(ER_EVENT_DATA_TOO_LONG, MYF(0), fields[f_num]->field_name);
|
my_error(ER_EVENT_DATA_TOO_LONG, MYF(0), fields[f_num]->field_name);
|
||||||
DBUG_RETURN(EVEX_GENERAL_ERROR);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -389,40 +389,33 @@ Event_db_repository::table_scan_all_for_i_s(THD *thd, TABLE *schema_table,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Fills I_S.EVENTS with data loaded from mysql.event. Also used by
|
Fills I_S.EVENTS with data loaded from mysql.event. Also used by
|
||||||
SHOW EVENTS
|
SHOW EVENTS
|
||||||
|
|
||||||
SYNOPSIS
|
The reason we reset and backup open tables here is that this
|
||||||
Event_db_repository::fill_schema_events()
|
function may be called from any query that accesses
|
||||||
thd Thread
|
INFORMATION_SCHEMA - including a query that is issued from
|
||||||
tables The schema table
|
a pre-locked statement, one that already has open and locked
|
||||||
db If not NULL then get events only from this schema
|
tables.
|
||||||
|
|
||||||
RETURN VALUE
|
@retval FALSE success
|
||||||
FALSE OK
|
@retval TRUE error
|
||||||
TRUE Error
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
bool
|
||||||
Event_db_repository::fill_schema_events(THD *thd, TABLE_LIST *tables,
|
Event_db_repository::fill_schema_events(THD *thd, TABLE_LIST *tables,
|
||||||
const char *db)
|
const char *db)
|
||||||
{
|
{
|
||||||
TABLE *schema_table= tables->table;
|
TABLE *schema_table= tables->table;
|
||||||
TABLE *event_table= NULL;
|
TABLE *event_table= NULL;
|
||||||
Open_tables_state backup;
|
|
||||||
int ret= 0;
|
int ret= 0;
|
||||||
|
|
||||||
DBUG_ENTER("Event_db_repository::fill_schema_events");
|
DBUG_ENTER("Event_db_repository::fill_schema_events");
|
||||||
DBUG_PRINT("info",("db=%s", db? db:"(null)"));
|
DBUG_PRINT("info",("db=%s", db? db:"(null)"));
|
||||||
|
|
||||||
thd->reset_n_backup_open_tables_state(&backup);
|
|
||||||
if (open_event_table(thd, TL_READ, &event_table))
|
if (open_event_table(thd, TL_READ, &event_table))
|
||||||
{
|
DBUG_RETURN(TRUE);
|
||||||
sql_print_error("Table mysql.event is damaged.");
|
|
||||||
thd->restore_backup_open_tables_state(&backup);
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
1. SELECT I_S => use table scan. I_S.EVENTS does not guarantee order
|
1. SELECT I_S => use table scan. I_S.EVENTS does not guarantee order
|
||||||
@ -439,163 +432,100 @@ Event_db_repository::fill_schema_events(THD *thd, TABLE_LIST *tables,
|
|||||||
ret= table_scan_all_for_i_s(thd, schema_table, event_table);
|
ret= table_scan_all_for_i_s(thd, schema_table, event_table);
|
||||||
|
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
thd->restore_backup_open_tables_state(&backup);
|
|
||||||
|
|
||||||
DBUG_PRINT("info", ("Return code=%d", ret));
|
DBUG_PRINT("info", ("Return code=%d", ret));
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Open mysql.event table for read
|
Open mysql.event table for read.
|
||||||
|
|
||||||
SYNOPSIS
|
It's assumed that the caller knows what they are doing:
|
||||||
Events::open_event_table()
|
- whether it was necessary to reset-and-backup the open tables state
|
||||||
thd [in] Thread context
|
- whether the requested lock does not lead to a deadlock
|
||||||
lock_type [in] How to lock the table
|
- whether this open mode would work under LOCK TABLES, or inside a
|
||||||
table [out] We will store the open table here
|
stored function or trigger.
|
||||||
|
|
||||||
RETURN VALUE
|
@param[in] thd Thread context
|
||||||
1 Cannot lock table
|
@param[in] lock_type How to lock the table
|
||||||
2 The table is corrupted - different number of fields
|
@param[out] table We will store the open table here
|
||||||
0 OK
|
|
||||||
|
@retval TRUE open and lock failed - an error message is pushed into the
|
||||||
|
stack
|
||||||
|
@retval FALSE success
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
bool
|
||||||
Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type,
|
Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type,
|
||||||
TABLE **table)
|
TABLE **table)
|
||||||
{
|
{
|
||||||
TABLE_LIST tables;
|
TABLE_LIST tables;
|
||||||
DBUG_ENTER("Event_db_repository::open_event_table");
|
DBUG_ENTER("Event_db_repository::open_event_table");
|
||||||
|
|
||||||
bzero((char*) &tables, sizeof(tables));
|
tables.init_one_table("mysql", "event", lock_type);
|
||||||
tables.db= (char*) "mysql";
|
|
||||||
tables.table_name= tables.alias= (char*) "event";
|
|
||||||
tables.lock_type= lock_type;
|
|
||||||
|
|
||||||
if (simple_open_n_lock_tables(thd, &tables))
|
if (simple_open_n_lock_tables(thd, &tables))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
if (table_check_intact(tables.table, ET_FIELD_COUNT,
|
|
||||||
event_table_fields,
|
|
||||||
&mysql_event_last_create_time,
|
|
||||||
ER_CANNOT_LOAD_FROM_TABLE))
|
|
||||||
{
|
|
||||||
close_thread_tables(thd);
|
|
||||||
DBUG_RETURN(2);
|
|
||||||
}
|
|
||||||
*table= tables.table;
|
*table= tables.table;
|
||||||
tables.table->use_all_columns();
|
tables.table->use_all_columns();
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Checks parameters which we got from the parsing phase.
|
Creates an event record in mysql.event table.
|
||||||
|
|
||||||
SYNOPSIS
|
Creates an event. Relies on mysql_event_fill_row which is shared with
|
||||||
check_parse_params()
|
::update_event.
|
||||||
thd Thread context
|
|
||||||
parse_data Event's data
|
|
||||||
|
|
||||||
RETURN VALUE
|
@pre All semantic checks must be performed outside. This function
|
||||||
FALSE OK
|
only creates a record on disk.
|
||||||
TRUE Error (reported)
|
@pre The thread handle has no open tables.
|
||||||
*/
|
|
||||||
|
|
||||||
static int
|
@param[in,out] THD
|
||||||
check_parse_params(THD *thd, Event_parse_data *parse_data)
|
@param[in] parse_data Parsed event definition
|
||||||
{
|
@param[in] create_if_not TRUE if IF NOT EXISTS clause was provided
|
||||||
DBUG_ENTER("check_parse_params");
|
to CREATE EVENT statement
|
||||||
|
|
||||||
if (parse_data->check_parse_data(thd))
|
@retval FALSE success
|
||||||
DBUG_RETURN(EVEX_BAD_PARAMS);
|
@retval TRUE error
|
||||||
|
|
||||||
if (!parse_data->dbname.str ||
|
|
||||||
(thd->lex->sql_command == SQLCOM_ALTER_EVENT && thd->lex->spname &&
|
|
||||||
!thd->lex->spname->m_db.str))
|
|
||||||
{
|
|
||||||
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
|
|
||||||
DBUG_RETURN(EVEX_BAD_PARAMS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (check_access(thd, EVENT_ACL, parse_data->dbname.str, 0, 0, 0,
|
|
||||||
is_schema_db(parse_data->dbname.str)) ||
|
|
||||||
(thd->lex->sql_command == SQLCOM_ALTER_EVENT && thd->lex->spname &&
|
|
||||||
(check_access(thd, EVENT_ACL, thd->lex->spname->m_db.str, 0, 0, 0,
|
|
||||||
is_schema_db(thd->lex->spname->m_db.str)))))
|
|
||||||
DBUG_RETURN(EVEX_BAD_PARAMS);
|
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Creates an event in mysql.event
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
Event_db_repository::create_event()
|
|
||||||
thd [in] THD
|
|
||||||
parse_data [in] Object containing info about the event
|
|
||||||
create_if_not [in] Whether to generate anwarning in case event exists
|
|
||||||
|
|
||||||
RETURN VALUE
|
|
||||||
0 OK
|
|
||||||
EVEX_GENERAL_ERROR Failure
|
|
||||||
|
|
||||||
DESCRIPTION
|
|
||||||
Creates an event. Relies on mysql_event_fill_row which is shared with
|
|
||||||
::update_event. The name of the event is inside "et".
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
|
Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
|
||||||
my_bool create_if_not)
|
my_bool create_if_not)
|
||||||
{
|
{
|
||||||
int ret= 0;
|
int ret= 1;
|
||||||
TABLE *table= NULL;
|
TABLE *table= NULL;
|
||||||
char old_db_buf[NAME_LEN+1];
|
|
||||||
LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) };
|
|
||||||
bool dbchanged= FALSE;
|
|
||||||
|
|
||||||
DBUG_ENTER("Event_db_repository::create_event");
|
DBUG_ENTER("Event_db_repository::create_event");
|
||||||
|
|
||||||
if (check_parse_params(thd, parse_data))
|
|
||||||
goto err;
|
|
||||||
if (parse_data->do_not_create)
|
|
||||||
goto ok;
|
|
||||||
|
|
||||||
DBUG_PRINT("info", ("open mysql.event for update"));
|
DBUG_PRINT("info", ("open mysql.event for update"));
|
||||||
|
|
||||||
if (open_event_table(thd, TL_WRITE, &table))
|
if (open_event_table(thd, TL_WRITE, &table))
|
||||||
{
|
goto end;
|
||||||
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBUG_PRINT("info", ("name: %.*s", parse_data->name.length,
|
DBUG_PRINT("info", ("name: %.*s", parse_data->name.length,
|
||||||
parse_data->name.str));
|
parse_data->name.str));
|
||||||
|
|
||||||
DBUG_PRINT("info", ("check existance of an event with the same name"));
|
DBUG_PRINT("info", ("check existance of an event with the same name"));
|
||||||
if (!find_named_event(thd, parse_data->dbname, parse_data->name, table))
|
if (!find_named_event(parse_data->dbname, parse_data->name, table))
|
||||||
{
|
{
|
||||||
if (create_if_not)
|
if (create_if_not)
|
||||||
{
|
{
|
||||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||||
ER_EVENT_ALREADY_EXISTS, ER(ER_EVENT_ALREADY_EXISTS),
|
ER_EVENT_ALREADY_EXISTS, ER(ER_EVENT_ALREADY_EXISTS),
|
||||||
parse_data->name.str);
|
parse_data->name.str);
|
||||||
goto ok;
|
ret= 0;
|
||||||
}
|
}
|
||||||
my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), parse_data->name.str);
|
else
|
||||||
goto err;
|
my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), parse_data->name.str);
|
||||||
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_PRINT("info", ("non-existant, go forward"));
|
DBUG_PRINT("info", ("non-existent, go forward"));
|
||||||
|
|
||||||
if ((ret= sp_use_new_db(thd, parse_data->dbname, &old_db, 0, &dbchanged)))
|
|
||||||
{
|
|
||||||
my_error(ER_BAD_DB_ERROR, MYF(0));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
restore_record(table, s->default_values); // Get default values for fields
|
restore_record(table, s->default_values); // Get default values for fields
|
||||||
|
|
||||||
@ -605,7 +535,7 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
|
|||||||
table->field[ET_FIELD_DB]->char_length())
|
table->field[ET_FIELD_DB]->char_length())
|
||||||
{
|
{
|
||||||
my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->dbname.str);
|
my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->dbname.str);
|
||||||
goto err;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (system_charset_info->cset->
|
if (system_charset_info->cset->
|
||||||
@ -614,20 +544,13 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
|
|||||||
table->field[ET_FIELD_NAME]->char_length())
|
table->field[ET_FIELD_NAME]->char_length())
|
||||||
{
|
{
|
||||||
my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->name.str);
|
my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->name.str);
|
||||||
goto err;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parse_data->body.length > table->field[ET_FIELD_BODY]->field_length)
|
if (parse_data->body.length > table->field[ET_FIELD_BODY]->field_length)
|
||||||
{
|
{
|
||||||
my_error(ER_TOO_LONG_BODY, MYF(0), parse_data->name.str);
|
my_error(ER_TOO_LONG_BODY, MYF(0), parse_data->name.str);
|
||||||
goto err;
|
goto end;
|
||||||
}
|
|
||||||
|
|
||||||
if (!(parse_data->expression) && !(parse_data->execute_at))
|
|
||||||
{
|
|
||||||
DBUG_PRINT("error", ("neither expression nor execute_at are set!"));
|
|
||||||
my_error(ER_EVENT_NEITHER_M_EXPR_NOR_M_AT, MYF(0));
|
|
||||||
goto err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
((Field_timestamp *)table->field[ET_FIELD_CREATED])->set_time();
|
((Field_timestamp *)table->field[ET_FIELD_CREATED])->set_time();
|
||||||
@ -636,95 +559,71 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
|
|||||||
mysql_event_fill_row() calls my_error() in case of error so no need to
|
mysql_event_fill_row() calls my_error() in case of error so no need to
|
||||||
handle it here
|
handle it here
|
||||||
*/
|
*/
|
||||||
if ((ret= mysql_event_fill_row(thd, table, parse_data, FALSE)))
|
if (mysql_event_fill_row(thd, table, parse_data, FALSE))
|
||||||
goto err;
|
goto end;
|
||||||
|
|
||||||
table->field[ET_FIELD_STATUS]->store((longlong)parse_data->status, TRUE);
|
table->field[ET_FIELD_STATUS]->store((longlong)parse_data->status, TRUE);
|
||||||
|
|
||||||
/* Close active transaction only if We are going to modify disk */
|
if ((ret= table->file->ha_write_row(table->record[0])))
|
||||||
if (end_active_trans(thd))
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
if (table->file->ha_write_row(table->record[0]))
|
|
||||||
{
|
{
|
||||||
my_error(ER_EVENT_STORE_FAILED, MYF(0), parse_data->name.str, ret);
|
table->file->print_error(ret, MYF(0));
|
||||||
goto err;
|
goto end;
|
||||||
}
|
}
|
||||||
|
ret= 0;
|
||||||
|
|
||||||
ok:
|
end:
|
||||||
if (dbchanged)
|
|
||||||
(void) mysql_change_db(thd, old_db.str, 1);
|
|
||||||
/*
|
|
||||||
This statement may cause a spooky valgrind warning at startup
|
|
||||||
inside init_key_cache on my system (ahristov, 2006/08/10)
|
|
||||||
*/
|
|
||||||
close_thread_tables(thd);
|
|
||||||
DBUG_RETURN(FALSE);
|
|
||||||
|
|
||||||
err:
|
|
||||||
if (dbchanged)
|
|
||||||
(void) mysql_change_db(thd, old_db.str, 1);
|
|
||||||
if (table)
|
if (table)
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(test(ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Used to execute ALTER EVENT. Pendant to Events::update_event().
|
Used to execute ALTER EVENT. Pendant to Events::update_event().
|
||||||
|
|
||||||
SYNOPSIS
|
@param[in,out] thd thread handle
|
||||||
Event_db_repository::update_event()
|
@param[in] parse_data parsed event definition
|
||||||
thd THD
|
@paran[in[ new_dbname not NULL if ALTER EVENT RENAME
|
||||||
sp_name the name of the event to alter
|
points at a new database name
|
||||||
et event's data
|
@param[in] new_name not NULL if ALTER EVENT RENAME
|
||||||
|
points at a new event name
|
||||||
|
|
||||||
RETURN VALUE
|
@pre All semantic checks are performed outside this function,
|
||||||
FALSE OK
|
it only updates the event definition on disk.
|
||||||
TRUE Error (reported)
|
@pre We don't have any tables open in the given thread.
|
||||||
|
|
||||||
NOTES
|
@retval FALSE success
|
||||||
sp_name is passed since this is the name of the event to
|
@retval TRUE error (reported)
|
||||||
alter in case of RENAME TO.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
|
Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
|
||||||
LEX_STRING *new_dbname, LEX_STRING *new_name)
|
LEX_STRING *new_dbname,
|
||||||
|
LEX_STRING *new_name)
|
||||||
{
|
{
|
||||||
CHARSET_INFO *scs= system_charset_info;
|
CHARSET_INFO *scs= system_charset_info;
|
||||||
TABLE *table= NULL;
|
TABLE *table= NULL;
|
||||||
|
int ret= 1;
|
||||||
DBUG_ENTER("Event_db_repository::update_event");
|
DBUG_ENTER("Event_db_repository::update_event");
|
||||||
|
|
||||||
if (open_event_table(thd, TL_WRITE, &table))
|
/* None or both must be set */
|
||||||
{
|
DBUG_ASSERT(new_dbname && new_name || new_dbname == new_name);
|
||||||
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (check_parse_params(thd, parse_data) || parse_data->do_not_create)
|
if (open_event_table(thd, TL_WRITE, &table))
|
||||||
goto err;
|
goto end;
|
||||||
|
|
||||||
DBUG_PRINT("info", ("dbname: %s", parse_data->dbname.str));
|
DBUG_PRINT("info", ("dbname: %s", parse_data->dbname.str));
|
||||||
DBUG_PRINT("info", ("name: %s", parse_data->name.str));
|
DBUG_PRINT("info", ("name: %s", parse_data->name.str));
|
||||||
DBUG_PRINT("info", ("user: %s", parse_data->definer.str));
|
DBUG_PRINT("info", ("user: %s", parse_data->definer.str));
|
||||||
if (new_dbname)
|
|
||||||
DBUG_PRINT("info", ("rename to: %s@%s", new_dbname->str, new_name->str));
|
|
||||||
|
|
||||||
/* first look whether we overwrite */
|
/* first look whether we overwrite */
|
||||||
if (new_name)
|
if (new_name)
|
||||||
{
|
{
|
||||||
if (!sortcmp_lex_string(parse_data->name, *new_name, scs) &&
|
DBUG_PRINT("info", ("rename to: %s@%s", new_dbname->str, new_name->str));
|
||||||
!sortcmp_lex_string(parse_data->dbname, *new_dbname, scs))
|
if (!find_named_event(*new_dbname, *new_name, table))
|
||||||
{
|
|
||||||
my_error(ER_EVENT_SAME_NAME, MYF(0), parse_data->name.str);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!find_named_event(thd, *new_dbname, *new_name, table))
|
|
||||||
{
|
{
|
||||||
my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), new_name->str);
|
my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), new_name->str);
|
||||||
goto err;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -733,10 +632,10 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
|
|||||||
overwrite the key and SE will tell us that it cannot find the already found
|
overwrite the key and SE will tell us that it cannot find the already found
|
||||||
row (copied into record[1] later
|
row (copied into record[1] later
|
||||||
*/
|
*/
|
||||||
if (find_named_event(thd, parse_data->dbname, parse_data->name, table))
|
if (find_named_event(parse_data->dbname, parse_data->name, table))
|
||||||
{
|
{
|
||||||
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), parse_data->name.str);
|
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), parse_data->name.str);
|
||||||
goto err;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
store_record(table,record[1]);
|
store_record(table,record[1]);
|
||||||
@ -749,7 +648,7 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
|
|||||||
handle it here
|
handle it here
|
||||||
*/
|
*/
|
||||||
if (mysql_event_fill_row(thd, table, parse_data, TRUE))
|
if (mysql_event_fill_row(thd, table, parse_data, TRUE))
|
||||||
goto err;
|
goto end;
|
||||||
|
|
||||||
if (new_dbname)
|
if (new_dbname)
|
||||||
{
|
{
|
||||||
@ -757,42 +656,32 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
|
|||||||
table->field[ET_FIELD_NAME]->store(new_name->str, new_name->length, scs);
|
table->field[ET_FIELD_NAME]->store(new_name->str, new_name->length, scs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close active transaction only if We are going to modify disk */
|
if ((ret= table->file->ha_update_row(table->record[1], table->record[0])))
|
||||||
if (end_active_trans(thd))
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
int res;
|
|
||||||
if ((res= table->file->ha_update_row(table->record[1], table->record[0])))
|
|
||||||
{
|
{
|
||||||
my_error(ER_EVENT_STORE_FAILED, MYF(0), parse_data->name.str, res);
|
table->file->print_error(ret, MYF(0));
|
||||||
goto err;
|
goto end;
|
||||||
}
|
}
|
||||||
|
ret= 0;
|
||||||
|
|
||||||
/* close mysql.event or we crash later when loading the event from disk */
|
end:
|
||||||
close_thread_tables(thd);
|
|
||||||
DBUG_RETURN(FALSE);
|
|
||||||
|
|
||||||
err:
|
|
||||||
if (table)
|
if (table)
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(test(ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Drops an event
|
Delete event record from mysql.event table.
|
||||||
|
|
||||||
SYNOPSIS
|
@param[in,out] thd thread handle
|
||||||
Event_db_repository::drop_event()
|
@param[in] db Database name
|
||||||
thd [in] THD
|
@param[in] name Event name
|
||||||
db [in] Database name
|
@param[in] drop_if_exists DROP IF EXISTS clause was specified.
|
||||||
name [in] Event's name
|
If set, and the event does not exist,
|
||||||
drop_if_exists [in] If set and the event not existing => warning
|
the error is downgraded to a warning.
|
||||||
onto the stack
|
|
||||||
|
|
||||||
RETURN VALUE
|
@retval FALSE success
|
||||||
FALSE OK
|
@retval TRUE error (reported)
|
||||||
TRUE Error (reported)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -800,66 +689,59 @@ Event_db_repository::drop_event(THD *thd, LEX_STRING db, LEX_STRING name,
|
|||||||
bool drop_if_exists)
|
bool drop_if_exists)
|
||||||
{
|
{
|
||||||
TABLE *table= NULL;
|
TABLE *table= NULL;
|
||||||
Open_tables_state backup;
|
int ret= 1;
|
||||||
int ret;
|
|
||||||
|
|
||||||
DBUG_ENTER("Event_db_repository::drop_event");
|
DBUG_ENTER("Event_db_repository::drop_event");
|
||||||
DBUG_PRINT("enter", ("%s@%s", db.str, name.str));
|
DBUG_PRINT("enter", ("%s@%s", db.str, name.str));
|
||||||
|
|
||||||
thd->reset_n_backup_open_tables_state(&backup);
|
if (open_event_table(thd, TL_WRITE, &table))
|
||||||
if ((ret= open_event_table(thd, TL_WRITE, &table)))
|
goto end;
|
||||||
|
|
||||||
|
if (!find_named_event(db, name, table))
|
||||||
{
|
{
|
||||||
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
|
if ((ret= table->file->ha_delete_row(table->record[0])))
|
||||||
goto done;
|
table->file->print_error(ret, MYF(0));
|
||||||
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(ret= find_named_event(thd, db, name, table)))
|
/* Event not found */
|
||||||
|
if (!drop_if_exists)
|
||||||
{
|
{
|
||||||
/* Close active transaction only if we are actually going to modify disk */
|
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str);
|
||||||
if (!(ret= end_active_trans(thd)) &&
|
goto end;
|
||||||
(ret= table->file->ha_delete_row(table->record[0])))
|
|
||||||
my_error(ER_EVENT_CANNOT_DELETE, MYF(0));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (drop_if_exists)
|
|
||||||
{
|
|
||||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
|
||||||
ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
|
|
||||||
"Event", name.str);
|
|
||||||
ret= 0;
|
|
||||||
} else
|
|
||||||
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||||
|
ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
|
||||||
|
"Event", name.str);
|
||||||
|
ret= 0;
|
||||||
|
|
||||||
|
end:
|
||||||
if (table)
|
if (table)
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
thd->restore_backup_open_tables_state(&backup);
|
|
||||||
|
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(test(ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Positions the internal pointer of `table` to the place where (db, name)
|
Positions the internal pointer of `table` to the place where (db, name)
|
||||||
is stored.
|
is stored.
|
||||||
|
|
||||||
SYNOPSIS
|
In case search succeeded, the table cursor points at the found row.
|
||||||
Event_db_repository::find_named_event()
|
|
||||||
thd Thread
|
|
||||||
db Schema
|
|
||||||
name Event name
|
|
||||||
table Opened mysql.event
|
|
||||||
|
|
||||||
RETURN VALUE
|
@param[in] db database name
|
||||||
FALSE OK
|
@param[in] name event name
|
||||||
TRUE No such event
|
@param[in,out] table mysql.event table
|
||||||
|
|
||||||
|
|
||||||
|
@retval FALSE an event with such db/name key exists
|
||||||
|
@reval TRUE no record found or an error occured.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Event_db_repository::find_named_event(THD *thd, LEX_STRING db, LEX_STRING name,
|
Event_db_repository::find_named_event(LEX_STRING db, LEX_STRING name,
|
||||||
TABLE *table)
|
TABLE *table)
|
||||||
{
|
{
|
||||||
byte key[MAX_KEY_LENGTH];
|
byte key[MAX_KEY_LENGTH];
|
||||||
DBUG_ENTER("Event_db_repository::find_named_event");
|
DBUG_ENTER("Event_db_repository::find_named_event");
|
||||||
@ -911,15 +793,15 @@ Event_db_repository::drop_schema_events(THD *thd, LEX_STRING schema)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Drops all events by field which has specific value of the field
|
Drops all events which have a specific value of a field.
|
||||||
|
|
||||||
SYNOPSIS
|
@pre The thread handle has no open tables.
|
||||||
Event_db_repository::drop_events_by_field()
|
|
||||||
thd Thread
|
@param[in,out] thd Thread
|
||||||
table mysql.event TABLE
|
@param[in,out] table mysql.event TABLE
|
||||||
field Which field of the row to use for matching
|
@param[in] field Which field of the row to use for matching
|
||||||
field_value The value that should match
|
@param[in] field_value The value that should match
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -934,16 +816,7 @@ Event_db_repository::drop_events_by_field(THD *thd,
|
|||||||
DBUG_PRINT("enter", ("field=%d field_value=%s", field, field_value.str));
|
DBUG_PRINT("enter", ("field=%d field_value=%s", field, field_value.str));
|
||||||
|
|
||||||
if (open_event_table(thd, TL_WRITE, &table))
|
if (open_event_table(thd, TL_WRITE, &table))
|
||||||
{
|
|
||||||
/*
|
|
||||||
Currently being used only for DROP DATABASE - In this case we don't need
|
|
||||||
error message since the OK packet has been sent. But for DROP USER we
|
|
||||||
could need it.
|
|
||||||
|
|
||||||
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
|
|
||||||
*/
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
|
||||||
|
|
||||||
/* only enabled events are in memory, so we go now and delete the rest */
|
/* only enabled events are in memory, so we go now and delete the rest */
|
||||||
init_read_record(&read_record_info, thd, table, NULL, 1, 0);
|
init_read_record(&read_record_info, thd, table, NULL, 1, 0);
|
||||||
@ -951,14 +824,20 @@ Event_db_repository::drop_events_by_field(THD *thd,
|
|||||||
{
|
{
|
||||||
char *et_field= get_field(thd->mem_root, table->field[field]);
|
char *et_field= get_field(thd->mem_root, table->field[field]);
|
||||||
|
|
||||||
LEX_STRING et_field_lex= { et_field, strlen(et_field) };
|
/* et_field may be NULL if the table is corrupted or out of memory */
|
||||||
DBUG_PRINT("info", ("Current event %s name=%s", et_field,
|
if (et_field)
|
||||||
get_field(thd->mem_root, table->field[ET_FIELD_NAME])));
|
|
||||||
|
|
||||||
if (!sortcmp_lex_string(et_field_lex, field_value, system_charset_info))
|
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("Dropping"));
|
LEX_STRING et_field_lex= { et_field, strlen(et_field) };
|
||||||
ret= table->file->ha_delete_row(table->record[0]);
|
DBUG_PRINT("info", ("Current event %s name=%s", et_field,
|
||||||
|
get_field(thd->mem_root,
|
||||||
|
table->field[ET_FIELD_NAME])));
|
||||||
|
|
||||||
|
if (!sortcmp_lex_string(et_field_lex, field_value, system_charset_info))
|
||||||
|
{
|
||||||
|
DBUG_PRINT("info", ("Dropping"));
|
||||||
|
if ((ret= table->file->ha_delete_row(table->record[0])))
|
||||||
|
table->file->print_error(ret, MYF(0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end_read_record(&read_record_info);
|
end_read_record(&read_record_info);
|
||||||
@ -968,20 +847,14 @@ Event_db_repository::drop_events_by_field(THD *thd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Looks for a named event in mysql.event and then loads it from
|
Looks for a named event in mysql.event and then loads it from
|
||||||
the table, compiles and inserts it into the cache.
|
the table.
|
||||||
|
|
||||||
SYNOPSIS
|
@pre The given thread does not have open tables.
|
||||||
Event_db_repository::load_named_event()
|
|
||||||
thd [in] Thread context
|
|
||||||
dbname [in] Event's db name
|
|
||||||
name [in] Event's name
|
|
||||||
etn [out] The loaded event
|
|
||||||
|
|
||||||
RETURN VALUE
|
@retval FALSE success
|
||||||
FALSE OK
|
@retval TRUE error
|
||||||
TRUE Error (reported)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -989,26 +862,169 @@ Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname,
|
|||||||
LEX_STRING name, Event_basic *etn)
|
LEX_STRING name, Event_basic *etn)
|
||||||
{
|
{
|
||||||
TABLE *table= NULL;
|
TABLE *table= NULL;
|
||||||
int ret= 0;
|
bool ret;
|
||||||
Open_tables_state backup;
|
|
||||||
|
|
||||||
DBUG_ENTER("Event_db_repository::load_named_event");
|
DBUG_ENTER("Event_db_repository::load_named_event");
|
||||||
DBUG_PRINT("enter",("thd: 0x%lx name: %*s", (long) thd, name.length, name.str));
|
DBUG_PRINT("enter",("thd: 0x%lx name: %*s", (long) thd, name.length, name.str));
|
||||||
|
|
||||||
thd->reset_n_backup_open_tables_state(&backup);
|
if (!(ret= open_event_table(thd, TL_READ, &table)))
|
||||||
|
{
|
||||||
|
if ((ret= find_named_event(dbname, name, table)))
|
||||||
|
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str);
|
||||||
|
else if ((ret= etn->load_from_row(thd, table)))
|
||||||
|
my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), "event");
|
||||||
|
|
||||||
if ((ret= open_event_table(thd, TL_READ, &table)))
|
|
||||||
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
|
|
||||||
else if ((ret= find_named_event(thd, dbname, name, table)))
|
|
||||||
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str);
|
|
||||||
else if ((ret= etn->load_from_row(thd, table)))
|
|
||||||
my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), "event");
|
|
||||||
|
|
||||||
if (table)
|
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
|
}
|
||||||
|
|
||||||
thd->restore_backup_open_tables_state(&backup);
|
|
||||||
/* In this case no memory was allocated so we don't need to clean */
|
|
||||||
|
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Update the event record in mysql.event table with a changed status
|
||||||
|
and/or last execution time.
|
||||||
|
|
||||||
|
@pre The thread handle does not have open tables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
Event_db_repository::
|
||||||
|
update_timing_fields_for_event(THD *thd,
|
||||||
|
LEX_STRING event_db_name,
|
||||||
|
LEX_STRING event_name,
|
||||||
|
bool update_last_executed,
|
||||||
|
my_time_t last_executed,
|
||||||
|
bool update_status,
|
||||||
|
ulonglong status)
|
||||||
|
{
|
||||||
|
TABLE *table= NULL;
|
||||||
|
Field **fields;
|
||||||
|
int ret= 1;
|
||||||
|
|
||||||
|
DBUG_ENTER("Event_db_repository::update_timing_fields_for_event");
|
||||||
|
|
||||||
|
if (open_event_table(thd, TL_WRITE, &table))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
fields= table->field;
|
||||||
|
|
||||||
|
if (find_named_event(event_db_name, event_name, table))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
store_record(table, record[1]);
|
||||||
|
/* Don't update create on row update. */
|
||||||
|
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
|
||||||
|
|
||||||
|
if (update_last_executed)
|
||||||
|
{
|
||||||
|
TIME time;
|
||||||
|
my_tz_UTC->gmt_sec_to_TIME(&time, last_executed);
|
||||||
|
|
||||||
|
fields[ET_FIELD_LAST_EXECUTED]->set_notnull();
|
||||||
|
fields[ET_FIELD_LAST_EXECUTED]->store_time(&time,
|
||||||
|
MYSQL_TIMESTAMP_DATETIME);
|
||||||
|
}
|
||||||
|
if (update_status)
|
||||||
|
{
|
||||||
|
fields[ET_FIELD_STATUS]->set_notnull();
|
||||||
|
fields[ET_FIELD_STATUS]->store(status, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret= table->file->ha_update_row(table->record[1], table->record[0])))
|
||||||
|
{
|
||||||
|
table->file->print_error(ret, MYF(0));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret= 0;
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (table)
|
||||||
|
close_thread_tables(thd);
|
||||||
|
|
||||||
|
DBUG_RETURN(test(ret));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Open mysql.db, mysql.user and mysql.event and check whether:
|
||||||
|
- mysql.db exists and is up to date (or from a newer version of MySQL),
|
||||||
|
- mysql.user has column Event_priv at an expected position,
|
||||||
|
- mysql.event exists and is up to date (or from a newer version of
|
||||||
|
MySQL)
|
||||||
|
|
||||||
|
This function is called only when the server is started.
|
||||||
|
@pre The passed in thread handle has no open tables.
|
||||||
|
|
||||||
|
@retval FALSE OK
|
||||||
|
@retval TRUE Error, an error message is output to the error log.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
Event_db_repository::check_system_tables(THD *thd)
|
||||||
|
{
|
||||||
|
TABLE_LIST tables;
|
||||||
|
int ret= FALSE;
|
||||||
|
const unsigned int event_priv_column_position= 29;
|
||||||
|
|
||||||
|
DBUG_ENTER("Event_db_repository::check_system_tables");
|
||||||
|
DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd));
|
||||||
|
|
||||||
|
|
||||||
|
/* Check mysql.db */
|
||||||
|
tables.init_one_table("mysql", "db", TL_READ);
|
||||||
|
|
||||||
|
if (simple_open_n_lock_tables(thd, &tables))
|
||||||
|
{
|
||||||
|
ret= 1;
|
||||||
|
sql_print_error("Cannot open mysql.db");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (table_check_intact(tables.table, MYSQL_DB_FIELD_COUNT,
|
||||||
|
mysql_db_table_fields))
|
||||||
|
ret= 1;
|
||||||
|
/* in case of an error, the message is printed inside table_check_intact */
|
||||||
|
|
||||||
|
close_thread_tables(thd);
|
||||||
|
}
|
||||||
|
/* Check mysql.user */
|
||||||
|
tables.init_one_table("mysql", "user", TL_READ);
|
||||||
|
|
||||||
|
if (simple_open_n_lock_tables(thd, &tables))
|
||||||
|
{
|
||||||
|
ret= 1;
|
||||||
|
sql_print_error("Cannot open mysql.user");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (tables.table->s->fields < event_priv_column_position ||
|
||||||
|
strncmp(tables.table->field[event_priv_column_position]->field_name,
|
||||||
|
STRING_WITH_LEN("Event_priv")))
|
||||||
|
{
|
||||||
|
sql_print_error("mysql.user has no `Event_priv` column at position %d",
|
||||||
|
event_priv_column_position);
|
||||||
|
ret= 1;
|
||||||
|
}
|
||||||
|
close_thread_tables(thd);
|
||||||
|
}
|
||||||
|
/* Check mysql.event */
|
||||||
|
tables.init_one_table("mysql", "event", TL_READ);
|
||||||
|
|
||||||
|
if (simple_open_n_lock_tables(thd, &tables))
|
||||||
|
{
|
||||||
|
ret= 1;
|
||||||
|
sql_print_error("Cannot open mysql.event");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (table_check_intact(tables.table, ET_FIELD_COUNT, event_table_fields))
|
||||||
|
ret= 1;
|
||||||
|
/* in case of an error, the message is printed inside table_check_intact */
|
||||||
|
close_thread_tables(thd);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBUG_RETURN(test(ret));
|
||||||
|
}
|
||||||
|
@ -15,7 +15,12 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
#define EVEX_OPEN_TABLE_FAILED -1
|
/*
|
||||||
|
@file
|
||||||
|
This is a private header file of Events module. Please do not include it
|
||||||
|
directly. All public declarations of Events module should be stored in
|
||||||
|
events.h and event_data_objects.h.
|
||||||
|
*/
|
||||||
|
|
||||||
enum enum_events_table_field
|
enum enum_events_table_field
|
||||||
{
|
{
|
||||||
@ -70,17 +75,28 @@ public:
|
|||||||
drop_schema_events(THD *thd, LEX_STRING schema);
|
drop_schema_events(THD *thd, LEX_STRING schema);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
find_named_event(THD *thd, LEX_STRING db, LEX_STRING name, TABLE *table);
|
find_named_event(LEX_STRING db, LEX_STRING name, TABLE *table);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
load_named_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_basic *et);
|
load_named_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_basic *et);
|
||||||
|
|
||||||
int
|
bool
|
||||||
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
|
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
|
||||||
|
|
||||||
int
|
bool
|
||||||
fill_schema_events(THD *thd, TABLE_LIST *tables, const char *db);
|
fill_schema_events(THD *thd, TABLE_LIST *tables, const char *db);
|
||||||
|
|
||||||
|
bool
|
||||||
|
update_timing_fields_for_event(THD *thd,
|
||||||
|
LEX_STRING event_db_name,
|
||||||
|
LEX_STRING event_name,
|
||||||
|
bool update_last_executed,
|
||||||
|
my_time_t last_executed,
|
||||||
|
bool update_status,
|
||||||
|
ulonglong status);
|
||||||
|
public:
|
||||||
|
static bool
|
||||||
|
check_system_tables(THD *thd);
|
||||||
private:
|
private:
|
||||||
void
|
void
|
||||||
drop_events_by_field(THD *thd, enum enum_events_table_field field,
|
drop_events_by_field(THD *thd, enum enum_events_table_field field,
|
||||||
@ -92,9 +108,7 @@ private:
|
|||||||
bool
|
bool
|
||||||
table_scan_all_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table);
|
table_scan_all_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table);
|
||||||
|
|
||||||
static bool
|
private:
|
||||||
check_system_tables(THD *thd);
|
|
||||||
|
|
||||||
/* Prevent use of these */
|
/* Prevent use of these */
|
||||||
Event_db_repository(const Event_db_repository &);
|
Event_db_repository(const Event_db_repository &);
|
||||||
void operator=(Event_db_repository &);
|
void operator=(Event_db_repository &);
|
||||||
|
@ -72,39 +72,21 @@ event_queue_element_compare_q(void *vptr, byte* a, byte *b)
|
|||||||
Event_queue::Event_queue()
|
Event_queue::Event_queue()
|
||||||
:mutex_last_unlocked_at_line(0), mutex_last_locked_at_line(0),
|
:mutex_last_unlocked_at_line(0), mutex_last_locked_at_line(0),
|
||||||
mutex_last_attempted_lock_at_line(0),
|
mutex_last_attempted_lock_at_line(0),
|
||||||
mutex_queue_data_locked(FALSE), mutex_queue_data_attempting_lock(FALSE)
|
mutex_queue_data_locked(FALSE),
|
||||||
|
mutex_queue_data_attempting_lock(FALSE),
|
||||||
|
next_activation_at(0)
|
||||||
{
|
{
|
||||||
mutex_last_unlocked_in_func= mutex_last_locked_in_func=
|
mutex_last_unlocked_in_func= mutex_last_locked_in_func=
|
||||||
mutex_last_attempted_lock_in_func= "";
|
mutex_last_attempted_lock_in_func= "";
|
||||||
next_activation_at= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Inits mutexes.
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
Event_queue::init_mutexes()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
Event_queue::init_mutexes()
|
|
||||||
{
|
|
||||||
pthread_mutex_init(&LOCK_event_queue, MY_MUTEX_INIT_FAST);
|
pthread_mutex_init(&LOCK_event_queue, MY_MUTEX_INIT_FAST);
|
||||||
pthread_cond_init(&COND_queue_state, NULL);
|
pthread_cond_init(&COND_queue_state, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
Event_queue::~Event_queue()
|
||||||
Destroys mutexes.
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
Event_queue::deinit_mutexes()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
Event_queue::deinit_mutexes()
|
|
||||||
{
|
{
|
||||||
|
deinit_queue();
|
||||||
pthread_mutex_destroy(&LOCK_event_queue);
|
pthread_mutex_destroy(&LOCK_event_queue);
|
||||||
pthread_cond_destroy(&COND_queue_state);
|
pthread_cond_destroy(&COND_queue_state);
|
||||||
}
|
}
|
||||||
@ -176,34 +158,47 @@ Event_queue::deinit_queue()
|
|||||||
/**
|
/**
|
||||||
Adds an event to the queue.
|
Adds an event to the queue.
|
||||||
|
|
||||||
SYNOPSIS
|
Compute the next execution time for an event, and if it is still
|
||||||
Event_queue::create_event()
|
active, add it to the queue. Otherwise delete it.
|
||||||
dbname The schema of the new event
|
The object is left intact in case of an error. Otherwise
|
||||||
name The name of the new event
|
the queue container assumes ownership of it.
|
||||||
|
|
||||||
|
@param[in] thd thread handle
|
||||||
|
@param[in] new_element a new element to add to the queue
|
||||||
|
@param[out] created set to TRUE if no error and the element is
|
||||||
|
added to the queue, FALSE otherwise
|
||||||
|
|
||||||
|
@retval TRUE an error occured. The value of created is undefined,
|
||||||
|
the element was not deleted.
|
||||||
|
@retval FALSE success
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
bool
|
||||||
Event_queue::create_event(THD *thd, Event_queue_element *new_element)
|
Event_queue::create_event(THD *thd, Event_queue_element *new_element,
|
||||||
|
bool *created)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Event_queue::create_event");
|
DBUG_ENTER("Event_queue::create_event");
|
||||||
DBUG_PRINT("enter", ("thd: 0x%lx et=%s.%s", (long) thd,
|
DBUG_PRINT("enter", ("thd: 0x%lx et=%s.%s", (long) thd,
|
||||||
new_element->dbname.str, new_element->name.str));
|
new_element->dbname.str, new_element->name.str));
|
||||||
|
|
||||||
if ((new_element->status == Event_queue_element::DISABLED)
|
/* Will do nothing if the event is disabled */
|
||||||
|| (new_element->status == Event_queue_element::SLAVESIDE_DISABLED))
|
new_element->compute_next_execution_time();
|
||||||
delete new_element;
|
if (new_element->status != Event_queue_element::ENABLED)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
new_element->compute_next_execution_time();
|
delete new_element;
|
||||||
DBUG_PRINT("info", ("new event in the queue: 0x%lx", (long) new_element));
|
*created= FALSE;
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
LOCK_QUEUE_DATA();
|
|
||||||
queue_insert_safe(&queue, (byte *) new_element);
|
|
||||||
dbug_dump_queue(thd->query_start());
|
|
||||||
pthread_cond_broadcast(&COND_queue_state);
|
|
||||||
UNLOCK_QUEUE_DATA();
|
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
|
||||||
|
DBUG_PRINT("info", ("new event in the queue: 0x%lx", (long) new_element));
|
||||||
|
|
||||||
|
LOCK_QUEUE_DATA();
|
||||||
|
*created= (queue_insert_safe(&queue, (byte *) new_element) == FALSE);
|
||||||
|
dbug_dump_queue(thd->query_start());
|
||||||
|
pthread_cond_broadcast(&COND_queue_state);
|
||||||
|
UNLOCK_QUEUE_DATA();
|
||||||
|
|
||||||
|
DBUG_RETURN(!*created);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,23 +25,16 @@ class Event_queue
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Event_queue();
|
Event_queue();
|
||||||
|
~Event_queue();
|
||||||
void
|
|
||||||
init_mutexes();
|
|
||||||
|
|
||||||
void
|
|
||||||
deinit_mutexes();
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
init_queue(THD *thd);
|
init_queue(THD *thd);
|
||||||
|
|
||||||
void
|
|
||||||
deinit_queue();
|
|
||||||
|
|
||||||
/* Methods for queue management follow */
|
/* Methods for queue management follow */
|
||||||
|
|
||||||
void
|
bool
|
||||||
create_event(THD *thd, Event_queue_element *new_element);
|
create_event(THD *thd, Event_queue_element *new_element,
|
||||||
|
bool *created);
|
||||||
|
|
||||||
void
|
void
|
||||||
update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
|
update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
|
||||||
@ -64,9 +57,23 @@ public:
|
|||||||
void
|
void
|
||||||
dump_internal_status();
|
dump_internal_status();
|
||||||
|
|
||||||
|
private:
|
||||||
void
|
void
|
||||||
empty_queue();
|
empty_queue();
|
||||||
protected:
|
|
||||||
|
void
|
||||||
|
deinit_queue();
|
||||||
|
/* helper functions for working with mutexes & conditionals */
|
||||||
|
void
|
||||||
|
lock_data(const char *func, uint line);
|
||||||
|
|
||||||
|
void
|
||||||
|
unlock_data(const char *func, uint line);
|
||||||
|
|
||||||
|
void
|
||||||
|
cond_wait(THD *thd, struct timespec *abstime, const char* msg,
|
||||||
|
const char *func, uint line);
|
||||||
|
|
||||||
void
|
void
|
||||||
find_n_remove_event(LEX_STRING db, LEX_STRING name);
|
find_n_remove_event(LEX_STRING db, LEX_STRING name);
|
||||||
|
|
||||||
@ -98,16 +105,6 @@ protected:
|
|||||||
bool mutex_queue_data_attempting_lock;
|
bool mutex_queue_data_attempting_lock;
|
||||||
bool waiting_on_cond;
|
bool waiting_on_cond;
|
||||||
|
|
||||||
/* helper functions for working with mutexes & conditionals */
|
|
||||||
void
|
|
||||||
lock_data(const char *func, uint line);
|
|
||||||
|
|
||||||
void
|
|
||||||
unlock_data(const char *func, uint line);
|
|
||||||
|
|
||||||
void
|
|
||||||
cond_wait(THD *thd, struct timespec *abstime, const char* msg,
|
|
||||||
const char *func, uint line);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _EVENT_QUEUE_H_ */
|
#endif /* _EVENT_QUEUE_H_ */
|
||||||
|
@ -37,7 +37,6 @@ extern pthread_attr_t connection_attrib;
|
|||||||
|
|
||||||
|
|
||||||
Event_db_repository *Event_worker_thread::db_repository;
|
Event_db_repository *Event_worker_thread::db_repository;
|
||||||
Events *Event_worker_thread::events_facade;
|
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -80,11 +79,11 @@ Event_worker_thread::print_warnings(THD *thd, Event_job_data *et)
|
|||||||
prefix.length(0);
|
prefix.length(0);
|
||||||
prefix.append("Event Scheduler: [");
|
prefix.append("Event Scheduler: [");
|
||||||
|
|
||||||
append_identifier(thd, &prefix, et->definer.str, et->definer.length);
|
prefix.append(et->definer.str, et->definer.length, system_charset_info);
|
||||||
prefix.append("][", 2);
|
prefix.append("][", 2);
|
||||||
append_identifier(thd,&prefix, et->dbname.str, et->dbname.length);
|
prefix.append(et->dbname.str, et->dbname.length, system_charset_info);
|
||||||
prefix.append('.');
|
prefix.append('.');
|
||||||
append_identifier(thd,&prefix, et->name.str, et->name.length);
|
prefix.append(et->name.str, et->name.length, system_charset_info);
|
||||||
prefix.append("] ", 2);
|
prefix.append("] ", 2);
|
||||||
|
|
||||||
List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
|
List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
|
||||||
@ -95,7 +94,6 @@ Event_worker_thread::print_warnings(THD *thd, Event_job_data *et)
|
|||||||
err_msg.length(0);
|
err_msg.length(0);
|
||||||
err_msg.append(prefix);
|
err_msg.append(prefix);
|
||||||
err_msg.append(err->msg, strlen(err->msg), system_charset_info);
|
err_msg.append(err->msg, strlen(err->msg), system_charset_info);
|
||||||
err_msg.append("]");
|
|
||||||
DBUG_ASSERT(err->level < 3);
|
DBUG_ASSERT(err->level < 3);
|
||||||
(sql_print_message_handlers[err->level])("%*s", err_msg.length(),
|
(sql_print_message_handlers[err->level])("%*s", err_msg.length(),
|
||||||
err_msg.c_ptr());
|
err_msg.c_ptr());
|
||||||
@ -239,7 +237,7 @@ event_scheduler_thread(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Function that executes an event in a child thread. Setups the
|
Function that executes an event in a child thread. Setups the
|
||||||
environment for the event execution and cleans after that.
|
environment for the event execution and cleans after that.
|
||||||
|
|
||||||
@ -266,7 +264,7 @@ event_worker_thread(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Function that executes an event in a child thread. Setups the
|
Function that executes an event in a child thread. Setups the
|
||||||
environment for the event execution and cleans after that.
|
environment for the event execution and cleans after that.
|
||||||
|
|
||||||
@ -315,17 +313,27 @@ Event_worker_thread::run(THD *thd, Event_queue_element_for_exec *event)
|
|||||||
|
|
||||||
print_warnings(thd, job_data);
|
print_warnings(thd, job_data);
|
||||||
|
|
||||||
sql_print_information("Event Scheduler: "
|
switch (ret) {
|
||||||
"[%s.%s of %s] executed in thread %lu. "
|
case 0:
|
||||||
"RetCode=%d", job_data->dbname.str, job_data->name.str,
|
|
||||||
job_data->definer.str, thd->thread_id, ret);
|
|
||||||
if (ret == EVEX_COMPILE_ERROR)
|
|
||||||
sql_print_information("Event Scheduler: "
|
sql_print_information("Event Scheduler: "
|
||||||
"COMPILE ERROR for event %s.%s of %s",
|
"[%s].[%s.%s] executed successfully in thread %lu.",
|
||||||
|
job_data->definer.str,
|
||||||
job_data->dbname.str, job_data->name.str,
|
job_data->dbname.str, job_data->name.str,
|
||||||
job_data->definer.str);
|
thd->thread_id);
|
||||||
else if (ret == EVEX_MICROSECOND_UNSUP)
|
break;
|
||||||
sql_print_information("Event Scheduler: MICROSECOND is not supported");
|
case EVEX_COMPILE_ERROR:
|
||||||
|
sql_print_information("Event Scheduler: "
|
||||||
|
"[%s].[%s.%s] event compilation failed.",
|
||||||
|
job_data->definer.str,
|
||||||
|
job_data->dbname.str, job_data->name.str);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sql_print_information("Event Scheduler: "
|
||||||
|
"[%s].[%s.%s] event execution failed.",
|
||||||
|
job_data->definer.str,
|
||||||
|
job_data->dbname.str, job_data->name.str);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
delete job_data;
|
delete job_data;
|
||||||
@ -349,66 +357,34 @@ end:
|
|||||||
problem. However, this comes at the price of introduction bi-directional
|
problem. However, this comes at the price of introduction bi-directional
|
||||||
association between class Events and class Event_worker_thread.
|
association between class Events and class Event_worker_thread.
|
||||||
*/
|
*/
|
||||||
events_facade->drop_event(thd, event->dbname, event->name, FALSE);
|
Events::drop_event(thd, event->dbname, event->name, FALSE);
|
||||||
}
|
}
|
||||||
DBUG_PRINT("info", ("Done with Event %s.%s", event->dbname.str,
|
DBUG_PRINT("info", ("Done with Event %s.%s", event->dbname.str,
|
||||||
event->name.str));
|
event->name.str));
|
||||||
|
|
||||||
delete event;
|
delete event;
|
||||||
deinit_event_thread(thd);
|
deinit_event_thread(thd);
|
||||||
pthread_exit(0);
|
/*
|
||||||
|
Do not pthread_exit since we want local destructors for stack objects
|
||||||
|
to be invoked.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
Event_scheduler::Event_scheduler(Event_queue *queue_arg)
|
||||||
Performs initialization of the scheduler data, outside of the
|
:state(UNINITIALIZED),
|
||||||
threading primitives.
|
scheduler_thd(NULL),
|
||||||
|
queue(queue_arg),
|
||||||
SYNOPSIS
|
started_events(0)
|
||||||
Event_scheduler::init_scheduler()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
Event_scheduler::init_scheduler(Event_queue *q)
|
|
||||||
{
|
|
||||||
LOCK_DATA();
|
|
||||||
queue= q;
|
|
||||||
started_events= 0;
|
|
||||||
scheduler_thd= NULL;
|
|
||||||
state= INITIALIZED;
|
|
||||||
UNLOCK_DATA();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Event_scheduler::deinit_scheduler() {}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Inits scheduler's threading primitives.
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
Event_scheduler::init_mutexes()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
Event_scheduler::init_mutexes()
|
|
||||||
{
|
{
|
||||||
pthread_mutex_init(&LOCK_scheduler_state, MY_MUTEX_INIT_FAST);
|
pthread_mutex_init(&LOCK_scheduler_state, MY_MUTEX_INIT_FAST);
|
||||||
pthread_cond_init(&COND_state, NULL);
|
pthread_cond_init(&COND_state, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
Event_scheduler::~Event_scheduler()
|
||||||
Deinits scheduler's threading primitives.
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
Event_scheduler::deinit_mutexes()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
Event_scheduler::deinit_mutexes()
|
|
||||||
{
|
{
|
||||||
|
stop(); /* does nothing if not running */
|
||||||
pthread_mutex_destroy(&LOCK_scheduler_state);
|
pthread_mutex_destroy(&LOCK_scheduler_state);
|
||||||
pthread_cond_destroy(&COND_state);
|
pthread_cond_destroy(&COND_state);
|
||||||
}
|
}
|
||||||
@ -639,6 +615,9 @@ Event_scheduler::is_running()
|
|||||||
Stops the scheduler (again). Waits for acknowledgement from the
|
Stops the scheduler (again). Waits for acknowledgement from the
|
||||||
scheduler that it has stopped - synchronous stopping.
|
scheduler that it has stopped - synchronous stopping.
|
||||||
|
|
||||||
|
Already running events will not be stopped. If the user needs
|
||||||
|
them stopped manual intervention is needed.
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
Event_scheduler::stop()
|
Event_scheduler::stop()
|
||||||
|
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
/*
|
/**
|
||||||
|
@file
|
||||||
This file is internal to Events module. Please do not include it directly.
|
This file is internal to Events module. Please do not include it directly.
|
||||||
All public declarations of Events module are in events.h and
|
All public declarations of Events module are in events.h and
|
||||||
event_data_objects.h.
|
event_data_objects.h.
|
||||||
@ -41,10 +42,9 @@ class Event_worker_thread
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void
|
static void
|
||||||
init(Events *events, Event_db_repository *db_repo)
|
init(Event_db_repository *db_repository_arg)
|
||||||
{
|
{
|
||||||
db_repository= db_repo;
|
db_repository= db_repository_arg;
|
||||||
events_facade= events;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -55,15 +55,15 @@ private:
|
|||||||
print_warnings(THD *thd, Event_job_data *et);
|
print_warnings(THD *thd, Event_job_data *et);
|
||||||
|
|
||||||
static Event_db_repository *db_repository;
|
static Event_db_repository *db_repository;
|
||||||
static Events *events_facade;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Event_scheduler
|
class Event_scheduler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Event_scheduler():state(UNINITIALIZED){}
|
Event_scheduler(Event_queue *event_queue_arg);
|
||||||
~Event_scheduler(){}
|
~Event_scheduler();
|
||||||
|
|
||||||
|
|
||||||
/* State changing methods follow */
|
/* State changing methods follow */
|
||||||
|
|
||||||
@ -80,17 +80,6 @@ public:
|
|||||||
bool
|
bool
|
||||||
run(THD *thd);
|
run(THD *thd);
|
||||||
|
|
||||||
void
|
|
||||||
init_scheduler(Event_queue *queue);
|
|
||||||
|
|
||||||
void
|
|
||||||
deinit_scheduler();
|
|
||||||
|
|
||||||
void
|
|
||||||
init_mutexes();
|
|
||||||
|
|
||||||
void
|
|
||||||
deinit_mutexes();
|
|
||||||
|
|
||||||
/* Information retrieving methods follow */
|
/* Information retrieving methods follow */
|
||||||
bool
|
bool
|
||||||
|
978
sql/events.cc
978
sql/events.cc
File diff suppressed because it is too large
Load Diff
106
sql/events.h
106
sql/events.h
@ -15,7 +15,11 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
class sp_name;
|
/*
|
||||||
|
@file
|
||||||
|
A public interface of Events Scheduler module.
|
||||||
|
*/
|
||||||
|
|
||||||
class Event_parse_data;
|
class Event_parse_data;
|
||||||
class Event_db_repository;
|
class Event_db_repository;
|
||||||
class Event_queue;
|
class Event_queue;
|
||||||
@ -40,6 +44,22 @@ sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
|
|||||||
/**
|
/**
|
||||||
@class Events -- a facade to the functionality of the Event Scheduler.
|
@class Events -- a facade to the functionality of the Event Scheduler.
|
||||||
|
|
||||||
|
Every public operation against the scheduler has to be executed via the
|
||||||
|
interface provided by a static method of this class. No instance of this
|
||||||
|
class is ever created and it has no non-static data members.
|
||||||
|
|
||||||
|
The life cycle of the Events module is the following:
|
||||||
|
|
||||||
|
At server start up:
|
||||||
|
set_opt_event_scheduler() -> init_mutexes() -> init()
|
||||||
|
When the server is running:
|
||||||
|
create_event(), drop_event(), start_or_stop_event_scheduler(), etc
|
||||||
|
At shutdown:
|
||||||
|
deinit(), destroy_mutexes().
|
||||||
|
|
||||||
|
The peculiar initialization and shutdown cycle is an adaptation to the
|
||||||
|
outside server startup/shutdown framework and mimics the rest of MySQL
|
||||||
|
subsystems (ACL, time zone tables, etc).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Events
|
class Events
|
||||||
@ -53,47 +73,48 @@ public:
|
|||||||
EVENTS_DISABLED= 4
|
EVENTS_DISABLED= 4
|
||||||
};
|
};
|
||||||
|
|
||||||
static enum_opt_event_scheduler opt_event_scheduler;
|
/* Possible values of @@event_scheduler variable */
|
||||||
static TYPELIB opt_typelib;
|
static const TYPELIB var_typelib;
|
||||||
static TYPELIB var_typelib;
|
|
||||||
|
|
||||||
bool
|
static bool
|
||||||
init();
|
set_opt_event_scheduler(char *argument);
|
||||||
|
|
||||||
void
|
static const char *
|
||||||
|
get_opt_event_scheduler_str();
|
||||||
|
|
||||||
|
/* A hack needed for Event_queue_element */
|
||||||
|
static Event_db_repository *
|
||||||
|
get_db_repository() { return db_repository; }
|
||||||
|
|
||||||
|
static bool
|
||||||
|
init(my_bool opt_noacl);
|
||||||
|
|
||||||
|
static void
|
||||||
deinit();
|
deinit();
|
||||||
|
|
||||||
void
|
static void
|
||||||
init_mutexes();
|
init_mutexes();
|
||||||
|
|
||||||
void
|
static void
|
||||||
destroy_mutexes();
|
destroy_mutexes();
|
||||||
|
|
||||||
bool
|
static bool
|
||||||
start_execution_of_events();
|
start_or_stop_event_scheduler(enum enum_opt_event_scheduler start_or_stop);
|
||||||
|
|
||||||
bool
|
static bool
|
||||||
stop_execution_of_events();
|
|
||||||
|
|
||||||
bool
|
|
||||||
is_execution_of_events_started();
|
|
||||||
|
|
||||||
static Events *
|
|
||||||
get_instance();
|
|
||||||
|
|
||||||
bool
|
|
||||||
create_event(THD *thd, Event_parse_data *parse_data, bool if_exists);
|
create_event(THD *thd, Event_parse_data *parse_data, bool if_exists);
|
||||||
|
|
||||||
bool
|
static bool
|
||||||
update_event(THD *thd, Event_parse_data *parse_data, sp_name *rename_to);
|
update_event(THD *thd, Event_parse_data *parse_data,
|
||||||
|
LEX_STRING *new_dbname, LEX_STRING *new_name);
|
||||||
|
|
||||||
bool
|
static bool
|
||||||
drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists);
|
drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists);
|
||||||
|
|
||||||
void
|
static void
|
||||||
drop_schema_events(THD *thd, char *db);
|
drop_schema_events(THD *thd, char *db);
|
||||||
|
|
||||||
bool
|
static bool
|
||||||
show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name);
|
show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name);
|
||||||
|
|
||||||
/* Needed for both SHOW CREATE EVENT and INFORMATION_SCHEMA */
|
/* Needed for both SHOW CREATE EVENT and INFORMATION_SCHEMA */
|
||||||
@ -104,31 +125,28 @@ public:
|
|||||||
static int
|
static int
|
||||||
fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */);
|
fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */);
|
||||||
|
|
||||||
void
|
static void
|
||||||
dump_internal_status();
|
dump_internal_status();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool
|
static bool check_if_system_tables_error();
|
||||||
check_system_tables(THD *thd);
|
|
||||||
|
|
||||||
int
|
static bool
|
||||||
load_events_from_db(THD *thd);
|
load_events_from_db(THD *thd);
|
||||||
|
|
||||||
/* Singleton DP is used */
|
private:
|
||||||
Events();
|
/* Command line option names */
|
||||||
~Events(){}
|
static const TYPELIB opt_typelib;
|
||||||
|
static pthread_mutex_t LOCK_event_metadata;
|
||||||
/* Singleton instance */
|
static Event_queue *event_queue;
|
||||||
static Events singleton;
|
static Event_scheduler *scheduler;
|
||||||
|
static Event_db_repository *db_repository;
|
||||||
Event_queue *event_queue;
|
/* Current state of Event Scheduler */
|
||||||
Event_scheduler *scheduler;
|
static enum enum_opt_event_scheduler opt_event_scheduler;
|
||||||
Event_db_repository *db_repository;
|
/* Set to TRUE if an error at start up */
|
||||||
|
static bool check_system_tables_error;
|
||||||
pthread_mutex_t LOCK_event_metadata;
|
|
||||||
|
|
||||||
bool check_system_tables_error;
|
|
||||||
|
|
||||||
|
private:
|
||||||
/* Prevent use of these */
|
/* Prevent use of these */
|
||||||
Events(const Events &);
|
Events(const Events &);
|
||||||
void operator=(Events &);
|
void operator=(Events &);
|
||||||
|
@ -885,7 +885,7 @@ static void close_connections(void)
|
|||||||
}
|
}
|
||||||
(void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
|
(void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
|
||||||
|
|
||||||
Events::get_instance()->deinit();
|
Events::deinit();
|
||||||
end_slave();
|
end_slave();
|
||||||
|
|
||||||
if (thread_count)
|
if (thread_count)
|
||||||
@ -1330,7 +1330,7 @@ static void clean_up_mutexes()
|
|||||||
(void) pthread_mutex_destroy(&LOCK_bytes_sent);
|
(void) pthread_mutex_destroy(&LOCK_bytes_sent);
|
||||||
(void) pthread_mutex_destroy(&LOCK_bytes_received);
|
(void) pthread_mutex_destroy(&LOCK_bytes_received);
|
||||||
(void) pthread_mutex_destroy(&LOCK_user_conn);
|
(void) pthread_mutex_destroy(&LOCK_user_conn);
|
||||||
Events::get_instance()->destroy_mutexes();
|
Events::destroy_mutexes();
|
||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
(void) pthread_mutex_destroy(&LOCK_des_key_file);
|
(void) pthread_mutex_destroy(&LOCK_des_key_file);
|
||||||
#ifndef HAVE_YASSL
|
#ifndef HAVE_YASSL
|
||||||
@ -3058,7 +3058,7 @@ static int init_thread_environment()
|
|||||||
(void) pthread_mutex_init(&LOCK_server_started, MY_MUTEX_INIT_FAST);
|
(void) pthread_mutex_init(&LOCK_server_started, MY_MUTEX_INIT_FAST);
|
||||||
(void) pthread_cond_init(&COND_server_started,NULL);
|
(void) pthread_cond_init(&COND_server_started,NULL);
|
||||||
sp_cache_init();
|
sp_cache_init();
|
||||||
Events::get_instance()->init_mutexes();
|
Events::init_mutexes();
|
||||||
/* Parameter for threads created for connections */
|
/* Parameter for threads created for connections */
|
||||||
(void) pthread_attr_init(&connection_attrib);
|
(void) pthread_attr_init(&connection_attrib);
|
||||||
(void) pthread_attr_setdetachstate(&connection_attrib,
|
(void) pthread_attr_setdetachstate(&connection_attrib,
|
||||||
@ -3844,21 +3844,15 @@ we force server id to 2, but this MySQL server will not act as a slave.");
|
|||||||
create_shutdown_thread();
|
create_shutdown_thread();
|
||||||
create_maintenance_thread();
|
create_maintenance_thread();
|
||||||
|
|
||||||
|
if (Events::init(opt_noacl))
|
||||||
|
unireg_abort(1);
|
||||||
|
|
||||||
sql_print_information(ER(ER_STARTUP),my_progname,server_version,
|
sql_print_information(ER(ER_STARTUP),my_progname,server_version,
|
||||||
((unix_sock == INVALID_SOCKET) ? (char*) ""
|
((unix_sock == INVALID_SOCKET) ? (char*) ""
|
||||||
: mysqld_unix_port),
|
: mysqld_unix_port),
|
||||||
mysqld_port,
|
mysqld_port,
|
||||||
MYSQL_COMPILATION_COMMENT);
|
MYSQL_COMPILATION_COMMENT);
|
||||||
|
|
||||||
if (!opt_noacl)
|
|
||||||
{
|
|
||||||
if (Events::get_instance()->init())
|
|
||||||
unireg_abort(1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Events::opt_event_scheduler = Events::EVENTS_DISABLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Signal threads waiting for server to be started */
|
/* Signal threads waiting for server to be started */
|
||||||
pthread_mutex_lock(&LOCK_server_started);
|
pthread_mutex_lock(&LOCK_server_started);
|
||||||
@ -7585,32 +7579,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
case OPT_EVENT_SCHEDULER:
|
case OPT_EVENT_SCHEDULER:
|
||||||
if (!argument)
|
if (Events::set_opt_event_scheduler(argument))
|
||||||
Events::opt_event_scheduler= Events::EVENTS_DISABLED;
|
exit(1);
|
||||||
else
|
|
||||||
{
|
|
||||||
int type;
|
|
||||||
/*
|
|
||||||
type= 5 1 2 3 4
|
|
||||||
(DISABLE ) - (OFF | ON) - (0 | 1)
|
|
||||||
*/
|
|
||||||
switch ((type=find_type(argument, &Events::opt_typelib, 1))) {
|
|
||||||
case 0:
|
|
||||||
fprintf(stderr, "Unknown option to event-scheduler: %s\n",argument);
|
|
||||||
exit(1);
|
|
||||||
case 5: /* OPT_DISABLED */
|
|
||||||
Events::opt_event_scheduler= Events::EVENTS_DISABLED;
|
|
||||||
break;
|
|
||||||
case 2: /* OPT_ON */
|
|
||||||
case 4: /* 1 */
|
|
||||||
Events::opt_event_scheduler= Events::EVENTS_ON;
|
|
||||||
break;
|
|
||||||
case 1: /* OPT_OFF */
|
|
||||||
case 3: /* 0 */
|
|
||||||
Events::opt_event_scheduler= Events::EVENTS_OFF;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case (int) OPT_SKIP_NEW:
|
case (int) OPT_SKIP_NEW:
|
||||||
opt_specialflag|= SPECIAL_NO_NEW_FUNC;
|
opt_specialflag|= SPECIAL_NO_NEW_FUNC;
|
||||||
|
@ -1686,7 +1686,7 @@ byte *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool sys_var::check_enum(THD *thd, set_var *var, TYPELIB *enum_names)
|
bool sys_var::check_enum(THD *thd, set_var *var, const TYPELIB *enum_names)
|
||||||
{
|
{
|
||||||
char buff[STRING_BUFFER_USUAL_SIZE];
|
char buff[STRING_BUFFER_USUAL_SIZE];
|
||||||
const char *value;
|
const char *value;
|
||||||
@ -3643,21 +3643,18 @@ bool sys_var_thd_table_type::update(THD *thd, set_var *var)
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
thd in thread handler
|
thd in thread handler
|
||||||
val in sql_mode value
|
val in sql_mode value
|
||||||
len out pointer on length of string
|
rep out pointer pointer to string with sql_mode representation
|
||||||
|
|
||||||
RETURN
|
|
||||||
pointer to string with sql_mode representation
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
byte *sys_var_thd_sql_mode::symbolic_mode_representation(THD *thd,
|
bool
|
||||||
ulonglong val,
|
sys_var_thd_sql_mode::
|
||||||
ulong *len)
|
symbolic_mode_representation(THD *thd, ulonglong val, LEX_STRING *rep)
|
||||||
{
|
{
|
||||||
char buff[256];
|
char buff[STRING_BUFFER_USUAL_SIZE*8];
|
||||||
String tmp(buff, sizeof(buff), &my_charset_latin1);
|
String tmp(buff, sizeof(buff), &my_charset_latin1);
|
||||||
ulong length;
|
|
||||||
|
|
||||||
tmp.length(0);
|
tmp.length(0);
|
||||||
|
|
||||||
for (uint i= 0; val; val>>= 1, i++)
|
for (uint i= 0; val; val>>= 1, i++)
|
||||||
{
|
{
|
||||||
if (val & 1)
|
if (val & 1)
|
||||||
@ -3668,20 +3665,25 @@ byte *sys_var_thd_sql_mode::symbolic_mode_representation(THD *thd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((length= tmp.length()))
|
if (tmp.length())
|
||||||
length--;
|
tmp.length(tmp.length() - 1); /* trim the trailing comma */
|
||||||
*len= length;
|
|
||||||
return (byte*) thd->strmake(tmp.ptr(), length);
|
rep->str= thd->strmake(tmp.ptr(), tmp.length());
|
||||||
|
|
||||||
|
rep->length= rep->str ? tmp.length() : 0;
|
||||||
|
|
||||||
|
return rep->length != tmp.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type,
|
byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type,
|
||||||
LEX_STRING *base)
|
LEX_STRING *base)
|
||||||
{
|
{
|
||||||
|
LEX_STRING sql_mode;
|
||||||
ulonglong val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
|
ulonglong val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
|
||||||
thd->variables.*offset);
|
thd->variables.*offset);
|
||||||
ulong length_unused;
|
(void) symbolic_mode_representation(thd, val, &sql_mode);
|
||||||
return symbolic_mode_representation(thd, val, &length_unused);
|
return sql_mode.str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4012,24 +4014,13 @@ sys_var_event_scheduler::update(THD *thd, set_var *var)
|
|||||||
int res;
|
int res;
|
||||||
/* here start the thread if not running. */
|
/* here start the thread if not running. */
|
||||||
DBUG_ENTER("sys_var_event_scheduler::update");
|
DBUG_ENTER("sys_var_event_scheduler::update");
|
||||||
if (Events::opt_event_scheduler == Events::EVENTS_DISABLED)
|
|
||||||
{
|
|
||||||
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--event-scheduler=DISABLED or --skip-grant-tables");
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
DBUG_PRINT("info", ("new_value: %d", (int) var->save_result.ulong_value));
|
DBUG_PRINT("info", ("new_value: %d", (int) var->save_result.ulong_value));
|
||||||
|
|
||||||
if (var->save_result.ulong_value == Events::EVENTS_ON)
|
enum Events::enum_opt_event_scheduler
|
||||||
res= Events::get_instance()->start_execution_of_events();
|
new_state=
|
||||||
else if (var->save_result.ulong_value == Events::EVENTS_OFF)
|
(enum Events::enum_opt_event_scheduler) var->save_result.ulong_value;
|
||||||
res= Events::get_instance()->stop_execution_of_events();
|
|
||||||
else
|
res= Events::start_or_stop_event_scheduler(new_state);
|
||||||
{
|
|
||||||
assert(0); // Impossible
|
|
||||||
}
|
|
||||||
if (res)
|
|
||||||
my_error(ER_EVENT_SET_VAR_ERROR, MYF(0));
|
|
||||||
|
|
||||||
DBUG_RETURN((bool) res);
|
DBUG_RETURN((bool) res);
|
||||||
}
|
}
|
||||||
@ -4038,15 +4029,7 @@ sys_var_event_scheduler::update(THD *thd, set_var *var)
|
|||||||
byte *sys_var_event_scheduler::value_ptr(THD *thd, enum_var_type type,
|
byte *sys_var_event_scheduler::value_ptr(THD *thd, enum_var_type type,
|
||||||
LEX_STRING *base)
|
LEX_STRING *base)
|
||||||
{
|
{
|
||||||
int state;
|
return (byte *) Events::get_opt_event_scheduler_str();
|
||||||
if (Events::opt_event_scheduler == Events::EVENTS_DISABLED)
|
|
||||||
state= Events::EVENTS_DISABLED; // This should be DISABLED
|
|
||||||
else if (Events::get_instance()->is_execution_of_events_started())
|
|
||||||
state= Events::EVENTS_ON; // This should be ON
|
|
||||||
else
|
|
||||||
state= Events::EVENTS_OFF; // This should be OFF
|
|
||||||
|
|
||||||
return (byte*) Events::opt_typelib.type_names[state];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ public:
|
|||||||
sys_vars++;
|
sys_vars++;
|
||||||
}
|
}
|
||||||
virtual bool check(THD *thd, set_var *var);
|
virtual bool check(THD *thd, set_var *var);
|
||||||
bool check_enum(THD *thd, set_var *var, TYPELIB *enum_names);
|
bool check_enum(THD *thd, set_var *var, const TYPELIB *enum_names);
|
||||||
bool check_set(THD *thd, set_var *var, TYPELIB *enum_names);
|
bool check_set(THD *thd, set_var *var, TYPELIB *enum_names);
|
||||||
virtual bool update(THD *thd, set_var *var)=0;
|
virtual bool update(THD *thd, set_var *var)=0;
|
||||||
virtual void set_default(THD *thd_arg, enum_var_type type) {}
|
virtual void set_default(THD *thd_arg, enum_var_type type) {}
|
||||||
@ -450,8 +450,8 @@ public:
|
|||||||
}
|
}
|
||||||
void set_default(THD *thd, enum_var_type type);
|
void set_default(THD *thd, enum_var_type type);
|
||||||
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
|
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
|
||||||
static byte *symbolic_mode_representation(THD *thd, ulonglong sql_mode,
|
static bool symbolic_mode_representation(THD *thd, ulonglong sql_mode,
|
||||||
ulong *length);
|
LEX_STRING *rep);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -5884,8 +5884,8 @@ ER_COL_COUNT_DOESNT_MATCH_CORRUPTED
|
|||||||
eng "Column count of mysql.%s is wrong. Expected %d, found %d. The table is probably corrupted"
|
eng "Column count of mysql.%s is wrong. Expected %d, found %d. The table is probably corrupted"
|
||||||
ger "Spaltenanzahl von mysql.%s falsch. %d erwartet, aber %d gefunden. Tabelle ist wahrscheinlich besch<63>digt"
|
ger "Spaltenanzahl von mysql.%s falsch. %d erwartet, aber %d gefunden. Tabelle ist wahrscheinlich besch<63>digt"
|
||||||
ER_CANNOT_LOAD_FROM_TABLE
|
ER_CANNOT_LOAD_FROM_TABLE
|
||||||
eng "Cannot load from mysql.%s. The table is probably corrupted. Please see the error log for details"
|
eng "Cannot load from mysql.%s. The table is probably corrupted"
|
||||||
ger "Kann mysql.%s nicht einlesen. Tabelle ist wahrscheinlich besch<63>digt, siehe Fehlerlog"
|
ger "Kann mysql.%s nicht einlesen. Tabelle ist wahrscheinlich besch<63>digt"
|
||||||
ER_EVENT_CANNOT_DELETE
|
ER_EVENT_CANNOT_DELETE
|
||||||
eng "Failed to delete the event from mysql.event"
|
eng "Failed to delete the event from mysql.event"
|
||||||
ger "L<>schen des Events aus mysql.event fehlgeschlagen"
|
ger "L<>schen des Events aus mysql.event fehlgeschlagen"
|
||||||
|
@ -2104,8 +2104,7 @@ sp_head::show_create_procedure(THD *thd)
|
|||||||
String buffer(buff, sizeof(buff), system_charset_info);
|
String buffer(buff, sizeof(buff), system_charset_info);
|
||||||
int res;
|
int res;
|
||||||
List<Item> field_list;
|
List<Item> field_list;
|
||||||
byte *sql_mode_str;
|
LEX_STRING sql_mode;
|
||||||
ulong sql_mode_len;
|
|
||||||
bool full_access;
|
bool full_access;
|
||||||
DBUG_ENTER("sp_head::show_create_procedure");
|
DBUG_ENTER("sp_head::show_create_procedure");
|
||||||
DBUG_PRINT("info", ("procedure %s", m_name.str));
|
DBUG_PRINT("info", ("procedure %s", m_name.str));
|
||||||
@ -2116,12 +2115,10 @@ sp_head::show_create_procedure(THD *thd)
|
|||||||
if (check_show_routine_access(thd, this, &full_access))
|
if (check_show_routine_access(thd, this, &full_access))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
sql_mode_str=
|
sys_var_thd_sql_mode::symbolic_mode_representation(thd, m_sql_mode,
|
||||||
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
|
&sql_mode);
|
||||||
m_sql_mode,
|
|
||||||
&sql_mode_len);
|
|
||||||
field_list.push_back(new Item_empty_string("Procedure", NAME_LEN));
|
field_list.push_back(new Item_empty_string("Procedure", NAME_LEN));
|
||||||
field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len));
|
field_list.push_back(new Item_empty_string("sql_mode", sql_mode.length));
|
||||||
// 1024 is for not to confuse old clients
|
// 1024 is for not to confuse old clients
|
||||||
Item_empty_string *definition=
|
Item_empty_string *definition=
|
||||||
new Item_empty_string("Create Procedure", max(buffer.length(),1024));
|
new Item_empty_string("Create Procedure", max(buffer.length(),1024));
|
||||||
@ -2133,7 +2130,7 @@ sp_head::show_create_procedure(THD *thd)
|
|||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
protocol->prepare_for_resend();
|
protocol->prepare_for_resend();
|
||||||
protocol->store(m_name.str, m_name.length, system_charset_info);
|
protocol->store(m_name.str, m_name.length, system_charset_info);
|
||||||
protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
|
protocol->store((char*) sql_mode.str, sql_mode.length, system_charset_info);
|
||||||
if (full_access)
|
if (full_access)
|
||||||
protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
|
protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
|
||||||
else
|
else
|
||||||
@ -2176,23 +2173,18 @@ sp_head::show_create_function(THD *thd)
|
|||||||
String buffer(buff, sizeof(buff), system_charset_info);
|
String buffer(buff, sizeof(buff), system_charset_info);
|
||||||
int res;
|
int res;
|
||||||
List<Item> field_list;
|
List<Item> field_list;
|
||||||
byte *sql_mode_str;
|
LEX_STRING sql_mode;
|
||||||
ulong sql_mode_len;
|
|
||||||
bool full_access;
|
bool full_access;
|
||||||
DBUG_ENTER("sp_head::show_create_function");
|
DBUG_ENTER("sp_head::show_create_function");
|
||||||
DBUG_PRINT("info", ("procedure %s", m_name.str));
|
DBUG_PRINT("info", ("procedure %s", m_name.str));
|
||||||
LINT_INIT(sql_mode_str);
|
|
||||||
LINT_INIT(sql_mode_len);
|
|
||||||
|
|
||||||
if (check_show_routine_access(thd, this, &full_access))
|
if (check_show_routine_access(thd, this, &full_access))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
sql_mode_str=
|
sys_var_thd_sql_mode::symbolic_mode_representation(thd, m_sql_mode,
|
||||||
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
|
&sql_mode);
|
||||||
m_sql_mode,
|
|
||||||
&sql_mode_len);
|
|
||||||
field_list.push_back(new Item_empty_string("Function",NAME_LEN));
|
field_list.push_back(new Item_empty_string("Function",NAME_LEN));
|
||||||
field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len));
|
field_list.push_back(new Item_empty_string("sql_mode", sql_mode.length));
|
||||||
Item_empty_string *definition=
|
Item_empty_string *definition=
|
||||||
new Item_empty_string("Create Function", max(buffer.length(),1024));
|
new Item_empty_string("Create Function", max(buffer.length(),1024));
|
||||||
definition->maybe_null= TRUE;
|
definition->maybe_null= TRUE;
|
||||||
@ -2203,7 +2195,7 @@ sp_head::show_create_function(THD *thd)
|
|||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
protocol->prepare_for_resend();
|
protocol->prepare_for_resend();
|
||||||
protocol->store(m_name.str, m_name.length, system_charset_info);
|
protocol->store(m_name.str, m_name.length, system_charset_info);
|
||||||
protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
|
protocol->store(sql_mode.str, sql_mode.length, system_charset_info);
|
||||||
if (full_access)
|
if (full_access)
|
||||||
protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
|
protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
|
||||||
else
|
else
|
||||||
|
@ -953,7 +953,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
|
|||||||
|
|
||||||
exit:
|
exit:
|
||||||
(void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */
|
(void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */
|
||||||
Events::get_instance()->drop_schema_events(thd, db);
|
Events::drop_schema_events(thd, db);
|
||||||
/*
|
/*
|
||||||
If this database was the client's selected database, we silently
|
If this database was the client's selected database, we silently
|
||||||
change the client's selected database to nothing (to have an empty
|
change the client's selected database to nothing (to have an empty
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
#include "sp.h"
|
#include "sp.h"
|
||||||
#include "sp_cache.h"
|
#include "sp_cache.h"
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
#include "event_data_objects.h"
|
|
||||||
#include "sql_trigger.h"
|
#include "sql_trigger.h"
|
||||||
|
|
||||||
/* Used in error handling only */
|
/* Used in error handling only */
|
||||||
@ -3181,13 +3180,16 @@ end_with_restore_list:
|
|||||||
|
|
||||||
switch (lex->sql_command) {
|
switch (lex->sql_command) {
|
||||||
case SQLCOM_CREATE_EVENT:
|
case SQLCOM_CREATE_EVENT:
|
||||||
res= Events::get_instance()->
|
{
|
||||||
create_event(thd, lex->event_parse_data,
|
bool if_not_exists= (lex->create_info.options &
|
||||||
lex->create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS);
|
HA_LEX_CREATE_IF_NOT_EXISTS);
|
||||||
|
res= Events::create_event(thd, lex->event_parse_data, if_not_exists);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case SQLCOM_ALTER_EVENT:
|
case SQLCOM_ALTER_EVENT:
|
||||||
res= Events::get_instance()->update_event(thd, lex->event_parse_data,
|
res= Events::update_event(thd, lex->event_parse_data,
|
||||||
lex->spname);
|
lex->spname ? &lex->spname->m_db : NULL,
|
||||||
|
lex->spname ? &lex->spname->m_name : NULL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
@ -3205,39 +3207,16 @@ end_with_restore_list:
|
|||||||
}
|
}
|
||||||
/* lex->unit.cleanup() is called outside, no need to call it here */
|
/* lex->unit.cleanup() is called outside, no need to call it here */
|
||||||
break;
|
break;
|
||||||
case SQLCOM_DROP_EVENT:
|
|
||||||
case SQLCOM_SHOW_CREATE_EVENT:
|
case SQLCOM_SHOW_CREATE_EVENT:
|
||||||
{
|
res= Events::show_create_event(thd, lex->spname->m_db,
|
||||||
DBUG_ASSERT(lex->spname);
|
lex->spname->m_name);
|
||||||
if (! lex->spname->m_db.str)
|
break;
|
||||||
{
|
case SQLCOM_DROP_EVENT:
|
||||||
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
|
if (!(res= Events::drop_event(thd,
|
||||||
goto error;
|
lex->spname->m_db, lex->spname->m_name,
|
||||||
}
|
lex->drop_if_exists)))
|
||||||
if (check_access(thd, EVENT_ACL, lex->spname->m_db.str, 0, 0, 0,
|
send_ok(thd);
|
||||||
is_schema_db(lex->spname->m_db.str)))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (lex->spname->m_name.length > NAME_LEN)
|
|
||||||
{
|
|
||||||
my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
|
|
||||||
/* this jumps to the end of the function and skips own messaging */
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lex->sql_command == SQLCOM_SHOW_CREATE_EVENT)
|
|
||||||
res= Events::get_instance()->show_create_event(thd, lex->spname->m_db,
|
|
||||||
lex->spname->m_name);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!(res= Events::get_instance()->drop_event(thd,
|
|
||||||
lex->spname->m_db,
|
|
||||||
lex->spname->m_name,
|
|
||||||
lex->drop_if_exists)))
|
|
||||||
send_ok(thd);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case SQLCOM_CREATE_FUNCTION: // UDF function
|
case SQLCOM_CREATE_FUNCTION: // UDF function
|
||||||
{
|
{
|
||||||
if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0))
|
if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0))
|
||||||
|
@ -3761,8 +3761,7 @@ static bool store_trigger(THD *thd, TABLE *table, const char *db,
|
|||||||
LEX_STRING *definer_buffer)
|
LEX_STRING *definer_buffer)
|
||||||
{
|
{
|
||||||
CHARSET_INFO *cs= system_charset_info;
|
CHARSET_INFO *cs= system_charset_info;
|
||||||
byte *sql_mode_str;
|
LEX_STRING sql_mode_rep;
|
||||||
ulong sql_mode_len;
|
|
||||||
|
|
||||||
restore_record(table, s->default_values);
|
restore_record(table, s->default_values);
|
||||||
table->field[1]->store(db, strlen(db), cs);
|
table->field[1]->store(db, strlen(db), cs);
|
||||||
@ -3778,11 +3777,9 @@ static bool store_trigger(THD *thd, TABLE *table, const char *db,
|
|||||||
table->field[14]->store(STRING_WITH_LEN("OLD"), cs);
|
table->field[14]->store(STRING_WITH_LEN("OLD"), cs);
|
||||||
table->field[15]->store(STRING_WITH_LEN("NEW"), cs);
|
table->field[15]->store(STRING_WITH_LEN("NEW"), cs);
|
||||||
|
|
||||||
sql_mode_str=
|
sys_var_thd_sql_mode::symbolic_mode_representation(thd, sql_mode,
|
||||||
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
|
&sql_mode_rep);
|
||||||
sql_mode,
|
table->field[17]->store(sql_mode_rep.str, sql_mode_rep.length, cs);
|
||||||
&sql_mode_len);
|
|
||||||
table->field[17]->store((const char*)sql_mode_str, sql_mode_len, cs);
|
|
||||||
table->field[18]->store((const char *)definer_buffer->str, definer_buffer->length, cs);
|
table->field[18]->store((const char *)definer_buffer->str, definer_buffer->length, cs);
|
||||||
return schema_table_store_record(thd, table);
|
return schema_table_store_record(thd, table);
|
||||||
}
|
}
|
||||||
@ -4308,13 +4305,13 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
|
|||||||
CHARSET_INFO *scs= system_charset_info;
|
CHARSET_INFO *scs= system_charset_info;
|
||||||
TIME time;
|
TIME time;
|
||||||
Event_timed et;
|
Event_timed et;
|
||||||
DBUG_ENTER("fill_events_copy_to_schema_tab");
|
DBUG_ENTER("copy_event_to_schema_table");
|
||||||
|
|
||||||
restore_record(sch_table, s->default_values);
|
restore_record(sch_table, s->default_values);
|
||||||
|
|
||||||
if (et.load_from_row(thd, event_table))
|
if (et.load_from_row(thd, event_table))
|
||||||
{
|
{
|
||||||
my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0));
|
my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), event_table->alias);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4349,13 +4346,11 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
|
|||||||
|
|
||||||
/* SQL_MODE */
|
/* SQL_MODE */
|
||||||
{
|
{
|
||||||
byte *sql_mode_str;
|
LEX_STRING sql_mode;
|
||||||
ulong sql_mode_len= 0;
|
sys_var_thd_sql_mode::symbolic_mode_representation(thd, et.sql_mode,
|
||||||
sql_mode_str=
|
&sql_mode);
|
||||||
sys_var_thd_sql_mode::symbolic_mode_representation(thd, et.sql_mode,
|
|
||||||
&sql_mode_len);
|
|
||||||
sch_table->field[ISE_SQL_MODE]->
|
sch_table->field[ISE_SQL_MODE]->
|
||||||
store((const char*)sql_mode_str, sql_mode_len, scs);
|
store(sql_mode.str, sql_mode.length, scs);
|
||||||
}
|
}
|
||||||
|
|
||||||
int not_used=0;
|
int not_used=0;
|
||||||
|
@ -537,6 +537,6 @@ Estimated memory (with thread stack): %ld\n",
|
|||||||
(long) (thread_count * thread_stack + info.hblkhd + info.arena));
|
(long) (thread_count * thread_stack + info.hblkhd + info.arena));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Events::get_instance()->dump_internal_status();
|
Events::dump_internal_status();
|
||||||
puts("");
|
puts("");
|
||||||
}
|
}
|
||||||
|
265
sql/table.cc
265
sql/table.cc
@ -250,7 +250,7 @@ void free_table_share(TABLE_SHARE *share)
|
|||||||
Currently these are:
|
Currently these are:
|
||||||
|
|
||||||
help_category, help_keyword, help_relation, help_topic,
|
help_category, help_keyword, help_relation, help_topic,
|
||||||
proc,
|
proc, event
|
||||||
time_zone, time_zone_leap_second, time_zone_name, time_zone_transition,
|
time_zone, time_zone_leap_second, time_zone_name, time_zone_transition,
|
||||||
time_zone_transition_type
|
time_zone_transition_type
|
||||||
|
|
||||||
@ -283,7 +283,14 @@ inline bool is_system_table_name(const char *name, uint length)
|
|||||||
my_tolower(ci, name[0]) == 't' &&
|
my_tolower(ci, name[0]) == 't' &&
|
||||||
my_tolower(ci, name[1]) == 'i' &&
|
my_tolower(ci, name[1]) == 'i' &&
|
||||||
my_tolower(ci, name[2]) == 'm' &&
|
my_tolower(ci, name[2]) == 'm' &&
|
||||||
my_tolower(ci, name[3]) == 'e'
|
my_tolower(ci, name[3]) == 'e' ||
|
||||||
|
|
||||||
|
/* mysql.event table */
|
||||||
|
my_tolower(ci, name[0]) == 'e' &&
|
||||||
|
my_tolower(ci, name[1]) == 'v' &&
|
||||||
|
my_tolower(ci, name[2]) == 'e' &&
|
||||||
|
my_tolower(ci, name[3]) == 'n' &&
|
||||||
|
my_tolower(ci, name[4]) == 't'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -2432,153 +2439,143 @@ bool check_column_name(const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Checks whether a table is intact. Should be done *just* after the table has
|
Checks whether a table is intact. Should be done *just* after the table has
|
||||||
been opened.
|
been opened.
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
table_check_intact()
|
|
||||||
table The table to check
|
|
||||||
table_f_count Expected number of columns in the table
|
|
||||||
table_def Expected structure of the table (column name and type)
|
|
||||||
last_create_time The table->file->create_time of the table in memory
|
|
||||||
we have checked last time
|
|
||||||
error_num ER_XXXX from the error messages file. When 0 no error
|
|
||||||
is sent to the client in case types does not match.
|
|
||||||
If different col number either
|
|
||||||
ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE or
|
|
||||||
ER_COL_COUNT_DOESNT_MATCH_CORRUPTED is used
|
|
||||||
|
|
||||||
RETURNS
|
@param[in] table The table to check
|
||||||
FALSE OK
|
@param[in] table_f_count Expected number of columns in the table
|
||||||
TRUE There was an error
|
@param[in] table_def Expected structure of the table (column name
|
||||||
|
and type)
|
||||||
|
|
||||||
|
@retval FALSE OK
|
||||||
|
@retval TRUE There was an error. An error message is output
|
||||||
|
to the error log. We do not push an error
|
||||||
|
message into the error stack because this
|
||||||
|
function is currently only called at start up,
|
||||||
|
and such errors never reach the user.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
my_bool
|
my_bool
|
||||||
table_check_intact(TABLE *table, const uint table_f_count,
|
table_check_intact(TABLE *table, const uint table_f_count,
|
||||||
const TABLE_FIELD_W_TYPE *table_def,
|
const TABLE_FIELD_W_TYPE *table_def)
|
||||||
time_t *last_create_time, int error_num)
|
|
||||||
{
|
{
|
||||||
uint i;
|
uint i;
|
||||||
my_bool error= FALSE;
|
my_bool error= FALSE;
|
||||||
my_bool fields_diff_count;
|
my_bool fields_diff_count;
|
||||||
DBUG_ENTER("table_check_intact");
|
DBUG_ENTER("table_check_intact");
|
||||||
DBUG_PRINT("info",("table: %s expected_count: %d last_create_time: %ld",
|
DBUG_PRINT("info",("table: %s expected_count: %d",
|
||||||
table->alias, table_f_count, *last_create_time));
|
table->alias, table_f_count));
|
||||||
|
|
||||||
if ((fields_diff_count= (table->s->fields != table_f_count)) ||
|
|
||||||
(*last_create_time != table->file->stats.create_time))
|
|
||||||
{
|
|
||||||
DBUG_PRINT("info", ("I am suspecting, checking table"));
|
|
||||||
if (fields_diff_count)
|
|
||||||
{
|
|
||||||
/* previous MySQL version */
|
|
||||||
error= TRUE;
|
|
||||||
if (MYSQL_VERSION_ID > table->s->mysql_version)
|
|
||||||
{
|
|
||||||
my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0), table->alias,
|
|
||||||
table_f_count, table->s->fields, table->s->mysql_version,
|
|
||||||
MYSQL_VERSION_ID);
|
|
||||||
sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE),
|
|
||||||
table->alias, table_f_count, table->s->fields,
|
|
||||||
table->s->mysql_version, MYSQL_VERSION_ID);
|
|
||||||
DBUG_RETURN(error);
|
|
||||||
|
|
||||||
}
|
fields_diff_count= (table->s->fields != table_f_count);
|
||||||
else if (MYSQL_VERSION_ID == table->s->mysql_version)
|
if (fields_diff_count)
|
||||||
{
|
|
||||||
my_error(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED,MYF(0), table->alias,
|
|
||||||
table_f_count, table->s->fields);
|
|
||||||
sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED), table->alias,
|
|
||||||
table_f_count, table->s->fields);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Moving from newer mysql to older one -> let's say not an error but
|
|
||||||
will check the definition afterwards. If a column was added at the
|
|
||||||
end then we don't care much since it's not in the middle.
|
|
||||||
*/
|
|
||||||
error= FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* definitely something has changed */
|
|
||||||
char buffer[255];
|
|
||||||
for (i=0 ; i < table_f_count; i++, table_def++)
|
|
||||||
{
|
|
||||||
String sql_type(buffer, sizeof(buffer), system_charset_info);
|
|
||||||
sql_type.length(0);
|
|
||||||
/*
|
|
||||||
Name changes are not fatal, we use sequence numbers => no problem
|
|
||||||
for us but this can show tampered table or broken table.
|
|
||||||
*/
|
|
||||||
if (i < table->s->fields)
|
|
||||||
{
|
|
||||||
Field *field= table->field[i];
|
|
||||||
if (strncmp(field->field_name, table_def->name.str,
|
|
||||||
table_def->name.length))
|
|
||||||
{
|
|
||||||
sql_print_error("(%s) Expected field %s at position %d, found %s",
|
|
||||||
table->alias, table_def->name.str, i,
|
|
||||||
field->field_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
If the type does not match than something is really wrong
|
|
||||||
Check up to length - 1. Why?
|
|
||||||
1. datetime -> datetim -> the same
|
|
||||||
2. int(11) -> int(11 -> the same
|
|
||||||
3. set('one','two') -> set('one','two'
|
|
||||||
so for sets if the same prefix is there it's ok if more are
|
|
||||||
added as part of the set. The same is valid for enum. So a new
|
|
||||||
table running on a old server will be valid.
|
|
||||||
*/
|
|
||||||
field->sql_type(sql_type);
|
|
||||||
if (strncmp(sql_type.c_ptr_safe(), table_def->type.str,
|
|
||||||
table_def->type.length - 1))
|
|
||||||
{
|
|
||||||
sql_print_error("(%s) Expected field %s at position %d to have type "
|
|
||||||
"%s, found %s", table->alias, table_def->name.str,
|
|
||||||
i, table_def->type.str, sql_type.c_ptr_safe());
|
|
||||||
error= TRUE;
|
|
||||||
}
|
|
||||||
else if (table_def->cset.str && !field->has_charset())
|
|
||||||
{
|
|
||||||
sql_print_error("(%s) Expected field %s at position %d to have "
|
|
||||||
"character set '%s' but found no such", table->alias,
|
|
||||||
table_def->name.str, i, table_def->cset.str);
|
|
||||||
error= TRUE;
|
|
||||||
}
|
|
||||||
else if (table_def->cset.str &&
|
|
||||||
strcmp(field->charset()->csname, table_def->cset.str))
|
|
||||||
{
|
|
||||||
sql_print_error("(%s) Expected field %s at position %d to have "
|
|
||||||
"character set '%s' but found '%s'", table->alias,
|
|
||||||
table_def->name.str, i, table_def->cset.str,
|
|
||||||
field->charset()->csname);
|
|
||||||
error= TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sql_print_error("(%s) Expected field %s at position %d to have type %s "
|
|
||||||
" but no field found.", table->alias,
|
|
||||||
table_def->name.str, i, table_def->type.str);
|
|
||||||
error= TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!error)
|
|
||||||
*last_create_time= table->file->stats.create_time;
|
|
||||||
else if (!fields_diff_count && error_num)
|
|
||||||
my_error(error_num,MYF(0), table->alias, table_f_count, table->s->fields);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("Table seems ok without thorough checking."));
|
DBUG_PRINT("info", ("Column count has changed, checking the definition"));
|
||||||
*last_create_time= table->file->stats.create_time;
|
|
||||||
|
/* previous MySQL version */
|
||||||
|
if (MYSQL_VERSION_ID > table->s->mysql_version)
|
||||||
|
{
|
||||||
|
sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE),
|
||||||
|
table->alias, table_f_count, table->s->fields,
|
||||||
|
table->s->mysql_version, MYSQL_VERSION_ID);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
else if (MYSQL_VERSION_ID == table->s->mysql_version)
|
||||||
|
{
|
||||||
|
sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED), table->alias,
|
||||||
|
table_f_count, table->s->fields);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Something has definitely changed, but we're running an older
|
||||||
|
version of MySQL with new system tables.
|
||||||
|
Let's check column definitions. If a column was added at
|
||||||
|
the end of the table, then we don't care much since such change
|
||||||
|
is backward compatible.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
char buffer[STRING_BUFFER_USUAL_SIZE];
|
||||||
DBUG_RETURN(error);
|
for (i=0 ; i < table_f_count; i++, table_def++)
|
||||||
|
{
|
||||||
|
String sql_type(buffer, sizeof(buffer), system_charset_info);
|
||||||
|
sql_type.length(0);
|
||||||
|
if (i < table->s->fields)
|
||||||
|
{
|
||||||
|
Field *field= table->field[i];
|
||||||
|
|
||||||
|
if (strncmp(field->field_name, table_def->name.str,
|
||||||
|
table_def->name.length))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Name changes are not fatal, we use ordinal numbers to access columns.
|
||||||
|
Still this can be a sign of a tampered table, output an error
|
||||||
|
to the error log.
|
||||||
|
*/
|
||||||
|
sql_print_error("Incorrect definition of table %s.%s: "
|
||||||
|
"expected column '%s' at position %d, found '%s'.",
|
||||||
|
table->s->db.str, table->alias, table_def->name.str, i,
|
||||||
|
field->field_name);
|
||||||
|
}
|
||||||
|
field->sql_type(sql_type);
|
||||||
|
/*
|
||||||
|
Generally, if column types don't match, then something is
|
||||||
|
wrong.
|
||||||
|
|
||||||
|
However, we only compare column definitions up to the
|
||||||
|
length of the original definition, since we consider the
|
||||||
|
following definitions compatible:
|
||||||
|
|
||||||
|
1. DATETIME and DATETIM
|
||||||
|
2. INT(11) and INT(11
|
||||||
|
3. SET('one', 'two') and SET('one', 'two', 'more')
|
||||||
|
|
||||||
|
For SETs or ENUMs, if the same prefix is there it's OK to
|
||||||
|
add more elements - they will get higher ordinal numbers and
|
||||||
|
the new table definition is backward compatible with the
|
||||||
|
original one.
|
||||||
|
*/
|
||||||
|
if (strncmp(sql_type.c_ptr_safe(), table_def->type.str,
|
||||||
|
table_def->type.length - 1))
|
||||||
|
{
|
||||||
|
sql_print_error("Incorrect definition of table %s.%s: "
|
||||||
|
"expected column '%s' at position %d to have type "
|
||||||
|
"%s, found type %s.", table->s->db.str, table->alias,
|
||||||
|
table_def->name.str, i, table_def->type.str,
|
||||||
|
sql_type.c_ptr_safe());
|
||||||
|
error= TRUE;
|
||||||
|
}
|
||||||
|
else if (table_def->cset.str && !field->has_charset())
|
||||||
|
{
|
||||||
|
sql_print_error("Incorrect definition of table %s.%s: "
|
||||||
|
"expected the type of column '%s' at position %d "
|
||||||
|
"to have character set '%s' but the type has no "
|
||||||
|
"character set.", table->s->db.str, table->alias,
|
||||||
|
table_def->name.str, i, table_def->cset.str);
|
||||||
|
error= TRUE;
|
||||||
|
}
|
||||||
|
else if (table_def->cset.str &&
|
||||||
|
strcmp(field->charset()->csname, table_def->cset.str))
|
||||||
|
{
|
||||||
|
sql_print_error("Incorrect definition of table %s.%s: "
|
||||||
|
"expected the type of column '%s' at position %d "
|
||||||
|
"to have character set '%s' but found "
|
||||||
|
"character set '%s'.", table->s->db.str, table->alias,
|
||||||
|
table_def->name.str, i, table_def->cset.str,
|
||||||
|
field->charset()->csname);
|
||||||
|
error= TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sql_print_error("Incorrect definition of table %s.%s: "
|
||||||
|
"expected column '%s' at position %d to have type %s "
|
||||||
|
" but the column is not found.",
|
||||||
|
table->s->db.str, table->alias,
|
||||||
|
table_def->name.str, i, table_def->type.str);
|
||||||
|
error= TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
18
sql/table.h
18
sql/table.h
@ -689,6 +689,21 @@ class index_hint;
|
|||||||
typedef struct st_table_list
|
typedef struct st_table_list
|
||||||
{
|
{
|
||||||
st_table_list() {} /* Remove gcc warning */
|
st_table_list() {} /* Remove gcc warning */
|
||||||
|
|
||||||
|
/**
|
||||||
|
Prepare TABLE_LIST that consists of one table instance to use in
|
||||||
|
simple_open_and_lock_tables
|
||||||
|
*/
|
||||||
|
inline void init_one_table(const char *db_name_arg,
|
||||||
|
const char *table_name_arg,
|
||||||
|
enum thr_lock_type lock_type_arg)
|
||||||
|
{
|
||||||
|
bzero((char*) this, sizeof(*this));
|
||||||
|
db= (char*) db_name_arg;
|
||||||
|
table_name= alias= (char*) table_name_arg;
|
||||||
|
lock_type= lock_type_arg;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
List of tables local to a subquery (used by SQL_LIST). Considers
|
List of tables local to a subquery (used by SQL_LIST). Considers
|
||||||
views as leaves (unlike 'next_leaf' below). Created at parse time
|
views as leaves (unlike 'next_leaf' below). Created at parse time
|
||||||
@ -1097,8 +1112,7 @@ typedef struct st_table_field_w_type
|
|||||||
|
|
||||||
my_bool
|
my_bool
|
||||||
table_check_intact(TABLE *table, const uint table_f_count,
|
table_check_intact(TABLE *table, const uint table_f_count,
|
||||||
const TABLE_FIELD_W_TYPE *table_def,
|
const TABLE_FIELD_W_TYPE *table_def);
|
||||||
time_t *last_create_time, int error_num);
|
|
||||||
|
|
||||||
static inline my_bitmap_map *tmp_use_all_columns(TABLE *table,
|
static inline my_bitmap_map *tmp_use_all_columns(TABLE *table,
|
||||||
MY_BITMAP *bitmap)
|
MY_BITMAP *bitmap)
|
||||||
|
Reference in New Issue
Block a user