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;
|
||||
CREATE USER pauline@localhost;
|
||||
CREATE DATABASE db_x;
|
||||
@ -193,7 +197,7 @@ create event
|
||||
SHOW CREATE EVENT <20><><EFBFBD><EFBFBD>21;
|
||||
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
|
||||
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;
|
||||
ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
|
||||
SHOW EVENTS;
|
||||
@ -223,73 +227,180 @@ drop event root19;
|
||||
drop event root20;
|
||||
drop event <20><><EFBFBD><EFBFBD>21;
|
||||
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";
|
||||
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
|
||||
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
|
||||
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;
|
||||
SHOW EVENTS;
|
||||
ERROR HY000: Column count of mysql.event is wrong. Expected 18, found 19. The table is probably corrupted
|
||||
ALTER TABLE mysql.event DROP dummy, ADD dummy2 VARCHAR(64) FIRST;
|
||||
SHOW EVENTS;
|
||||
ERROR HY000: Column count of mysql.event is wrong. Expected 18, found 19. The table is probably corrupted
|
||||
ALTER TABLE mysql.event DROP dummy2;
|
||||
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
|
||||
ERROR HY000: Cannot load from mysql.event. The table is probably corrupted
|
||||
SELECT event_name FROM INFORMATION_SCHEMA.events;
|
||||
ERROR HY000: Cannot load from mysql.event. The table is probably corrupted
|
||||
SHOW CREATE EVENT intact_check;
|
||||
ERROR HY000: Unknown event 'intact_check'
|
||||
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: 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;
|
||||
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;
|
||||
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
|
||||
|
||||
Drop some columns and try more checks.
|
||||
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
INSERT INTO mysql.event SELECT * FROM event_like;
|
||||
DROP TABLE event_like;
|
||||
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
|
||||
DROP EVENT intact_check;
|
||||
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
|
||||
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;
|
||||
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 ``;
|
||||
ERROR 42000: Incorrect database name ''
|
||||
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;
|
||||
|
@ -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;
|
||||
CREATE EVENT lower_case ON SCHEDULE EVERY 1 MINUTE DO SELECT 1;
|
||||
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;
|
||||
ERROR HY000: Unknown event 'e1'
|
||||
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;
|
||||
|
@ -1,12 +1,16 @@
|
||||
create database if not exists mysqltest_events_test;
|
||||
use mysqltest_events_test;
|
||||
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 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');
|
||||
select name from execution_log;
|
||||
name
|
||||
insert into mysql.event values ('db1','bad','select 42','root@localhost',NULL,1000,'MICROSECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment1',1,'SYSTEM');
|
||||
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 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');
|
||||
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"
|
||||
|
@ -1,6 +1,42 @@
|
||||
use mysqltest_events_test;
|
||||
"Should get 0 rows because the queue aborted run
|
||||
select distinct name from execution_log order by name;
|
||||
name
|
||||
delete from mysql.event where name like 'bad%';
|
||||
"Now restart the server again"
|
||||
use events_test;
|
||||
select @@event_scheduler;
|
||||
@@event_scheduler
|
||||
DISABLED
|
||||
show events;
|
||||
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
|
||||
select distinct name from execution_log order by name;
|
||||
name
|
||||
abc1
|
||||
abc2
|
||||
abc3
|
||||
drop event abc1;
|
||||
drop event abc2;
|
||||
drop event abc3;
|
||||
drop table execution_log;
|
||||
drop database mysqltest_events_test;
|
||||
drop database events_test;
|
||||
|
@ -1,6 +1,8 @@
|
||||
CREATE DATABASE IF NOT EXISTS events_test;
|
||||
USE events_test;
|
||||
SET GLOBAL event_scheduler=OFF;
|
||||
Try agian to make sure it's allowed
|
||||
SET GLOBAL event_scheduler=OFF;
|
||||
SHOW VARIABLES LIKE 'event_scheduler';
|
||||
Variable_name Value
|
||||
event_scheduler OFF
|
||||
@ -13,6 +15,8 @@ SHOW VARIABLES LIKE 'event_scheduler';
|
||||
Variable_name Value
|
||||
event_scheduler OFF
|
||||
SET GLOBAL event_scheduler=ON;
|
||||
Try again to make sure it's allowed
|
||||
SET GLOBAL event_scheduler=ON;
|
||||
SHOW VARIABLES LIKE 'event_scheduler';
|
||||
Variable_name Value
|
||||
event_scheduler ON
|
||||
|
@ -3,148 +3,6 @@ CREATE DATABASE mysqltest_db1;
|
||||
USE mysqltest_db1;
|
||||
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 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);
|
||||
INSERT INTO t_step VALUES (@step);
|
||||
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
|
||||
-- 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;
|
||||
|
||||
#
|
||||
@ -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";
|
||||
--replace_column 8 # 9 #
|
||||
SHOW EVENTS;
|
||||
ALTER TABLE mysql.event ADD dummy INT FIRST;
|
||||
--error ER_COL_COUNT_DOESNT_MATCH_CORRUPTED
|
||||
SHOW EVENTS;
|
||||
ALTER TABLE mysql.event DROP dummy, ADD dummy2 VARCHAR(64) FIRST;
|
||||
--error ER_COL_COUNT_DOESNT_MATCH_CORRUPTED
|
||||
SHOW EVENTS;
|
||||
ALTER TABLE mysql.event DROP dummy2;
|
||||
#
|
||||
--echo Try to alter mysql.event: the server should fail to load
|
||||
--echo event information after mysql.event was tampered with.
|
||||
--echo
|
||||
--echo First, let's add a column to the end and make sure everything
|
||||
--echo works as before
|
||||
--echo
|
||||
ALTER TABLE mysql.event ADD dummy INT;
|
||||
--replace_column 8 # 9 #
|
||||
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;
|
||||
INSERT INTO event_like SELECT * FROM mysql.event;
|
||||
#sleep a bit or we won't catch the change of time
|
||||
--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;
|
||||
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
|
||||
--echo
|
||||
--echo Drop some columns and try more checks.
|
||||
--echo
|
||||
--echo
|
||||
ALTER TABLE mysql.event DROP comment, DROP starts;
|
||||
--sleep 1.1
|
||||
--error ER_COL_COUNT_DOESNT_MATCH_CORRUPTED
|
||||
--error ER_CANNOT_LOAD_FROM_TABLE
|
||||
SHOW EVENTS;
|
||||
--error ER_CANNOT_LOAD_FROM_TABLE
|
||||
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;
|
||||
--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;
|
||||
INSERT INTO mysql.event SELECT * FROM event_like;
|
||||
DROP TABLE event_like;
|
||||
--replace_column 8 # 9 #
|
||||
SHOW EVENTS;
|
||||
DROP EVENT intact_check;
|
||||
#
|
||||
# mysql.event intact checking end
|
||||
#
|
||||
@ -424,5 +529,200 @@ SHOW EVENTS FROM aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
SHOW EVENTS FROM ``;
|
||||
|
||||
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;
|
||||
|
@ -1,7 +1,12 @@
|
||||
# Can't test with embedded server that doesn't support grants
|
||||
-- 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;
|
||||
|
||||
#
|
||||
@ -428,6 +433,184 @@ connection default;
|
||||
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
|
||||
#
|
||||
|
@ -1,19 +1,43 @@
|
||||
# Can't test with embedded server that doesn't support grants
|
||||
-- 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
|
||||
create database if not exists mysqltest_events_test;
|
||||
drop database if exists events_test;
|
||||
--enable_warnings
|
||||
|
||||
use mysqltest_events_test;
|
||||
set global event_scheduler=off;
|
||||
create database events_test;
|
||||
use events_test;
|
||||
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');
|
||||
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 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');
|
||||
#
|
||||
# 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"
|
||||
|
@ -1,9 +1,41 @@
|
||||
# Can't test with embedded server that doesn't support grants
|
||||
-- source include/not_embedded.inc
|
||||
|
||||
use mysqltest_events_test;
|
||||
--sleep 1.5
|
||||
--echo "Should get 0 rows because the queue aborted run
|
||||
select distinct name from execution_log order by name;
|
||||
delete from mysql.event where name like 'bad%';
|
||||
--echo "Now restart the server again"
|
||||
use events_test;
|
||||
# Event scheduler should be disabled: the system tables are damaged
|
||||
select @@event_scheduler;
|
||||
# Try various Event Scheduler operation and check the output.
|
||||
--error ER_EVENTS_DB_ERROR
|
||||
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
|
||||
-- source include/not_embedded.inc
|
||||
|
||||
use mysqltest_events_test;
|
||||
--sleep 2
|
||||
#
|
||||
# We need this file primarily to make sure that the scheduler is restarted
|
||||
# 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
|
||||
select distinct name from execution_log order by name;
|
||||
|
||||
drop event abc1;
|
||||
drop event abc2;
|
||||
drop event abc3;
|
||||
drop table execution_log;
|
||||
|
||||
drop database mysqltest_events_test;
|
||||
# Will drop all events
|
||||
drop database events_test;
|
||||
|
@ -5,6 +5,8 @@
|
||||
CREATE DATABASE IF NOT EXISTS events_test;
|
||||
USE events_test;
|
||||
|
||||
SET GLOBAL event_scheduler=OFF;
|
||||
--echo Try agian to make sure it's allowed
|
||||
SET GLOBAL event_scheduler=OFF;
|
||||
SHOW VARIABLES LIKE 'event_scheduler';
|
||||
SET GLOBAL event_scheduler=1;
|
||||
@ -12,6 +14,8 @@ SHOW VARIABLES LIKE 'event_scheduler';
|
||||
SET GLOBAL event_scheduler=0;
|
||||
SHOW VARIABLES LIKE 'event_scheduler';
|
||||
SET GLOBAL event_scheduler=ON;
|
||||
--echo Try again to make sure it's allowed
|
||||
SET GLOBAL event_scheduler=ON;
|
||||
SHOW VARIABLES LIKE 'event_scheduler';
|
||||
--error ER_WRONG_VALUE_FOR_VAR
|
||||
SET GLOBAL event_scheduler=DISABLED;
|
||||
|
@ -20,6 +20,7 @@ let $old_db= `SELECT DATABASE()`;
|
||||
USE mysqltest_db1;
|
||||
|
||||
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
|
||||
#
|
||||
|
||||
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.
|
||||
|
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 "sp_head.h"
|
||||
|
||||
/* That's a provisional solution */
|
||||
extern Event_db_repository events_event_db_repository;
|
||||
|
||||
#define EVEX_MAX_INTERVAL_VALUE 1000000000L
|
||||
|
||||
@ -101,8 +99,7 @@ Event_parse_data::new_instance(THD *thd)
|
||||
*/
|
||||
|
||||
Event_parse_data::Event_parse_data()
|
||||
:on_completion(Event_basic::ON_COMPLETION_DROP),
|
||||
status(Event_basic::ENABLED), do_not_create(FALSE),
|
||||
:on_completion(ON_COMPLETION_DROP), status(ENABLED), do_not_create(FALSE),
|
||||
item_starts(NULL), item_ends(NULL), item_execute_at(NULL),
|
||||
starts_null(TRUE), ends_null(TRUE), execute_at_null(TRUE),
|
||||
item_expression(NULL), expression(0)
|
||||
@ -216,7 +213,7 @@ Event_parse_data::init_body(THD *thd)
|
||||
++body_begin;
|
||||
--body.length;
|
||||
}
|
||||
body.str= thd->strmake((char *)body_begin, body.length);
|
||||
body.str= thd->strmake(body_begin, body.length);
|
||||
|
||||
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())
|
||||
return;
|
||||
|
||||
if (on_completion == Event_basic::ON_COMPLETION_DROP)
|
||||
if (on_completion == ON_COMPLETION_DROP)
|
||||
{
|
||||
switch (thd->lex->sql_command) {
|
||||
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;
|
||||
}
|
||||
else if (status == Event_basic::ENABLED)
|
||||
else if (status == ENABLED)
|
||||
{
|
||||
status= Event_basic::DISABLED;
|
||||
status= DISABLED;
|
||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
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_definer(thd);
|
||||
|
||||
ret= init_execute_at(thd) || init_interval(thd) || init_starts(thd) ||
|
||||
init_ends(thd);
|
||||
check_originator_id(thd);
|
||||
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
|
||||
|
||||
@ -720,7 +692,7 @@ Event_basic::load_string_fields(Field **fields, ...)
|
||||
|
||||
va_start(args, fields);
|
||||
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 *);
|
||||
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)
|
||||
goto error;
|
||||
|
||||
if (table->s->fields != ET_FIELD_COUNT)
|
||||
if (table->s->fields < ET_FIELD_COUNT)
|
||||
goto error;
|
||||
|
||||
LEX_STRING tz_name;
|
||||
load_string_fields(table->field, ET_FIELD_DB, &dbname, ET_FIELD_NAME, &name,
|
||||
ET_FIELD_BODY, &body, ET_FIELD_DEFINER, &definer,
|
||||
ET_FIELD_TIME_ZONE, &tz_name, ET_FIELD_COUNT);
|
||||
if (load_string_fields(table->field,
|
||||
ET_FIELD_DB, &dbname,
|
||||
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))
|
||||
goto error;
|
||||
|
||||
@ -936,19 +914,24 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
|
||||
{
|
||||
char *ptr;
|
||||
TIME time;
|
||||
LEX_STRING tz_name;
|
||||
|
||||
DBUG_ENTER("Event_queue_element::load_from_row");
|
||||
|
||||
if (!table)
|
||||
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;
|
||||
|
||||
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))
|
||||
goto error;
|
||||
|
||||
@ -1021,23 +1004,8 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
|
||||
goto error;
|
||||
|
||||
DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", name.str, ptr));
|
||||
|
||||
/* Set event status (ENABLED | SLAVESIDE_DISABLED | DISABLED) */
|
||||
switch (ptr[0])
|
||||
{
|
||||
case 'E' :
|
||||
status = Event_queue_element::ENABLED;
|
||||
break;
|
||||
case 'S' :
|
||||
status = Event_queue_element::SLAVESIDE_DISABLED;
|
||||
break;
|
||||
case 'D' :
|
||||
status = Event_queue_element::DISABLED;
|
||||
break;
|
||||
}
|
||||
if ((ptr= get_field(&mem_root, table->field[ET_FIELD_ORIGINATOR])) == NullS)
|
||||
goto error;
|
||||
originator = table->field[ET_FIELD_ORIGINATOR]->val_int();
|
||||
status= (ptr[0]=='E'? Event_queue_element::ENABLED:
|
||||
Event_queue_element::DISABLED);
|
||||
|
||||
/* ToDo : Andrey . Find a way not to allocate ptr on event_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))
|
||||
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, '@');
|
||||
|
||||
@ -1384,7 +1356,7 @@ Event_queue_element::compute_next_execution_time()
|
||||
(long) starts, (long) ends, (long) last_executed,
|
||||
(long) this));
|
||||
|
||||
if (status != Event_queue_element::ENABLED)
|
||||
if (status == Event_queue_element::DISABLED)
|
||||
{
|
||||
DBUG_PRINT("compute_next_execution_time",
|
||||
("Event %s is DISABLED", name.str));
|
||||
@ -1635,10 +1607,8 @@ Event_queue_element::mark_last_executed(THD *thd)
|
||||
bool
|
||||
Event_queue_element::update_timing_fields(THD *thd)
|
||||
{
|
||||
TABLE *table;
|
||||
Field **fields;
|
||||
Open_tables_state backup;
|
||||
int ret= FALSE;
|
||||
Event_db_repository *db_repository= Events::get_db_repository();
|
||||
int ret;
|
||||
|
||||
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))
|
||||
DBUG_RETURN(0);
|
||||
|
||||
thd->reset_n_backup_open_tables_state(&backup);
|
||||
|
||||
if (events_event_db_repository.open_event_table(thd, TL_WRITE, &table))
|
||||
{
|
||||
ret= TRUE;
|
||||
goto done;
|
||||
}
|
||||
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);
|
||||
|
||||
ret= db_repository->update_timing_fields_for_event(thd,
|
||||
dbname, name,
|
||||
last_executed_changed,
|
||||
last_executed,
|
||||
status_changed,
|
||||
(ulonglong) status);
|
||||
last_executed_changed= status_changed= FALSE;
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
|
||||
@ -1778,8 +1708,6 @@ Event_timed::get_create_event(THD *thd, String *buf)
|
||||
|
||||
if (status == Event_timed::ENABLED)
|
||||
buf->append(STRING_WITH_LEN("ENABLE"));
|
||||
else if (status == Event_timed::SLAVESIDE_DISABLED)
|
||||
buf->append(STRING_WITH_LEN("SLAVESIDE_DISABLE"));
|
||||
else
|
||||
buf->append(STRING_WITH_LEN("DISABLE"));
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
#define EVEX_GET_FIELD_FAILED -2
|
||||
#define EVEX_COMPILE_ERROR -3
|
||||
#define EVEX_GENERAL_ERROR -4
|
||||
#define EVEX_BAD_PARAMS -5
|
||||
#define EVEX_MICROSECOND_UNSUP -6
|
||||
|
||||
@ -178,8 +177,6 @@ public:
|
||||
|
||||
ulong sql_mode;
|
||||
|
||||
uint execution_count;
|
||||
|
||||
Event_job_data();
|
||||
virtual ~Event_job_data();
|
||||
|
||||
|
@ -18,12 +18,6 @@
|
||||
#include "event_data_objects.h"
|
||||
#include "events.h"
|
||||
#include "sql_show.h"
|
||||
#include "sp.h"
|
||||
#include "sp_head.h"
|
||||
|
||||
|
||||
static
|
||||
time_t mysql_event_last_create_time= 0L;
|
||||
|
||||
static
|
||||
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.
|
||||
|
||||
SYNOPSIS
|
||||
mysql_event_fill_row()
|
||||
thd THD
|
||||
table The row to fill out
|
||||
et Event's data
|
||||
is_update CREATE EVENT or ALTER EVENT
|
||||
Used both when an event is created and when it is altered.
|
||||
|
||||
RETURN VALUE
|
||||
0 OK
|
||||
EVEX_GENERAL_ERROR Bad data
|
||||
EVEX_GET_FIELD_FAILED Field count does not match. table corrupted?
|
||||
@param thd THD
|
||||
@param table The row to fill out
|
||||
@param et Event's data
|
||||
@param is_update CREATE EVENT or ALTER EVENT
|
||||
|
||||
DESCRIPTION
|
||||
Used both when an event is created and when it is altered.
|
||||
@retval FALSE success
|
||||
@retval TRUE error
|
||||
*/
|
||||
|
||||
static int
|
||||
static bool
|
||||
mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et,
|
||||
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", ("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]->
|
||||
store(et->definer.str, et->definer.length, scs))
|
||||
goto err_truncate;
|
||||
@ -271,11 +271,11 @@ mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et,
|
||||
goto err_truncate;
|
||||
}
|
||||
|
||||
DBUG_RETURN(0);
|
||||
DBUG_RETURN(FALSE);
|
||||
|
||||
err_truncate:
|
||||
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
|
||||
SHOW EVENTS
|
||||
|
||||
SYNOPSIS
|
||||
Event_db_repository::fill_schema_events()
|
||||
thd Thread
|
||||
tables The schema table
|
||||
db If not NULL then get events only from this schema
|
||||
The reason we reset and backup open tables here is that this
|
||||
function may be called from any query that accesses
|
||||
INFORMATION_SCHEMA - including a query that is issued from
|
||||
a pre-locked statement, one that already has open and locked
|
||||
tables.
|
||||
|
||||
RETURN VALUE
|
||||
FALSE OK
|
||||
TRUE Error
|
||||
@retval FALSE success
|
||||
@retval TRUE error
|
||||
*/
|
||||
|
||||
int
|
||||
bool
|
||||
Event_db_repository::fill_schema_events(THD *thd, TABLE_LIST *tables,
|
||||
const char *db)
|
||||
{
|
||||
TABLE *schema_table= tables->table;
|
||||
TABLE *event_table= NULL;
|
||||
Open_tables_state backup;
|
||||
int ret= 0;
|
||||
|
||||
DBUG_ENTER("Event_db_repository::fill_schema_events");
|
||||
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))
|
||||
{
|
||||
sql_print_error("Table mysql.event is damaged.");
|
||||
thd->restore_backup_open_tables_state(&backup);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
/*
|
||||
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);
|
||||
|
||||
close_thread_tables(thd);
|
||||
thd->restore_backup_open_tables_state(&backup);
|
||||
|
||||
DBUG_PRINT("info", ("Return code=%d", ret));
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Open mysql.event table for read
|
||||
/**
|
||||
Open mysql.event table for read.
|
||||
|
||||
SYNOPSIS
|
||||
Events::open_event_table()
|
||||
thd [in] Thread context
|
||||
lock_type [in] How to lock the table
|
||||
table [out] We will store the open table here
|
||||
It's assumed that the caller knows what they are doing:
|
||||
- whether it was necessary to reset-and-backup the open tables state
|
||||
- whether the requested lock does not lead to a deadlock
|
||||
- whether this open mode would work under LOCK TABLES, or inside a
|
||||
stored function or trigger.
|
||||
|
||||
RETURN VALUE
|
||||
1 Cannot lock table
|
||||
2 The table is corrupted - different number of fields
|
||||
0 OK
|
||||
@param[in] thd Thread context
|
||||
@param[in] lock_type How to lock the table
|
||||
@param[out] table We will store the open table here
|
||||
|
||||
@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,
|
||||
TABLE **table)
|
||||
{
|
||||
TABLE_LIST tables;
|
||||
DBUG_ENTER("Event_db_repository::open_event_table");
|
||||
|
||||
bzero((char*) &tables, sizeof(tables));
|
||||
tables.db= (char*) "mysql";
|
||||
tables.table_name= tables.alias= (char*) "event";
|
||||
tables.lock_type= lock_type;
|
||||
tables.init_one_table("mysql", "event", lock_type);
|
||||
|
||||
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;
|
||||
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
|
||||
check_parse_params()
|
||||
thd Thread context
|
||||
parse_data Event's data
|
||||
Creates an event. Relies on mysql_event_fill_row which is shared with
|
||||
::update_event.
|
||||
|
||||
RETURN VALUE
|
||||
FALSE OK
|
||||
TRUE Error (reported)
|
||||
*/
|
||||
@pre All semantic checks must be performed outside. This function
|
||||
only creates a record on disk.
|
||||
@pre The thread handle has no open tables.
|
||||
|
||||
static int
|
||||
check_parse_params(THD *thd, Event_parse_data *parse_data)
|
||||
{
|
||||
DBUG_ENTER("check_parse_params");
|
||||
@param[in,out] THD
|
||||
@param[in] parse_data Parsed event definition
|
||||
@param[in] create_if_not TRUE if IF NOT EXISTS clause was provided
|
||||
to CREATE EVENT statement
|
||||
|
||||
if (parse_data->check_parse_data(thd))
|
||||
DBUG_RETURN(EVEX_BAD_PARAMS);
|
||||
|
||||
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".
|
||||
@retval FALSE success
|
||||
@retval TRUE error
|
||||
*/
|
||||
|
||||
bool
|
||||
Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
|
||||
my_bool create_if_not)
|
||||
{
|
||||
int ret= 0;
|
||||
int ret= 1;
|
||||
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");
|
||||
|
||||
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"));
|
||||
|
||||
if (open_event_table(thd, TL_WRITE, &table))
|
||||
{
|
||||
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
|
||||
goto err;
|
||||
}
|
||||
goto end;
|
||||
|
||||
DBUG_PRINT("info", ("name: %.*s", parse_data->name.length,
|
||||
parse_data->name.str));
|
||||
|
||||
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)
|
||||
{
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
ER_EVENT_ALREADY_EXISTS, ER(ER_EVENT_ALREADY_EXISTS),
|
||||
parse_data->name.str);
|
||||
goto ok;
|
||||
ret= 0;
|
||||
}
|
||||
my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), parse_data->name.str);
|
||||
goto err;
|
||||
else
|
||||
my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), parse_data->name.str);
|
||||
goto end;
|
||||
}
|
||||
|
||||
DBUG_PRINT("info", ("non-existant, 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;
|
||||
}
|
||||
DBUG_PRINT("info", ("non-existent, go forward"));
|
||||
|
||||
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())
|
||||
{
|
||||
my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->dbname.str);
|
||||
goto err;
|
||||
goto end;
|
||||
}
|
||||
|
||||
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())
|
||||
{
|
||||
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)
|
||||
{
|
||||
my_error(ER_TOO_LONG_BODY, MYF(0), parse_data->name.str);
|
||||
goto err;
|
||||
}
|
||||
|
||||
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;
|
||||
goto end;
|
||||
}
|
||||
|
||||
((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
|
||||
handle it here
|
||||
*/
|
||||
if ((ret= mysql_event_fill_row(thd, table, parse_data, FALSE)))
|
||||
goto err;
|
||||
if (mysql_event_fill_row(thd, table, parse_data, FALSE))
|
||||
goto end;
|
||||
|
||||
table->field[ET_FIELD_STATUS]->store((longlong)parse_data->status, TRUE);
|
||||
|
||||
/* Close active transaction only if We are going to modify disk */
|
||||
if (end_active_trans(thd))
|
||||
goto err;
|
||||
|
||||
if (table->file->ha_write_row(table->record[0]))
|
||||
if ((ret= table->file->ha_write_row(table->record[0])))
|
||||
{
|
||||
my_error(ER_EVENT_STORE_FAILED, MYF(0), parse_data->name.str, ret);
|
||||
goto err;
|
||||
table->file->print_error(ret, MYF(0));
|
||||
goto end;
|
||||
}
|
||||
ret= 0;
|
||||
|
||||
ok:
|
||||
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);
|
||||
end:
|
||||
if (table)
|
||||
close_thread_tables(thd);
|
||||
DBUG_RETURN(TRUE);
|
||||
DBUG_RETURN(test(ret));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
Used to execute ALTER EVENT. Pendant to Events::update_event().
|
||||
|
||||
SYNOPSIS
|
||||
Event_db_repository::update_event()
|
||||
thd THD
|
||||
sp_name the name of the event to alter
|
||||
et event's data
|
||||
@param[in,out] thd thread handle
|
||||
@param[in] parse_data parsed event definition
|
||||
@paran[in[ new_dbname not NULL if ALTER EVENT RENAME
|
||||
points at a new database name
|
||||
@param[in] new_name not NULL if ALTER EVENT RENAME
|
||||
points at a new event name
|
||||
|
||||
RETURN VALUE
|
||||
FALSE OK
|
||||
TRUE Error (reported)
|
||||
@pre All semantic checks are performed outside this function,
|
||||
it only updates the event definition on disk.
|
||||
@pre We don't have any tables open in the given thread.
|
||||
|
||||
NOTES
|
||||
sp_name is passed since this is the name of the event to
|
||||
alter in case of RENAME TO.
|
||||
@retval FALSE success
|
||||
@retval TRUE error (reported)
|
||||
*/
|
||||
|
||||
bool
|
||||
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;
|
||||
TABLE *table= NULL;
|
||||
int ret= 1;
|
||||
DBUG_ENTER("Event_db_repository::update_event");
|
||||
|
||||
if (open_event_table(thd, TL_WRITE, &table))
|
||||
{
|
||||
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
|
||||
goto err;
|
||||
}
|
||||
/* None or both must be set */
|
||||
DBUG_ASSERT(new_dbname && new_name || new_dbname == new_name);
|
||||
|
||||
if (check_parse_params(thd, parse_data) || parse_data->do_not_create)
|
||||
goto err;
|
||||
if (open_event_table(thd, TL_WRITE, &table))
|
||||
goto end;
|
||||
|
||||
DBUG_PRINT("info", ("dbname: %s", parse_data->dbname.str));
|
||||
DBUG_PRINT("info", ("name: %s", parse_data->name.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 */
|
||||
if (new_name)
|
||||
{
|
||||
if (!sortcmp_lex_string(parse_data->name, *new_name, scs) &&
|
||||
!sortcmp_lex_string(parse_data->dbname, *new_dbname, scs))
|
||||
{
|
||||
my_error(ER_EVENT_SAME_NAME, MYF(0), parse_data->name.str);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!find_named_event(thd, *new_dbname, *new_name, table))
|
||||
DBUG_PRINT("info", ("rename to: %s@%s", new_dbname->str, new_name->str));
|
||||
if (!find_named_event(*new_dbname, *new_name, table))
|
||||
{
|
||||
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
|
||||
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);
|
||||
goto err;
|
||||
goto end;
|
||||
}
|
||||
|
||||
store_record(table,record[1]);
|
||||
@ -749,7 +648,7 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
|
||||
handle it here
|
||||
*/
|
||||
if (mysql_event_fill_row(thd, table, parse_data, TRUE))
|
||||
goto err;
|
||||
goto end;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* Close active transaction only if We are going to modify disk */
|
||||
if (end_active_trans(thd))
|
||||
goto err;
|
||||
|
||||
int res;
|
||||
if ((res= table->file->ha_update_row(table->record[1], table->record[0])))
|
||||
if ((ret= table->file->ha_update_row(table->record[1], table->record[0])))
|
||||
{
|
||||
my_error(ER_EVENT_STORE_FAILED, MYF(0), parse_data->name.str, res);
|
||||
goto err;
|
||||
table->file->print_error(ret, MYF(0));
|
||||
goto end;
|
||||
}
|
||||
ret= 0;
|
||||
|
||||
/* close mysql.event or we crash later when loading the event from disk */
|
||||
close_thread_tables(thd);
|
||||
DBUG_RETURN(FALSE);
|
||||
|
||||
err:
|
||||
end:
|
||||
if (table)
|
||||
close_thread_tables(thd);
|
||||
DBUG_RETURN(TRUE);
|
||||
DBUG_RETURN(test(ret));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Drops an event
|
||||
/**
|
||||
Delete event record from mysql.event table.
|
||||
|
||||
SYNOPSIS
|
||||
Event_db_repository::drop_event()
|
||||
thd [in] THD
|
||||
db [in] Database name
|
||||
name [in] Event's name
|
||||
drop_if_exists [in] If set and the event not existing => warning
|
||||
onto the stack
|
||||
@param[in,out] thd thread handle
|
||||
@param[in] db Database name
|
||||
@param[in] name Event name
|
||||
@param[in] drop_if_exists DROP IF EXISTS clause was specified.
|
||||
If set, and the event does not exist,
|
||||
the error is downgraded to a warning.
|
||||
|
||||
RETURN VALUE
|
||||
FALSE OK
|
||||
TRUE Error (reported)
|
||||
@retval FALSE success
|
||||
@retval TRUE error (reported)
|
||||
*/
|
||||
|
||||
bool
|
||||
@ -800,66 +689,59 @@ Event_db_repository::drop_event(THD *thd, LEX_STRING db, LEX_STRING name,
|
||||
bool drop_if_exists)
|
||||
{
|
||||
TABLE *table= NULL;
|
||||
Open_tables_state backup;
|
||||
int ret;
|
||||
int ret= 1;
|
||||
|
||||
DBUG_ENTER("Event_db_repository::drop_event");
|
||||
DBUG_PRINT("enter", ("%s@%s", db.str, name.str));
|
||||
|
||||
thd->reset_n_backup_open_tables_state(&backup);
|
||||
if ((ret= open_event_table(thd, TL_WRITE, &table)))
|
||||
if (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));
|
||||
goto done;
|
||||
if ((ret= table->file->ha_delete_row(table->record[0])))
|
||||
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 */
|
||||
if (!(ret= end_active_trans(thd)) &&
|
||||
(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);
|
||||
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str);
|
||||
goto end;
|
||||
}
|
||||
|
||||
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)
|
||||
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)
|
||||
is stored.
|
||||
|
||||
SYNOPSIS
|
||||
Event_db_repository::find_named_event()
|
||||
thd Thread
|
||||
db Schema
|
||||
name Event name
|
||||
table Opened mysql.event
|
||||
In case search succeeded, the table cursor points at the found row.
|
||||
|
||||
RETURN VALUE
|
||||
FALSE OK
|
||||
TRUE No such event
|
||||
@param[in] db database name
|
||||
@param[in] name event name
|
||||
@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
|
||||
Event_db_repository::find_named_event(THD *thd, LEX_STRING db, LEX_STRING name,
|
||||
TABLE *table)
|
||||
Event_db_repository::find_named_event(LEX_STRING db, LEX_STRING name,
|
||||
TABLE *table)
|
||||
{
|
||||
byte key[MAX_KEY_LENGTH];
|
||||
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
|
||||
Event_db_repository::drop_events_by_field()
|
||||
thd Thread
|
||||
table mysql.event TABLE
|
||||
field Which field of the row to use for matching
|
||||
field_value The value that should match
|
||||
@pre The thread handle has no open tables.
|
||||
|
||||
@param[in,out] thd Thread
|
||||
@param[in,out] table mysql.event TABLE
|
||||
@param[in] field Which field of the row to use for matching
|
||||
@param[in] field_value The value that should match
|
||||
*/
|
||||
|
||||
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));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
@ -951,14 +824,20 @@ Event_db_repository::drop_events_by_field(THD *thd,
|
||||
{
|
||||
char *et_field= get_field(thd->mem_root, table->field[field]);
|
||||
|
||||
LEX_STRING et_field_lex= { et_field, strlen(et_field) };
|
||||
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))
|
||||
/* et_field may be NULL if the table is corrupted or out of memory */
|
||||
if (et_field)
|
||||
{
|
||||
DBUG_PRINT("info", ("Dropping"));
|
||||
ret= table->file->ha_delete_row(table->record[0]);
|
||||
LEX_STRING et_field_lex= { et_field, strlen(et_field) };
|
||||
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);
|
||||
@ -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
|
||||
the table, compiles and inserts it into the cache.
|
||||
the table.
|
||||
|
||||
SYNOPSIS
|
||||
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
|
||||
@pre The given thread does not have open tables.
|
||||
|
||||
RETURN VALUE
|
||||
FALSE OK
|
||||
TRUE Error (reported)
|
||||
@retval FALSE success
|
||||
@retval TRUE error
|
||||
*/
|
||||
|
||||
bool
|
||||
@ -989,26 +862,169 @@ Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname,
|
||||
LEX_STRING name, Event_basic *etn)
|
||||
{
|
||||
TABLE *table= NULL;
|
||||
int ret= 0;
|
||||
Open_tables_state backup;
|
||||
bool ret;
|
||||
|
||||
DBUG_ENTER("Event_db_repository::load_named_event");
|
||||
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);
|
||||
}
|
||||
|
||||
thd->restore_backup_open_tables_state(&backup);
|
||||
/* In this case no memory was allocated so we don't need to clean */
|
||||
|
||||
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
|
||||
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
|
||||
{
|
||||
@ -70,17 +75,28 @@ public:
|
||||
drop_schema_events(THD *thd, LEX_STRING schema);
|
||||
|
||||
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
|
||||
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);
|
||||
|
||||
int
|
||||
bool
|
||||
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:
|
||||
void
|
||||
drop_events_by_field(THD *thd, enum enum_events_table_field field,
|
||||
@ -92,9 +108,7 @@ private:
|
||||
bool
|
||||
table_scan_all_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table);
|
||||
|
||||
static bool
|
||||
check_system_tables(THD *thd);
|
||||
|
||||
private:
|
||||
/* Prevent use of these */
|
||||
Event_db_repository(const 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()
|
||||
:mutex_last_unlocked_at_line(0), mutex_last_locked_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_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_cond_init(&COND_queue_state, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Destroys mutexes.
|
||||
|
||||
SYNOPSIS
|
||||
Event_queue::deinit_mutexes()
|
||||
*/
|
||||
|
||||
void
|
||||
Event_queue::deinit_mutexes()
|
||||
Event_queue::~Event_queue()
|
||||
{
|
||||
deinit_queue();
|
||||
pthread_mutex_destroy(&LOCK_event_queue);
|
||||
pthread_cond_destroy(&COND_queue_state);
|
||||
}
|
||||
@ -176,34 +158,47 @@ Event_queue::deinit_queue()
|
||||
/**
|
||||
Adds an event to the queue.
|
||||
|
||||
SYNOPSIS
|
||||
Event_queue::create_event()
|
||||
dbname The schema of the new event
|
||||
name The name of the new event
|
||||
Compute the next execution time for an event, and if it is still
|
||||
active, add it to the queue. Otherwise delete it.
|
||||
The object is left intact in case of an error. Otherwise
|
||||
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
|
||||
Event_queue::create_event(THD *thd, Event_queue_element *new_element)
|
||||
bool
|
||||
Event_queue::create_event(THD *thd, Event_queue_element *new_element,
|
||||
bool *created)
|
||||
{
|
||||
DBUG_ENTER("Event_queue::create_event");
|
||||
DBUG_PRINT("enter", ("thd: 0x%lx et=%s.%s", (long) thd,
|
||||
new_element->dbname.str, new_element->name.str));
|
||||
|
||||
if ((new_element->status == Event_queue_element::DISABLED)
|
||||
|| (new_element->status == Event_queue_element::SLAVESIDE_DISABLED))
|
||||
delete new_element;
|
||||
else
|
||||
/* Will do nothing if the event is disabled */
|
||||
new_element->compute_next_execution_time();
|
||||
if (new_element->status != Event_queue_element::ENABLED)
|
||||
{
|
||||
new_element->compute_next_execution_time();
|
||||
DBUG_PRINT("info", ("new event in the queue: 0x%lx", (long) new_element));
|
||||
|
||||
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();
|
||||
delete new_element;
|
||||
*created= FALSE;
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
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:
|
||||
Event_queue();
|
||||
|
||||
void
|
||||
init_mutexes();
|
||||
|
||||
void
|
||||
deinit_mutexes();
|
||||
~Event_queue();
|
||||
|
||||
bool
|
||||
init_queue(THD *thd);
|
||||
|
||||
void
|
||||
deinit_queue();
|
||||
|
||||
/* Methods for queue management follow */
|
||||
|
||||
void
|
||||
create_event(THD *thd, Event_queue_element *new_element);
|
||||
bool
|
||||
create_event(THD *thd, Event_queue_element *new_element,
|
||||
bool *created);
|
||||
|
||||
void
|
||||
update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
|
||||
@ -64,9 +57,23 @@ public:
|
||||
void
|
||||
dump_internal_status();
|
||||
|
||||
private:
|
||||
void
|
||||
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
|
||||
find_n_remove_event(LEX_STRING db, LEX_STRING name);
|
||||
|
||||
@ -98,16 +105,6 @@ protected:
|
||||
bool mutex_queue_data_attempting_lock;
|
||||
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_ */
|
||||
|
@ -37,7 +37,6 @@ extern pthread_attr_t connection_attrib;
|
||||
|
||||
|
||||
Event_db_repository *Event_worker_thread::db_repository;
|
||||
Events *Event_worker_thread::events_facade;
|
||||
|
||||
|
||||
static
|
||||
@ -80,11 +79,11 @@ Event_worker_thread::print_warnings(THD *thd, Event_job_data *et)
|
||||
prefix.length(0);
|
||||
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);
|
||||
append_identifier(thd,&prefix, et->dbname.str, et->dbname.length);
|
||||
prefix.append(et->dbname.str, et->dbname.length, system_charset_info);
|
||||
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);
|
||||
|
||||
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.append(prefix);
|
||||
err_msg.append(err->msg, strlen(err->msg), system_charset_info);
|
||||
err_msg.append("]");
|
||||
DBUG_ASSERT(err->level < 3);
|
||||
(sql_print_message_handlers[err->level])("%*s", err_msg.length(),
|
||||
err_msg.c_ptr());
|
||||
@ -239,7 +237,7 @@ event_scheduler_thread(void *arg)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
Function that executes an event in a child thread. Setups the
|
||||
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
|
||||
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);
|
||||
|
||||
sql_print_information("Event Scheduler: "
|
||||
"[%s.%s of %s] executed in thread %lu. "
|
||||
"RetCode=%d", job_data->dbname.str, job_data->name.str,
|
||||
job_data->definer.str, thd->thread_id, ret);
|
||||
if (ret == EVEX_COMPILE_ERROR)
|
||||
switch (ret) {
|
||||
case 0:
|
||||
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->definer.str);
|
||||
else if (ret == EVEX_MICROSECOND_UNSUP)
|
||||
sql_print_information("Event Scheduler: MICROSECOND is not supported");
|
||||
thd->thread_id);
|
||||
break;
|
||||
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:
|
||||
delete job_data;
|
||||
@ -349,66 +357,34 @@ end:
|
||||
problem. However, this comes at the price of introduction bi-directional
|
||||
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,
|
||||
event->name.str));
|
||||
|
||||
delete event;
|
||||
deinit_event_thread(thd);
|
||||
pthread_exit(0);
|
||||
/*
|
||||
Do not pthread_exit since we want local destructors for stack objects
|
||||
to be invoked.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Performs initialization of the scheduler data, outside of the
|
||||
threading primitives.
|
||||
|
||||
SYNOPSIS
|
||||
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()
|
||||
Event_scheduler::Event_scheduler(Event_queue *queue_arg)
|
||||
:state(UNINITIALIZED),
|
||||
scheduler_thd(NULL),
|
||||
queue(queue_arg),
|
||||
started_events(0)
|
||||
{
|
||||
pthread_mutex_init(&LOCK_scheduler_state, MY_MUTEX_INIT_FAST);
|
||||
pthread_cond_init(&COND_state, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Deinits scheduler's threading primitives.
|
||||
|
||||
SYNOPSIS
|
||||
Event_scheduler::deinit_mutexes()
|
||||
*/
|
||||
|
||||
void
|
||||
Event_scheduler::deinit_mutexes()
|
||||
Event_scheduler::~Event_scheduler()
|
||||
{
|
||||
stop(); /* does nothing if not running */
|
||||
pthread_mutex_destroy(&LOCK_scheduler_state);
|
||||
pthread_cond_destroy(&COND_state);
|
||||
}
|
||||
@ -639,6 +615,9 @@ Event_scheduler::is_running()
|
||||
Stops the scheduler (again). Waits for acknowledgement from the
|
||||
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
|
||||
Event_scheduler::stop()
|
||||
|
||||
|
@ -15,7 +15,8 @@
|
||||
along with this program; if not, write to the Free Software
|
||||
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.
|
||||
All public declarations of Events module are in events.h and
|
||||
event_data_objects.h.
|
||||
@ -41,10 +42,9 @@ class Event_worker_thread
|
||||
{
|
||||
public:
|
||||
static void
|
||||
init(Events *events, Event_db_repository *db_repo)
|
||||
init(Event_db_repository *db_repository_arg)
|
||||
{
|
||||
db_repository= db_repo;
|
||||
events_facade= events;
|
||||
db_repository= db_repository_arg;
|
||||
}
|
||||
|
||||
void
|
||||
@ -55,15 +55,15 @@ private:
|
||||
print_warnings(THD *thd, Event_job_data *et);
|
||||
|
||||
static Event_db_repository *db_repository;
|
||||
static Events *events_facade;
|
||||
};
|
||||
|
||||
|
||||
class Event_scheduler
|
||||
{
|
||||
public:
|
||||
Event_scheduler():state(UNINITIALIZED){}
|
||||
~Event_scheduler(){}
|
||||
Event_scheduler(Event_queue *event_queue_arg);
|
||||
~Event_scheduler();
|
||||
|
||||
|
||||
/* State changing methods follow */
|
||||
|
||||
@ -80,17 +80,6 @@ public:
|
||||
bool
|
||||
run(THD *thd);
|
||||
|
||||
void
|
||||
init_scheduler(Event_queue *queue);
|
||||
|
||||
void
|
||||
deinit_scheduler();
|
||||
|
||||
void
|
||||
init_mutexes();
|
||||
|
||||
void
|
||||
deinit_mutexes();
|
||||
|
||||
/* Information retrieving methods follow */
|
||||
bool
|
||||
|
972
sql/events.cc
972
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
|
||||
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_db_repository;
|
||||
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.
|
||||
|
||||
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
|
||||
@ -53,47 +73,48 @@ public:
|
||||
EVENTS_DISABLED= 4
|
||||
};
|
||||
|
||||
static enum_opt_event_scheduler opt_event_scheduler;
|
||||
static TYPELIB opt_typelib;
|
||||
static TYPELIB var_typelib;
|
||||
/* Possible values of @@event_scheduler variable */
|
||||
static const TYPELIB var_typelib;
|
||||
|
||||
bool
|
||||
init();
|
||||
static bool
|
||||
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();
|
||||
|
||||
void
|
||||
static void
|
||||
init_mutexes();
|
||||
|
||||
void
|
||||
static void
|
||||
destroy_mutexes();
|
||||
|
||||
bool
|
||||
start_execution_of_events();
|
||||
static bool
|
||||
start_or_stop_event_scheduler(enum enum_opt_event_scheduler start_or_stop);
|
||||
|
||||
bool
|
||||
stop_execution_of_events();
|
||||
|
||||
bool
|
||||
is_execution_of_events_started();
|
||||
|
||||
static Events *
|
||||
get_instance();
|
||||
|
||||
bool
|
||||
static bool
|
||||
create_event(THD *thd, Event_parse_data *parse_data, bool if_exists);
|
||||
|
||||
bool
|
||||
update_event(THD *thd, Event_parse_data *parse_data, sp_name *rename_to);
|
||||
static bool
|
||||
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);
|
||||
|
||||
void
|
||||
static void
|
||||
drop_schema_events(THD *thd, char *db);
|
||||
|
||||
bool
|
||||
static bool
|
||||
show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name);
|
||||
|
||||
/* Needed for both SHOW CREATE EVENT and INFORMATION_SCHEMA */
|
||||
@ -104,31 +125,28 @@ public:
|
||||
static int
|
||||
fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */);
|
||||
|
||||
void
|
||||
static void
|
||||
dump_internal_status();
|
||||
|
||||
private:
|
||||
bool
|
||||
check_system_tables(THD *thd);
|
||||
static bool check_if_system_tables_error();
|
||||
|
||||
int
|
||||
static bool
|
||||
load_events_from_db(THD *thd);
|
||||
|
||||
/* Singleton DP is used */
|
||||
Events();
|
||||
~Events(){}
|
||||
|
||||
/* Singleton instance */
|
||||
static Events singleton;
|
||||
|
||||
Event_queue *event_queue;
|
||||
Event_scheduler *scheduler;
|
||||
Event_db_repository *db_repository;
|
||||
|
||||
pthread_mutex_t LOCK_event_metadata;
|
||||
|
||||
bool check_system_tables_error;
|
||||
private:
|
||||
/* Command line option names */
|
||||
static const TYPELIB opt_typelib;
|
||||
static pthread_mutex_t LOCK_event_metadata;
|
||||
static Event_queue *event_queue;
|
||||
static Event_scheduler *scheduler;
|
||||
static Event_db_repository *db_repository;
|
||||
/* Current state of Event Scheduler */
|
||||
static enum enum_opt_event_scheduler opt_event_scheduler;
|
||||
/* Set to TRUE if an error at start up */
|
||||
static bool check_system_tables_error;
|
||||
|
||||
private:
|
||||
/* Prevent use of these */
|
||||
Events(const Events &);
|
||||
void operator=(Events &);
|
||||
|
@ -885,7 +885,7 @@ static void close_connections(void)
|
||||
}
|
||||
(void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
|
||||
|
||||
Events::get_instance()->deinit();
|
||||
Events::deinit();
|
||||
end_slave();
|
||||
|
||||
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_received);
|
||||
(void) pthread_mutex_destroy(&LOCK_user_conn);
|
||||
Events::get_instance()->destroy_mutexes();
|
||||
Events::destroy_mutexes();
|
||||
#ifdef HAVE_OPENSSL
|
||||
(void) pthread_mutex_destroy(&LOCK_des_key_file);
|
||||
#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_cond_init(&COND_server_started,NULL);
|
||||
sp_cache_init();
|
||||
Events::get_instance()->init_mutexes();
|
||||
Events::init_mutexes();
|
||||
/* Parameter for threads created for connections */
|
||||
(void) pthread_attr_init(&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_maintenance_thread();
|
||||
|
||||
if (Events::init(opt_noacl))
|
||||
unireg_abort(1);
|
||||
|
||||
sql_print_information(ER(ER_STARTUP),my_progname,server_version,
|
||||
((unix_sock == INVALID_SOCKET) ? (char*) ""
|
||||
: mysqld_unix_port),
|
||||
mysqld_port,
|
||||
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 */
|
||||
pthread_mutex_lock(&LOCK_server_started);
|
||||
@ -7585,32 +7579,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
||||
}
|
||||
#endif
|
||||
case OPT_EVENT_SCHEDULER:
|
||||
if (!argument)
|
||||
Events::opt_event_scheduler= Events::EVENTS_DISABLED;
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (Events::set_opt_event_scheduler(argument))
|
||||
exit(1);
|
||||
break;
|
||||
case (int) OPT_SKIP_NEW:
|
||||
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];
|
||||
const char *value;
|
||||
@ -3643,21 +3643,18 @@ bool sys_var_thd_table_type::update(THD *thd, set_var *var)
|
||||
SYNOPSIS
|
||||
thd in thread handler
|
||||
val in sql_mode value
|
||||
len out pointer on length of string
|
||||
|
||||
RETURN
|
||||
pointer to string with sql_mode representation
|
||||
rep out pointer pointer to string with sql_mode representation
|
||||
*/
|
||||
|
||||
byte *sys_var_thd_sql_mode::symbolic_mode_representation(THD *thd,
|
||||
ulonglong val,
|
||||
ulong *len)
|
||||
bool
|
||||
sys_var_thd_sql_mode::
|
||||
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);
|
||||
ulong length;
|
||||
|
||||
tmp.length(0);
|
||||
|
||||
for (uint i= 0; val; val>>= 1, i++)
|
||||
{
|
||||
if (val & 1)
|
||||
@ -3668,20 +3665,25 @@ byte *sys_var_thd_sql_mode::symbolic_mode_representation(THD *thd,
|
||||
}
|
||||
}
|
||||
|
||||
if ((length= tmp.length()))
|
||||
length--;
|
||||
*len= length;
|
||||
return (byte*) thd->strmake(tmp.ptr(), length);
|
||||
if (tmp.length())
|
||||
tmp.length(tmp.length() - 1); /* trim the trailing comma */
|
||||
|
||||
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,
|
||||
LEX_STRING *base)
|
||||
{
|
||||
LEX_STRING sql_mode;
|
||||
ulonglong val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
|
||||
thd->variables.*offset);
|
||||
ulong length_unused;
|
||||
return symbolic_mode_representation(thd, val, &length_unused);
|
||||
(void) symbolic_mode_representation(thd, val, &sql_mode);
|
||||
return sql_mode.str;
|
||||
}
|
||||
|
||||
|
||||
@ -4012,24 +4014,13 @@ sys_var_event_scheduler::update(THD *thd, set_var *var)
|
||||
int res;
|
||||
/* here start the thread if not running. */
|
||||
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));
|
||||
|
||||
if (var->save_result.ulong_value == Events::EVENTS_ON)
|
||||
res= Events::get_instance()->start_execution_of_events();
|
||||
else if (var->save_result.ulong_value == Events::EVENTS_OFF)
|
||||
res= Events::get_instance()->stop_execution_of_events();
|
||||
else
|
||||
{
|
||||
assert(0); // Impossible
|
||||
}
|
||||
if (res)
|
||||
my_error(ER_EVENT_SET_VAR_ERROR, MYF(0));
|
||||
enum Events::enum_opt_event_scheduler
|
||||
new_state=
|
||||
(enum Events::enum_opt_event_scheduler) var->save_result.ulong_value;
|
||||
|
||||
res= Events::start_or_stop_event_scheduler(new_state);
|
||||
|
||||
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,
|
||||
LEX_STRING *base)
|
||||
{
|
||||
int state;
|
||||
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];
|
||||
return (byte *) Events::get_opt_event_scheduler_str();
|
||||
}
|
||||
|
||||
|
||||
|
@ -61,7 +61,7 @@ public:
|
||||
sys_vars++;
|
||||
}
|
||||
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);
|
||||
virtual bool update(THD *thd, set_var *var)=0;
|
||||
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);
|
||||
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
|
||||
static byte *symbolic_mode_representation(THD *thd, ulonglong sql_mode,
|
||||
ulong *length);
|
||||
static bool symbolic_mode_representation(THD *thd, ulonglong sql_mode,
|
||||
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"
|
||||
ger "Spaltenanzahl von mysql.%s falsch. %d erwartet, aber %d gefunden. Tabelle ist wahrscheinlich besch<63>digt"
|
||||
ER_CANNOT_LOAD_FROM_TABLE
|
||||
eng "Cannot load from mysql.%s. The table is probably corrupted. Please see the error log for details"
|
||||
ger "Kann mysql.%s nicht einlesen. Tabelle ist wahrscheinlich besch<63>digt, siehe Fehlerlog"
|
||||
eng "Cannot load from mysql.%s. The table is probably corrupted"
|
||||
ger "Kann mysql.%s nicht einlesen. Tabelle ist wahrscheinlich besch<63>digt"
|
||||
ER_EVENT_CANNOT_DELETE
|
||||
eng "Failed to delete the event from mysql.event"
|
||||
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);
|
||||
int res;
|
||||
List<Item> field_list;
|
||||
byte *sql_mode_str;
|
||||
ulong sql_mode_len;
|
||||
LEX_STRING sql_mode;
|
||||
bool full_access;
|
||||
DBUG_ENTER("sp_head::show_create_procedure");
|
||||
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))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
sql_mode_str=
|
||||
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
|
||||
m_sql_mode,
|
||||
&sql_mode_len);
|
||||
sys_var_thd_sql_mode::symbolic_mode_representation(thd, m_sql_mode,
|
||||
&sql_mode);
|
||||
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
|
||||
Item_empty_string *definition=
|
||||
new Item_empty_string("Create Procedure", max(buffer.length(),1024));
|
||||
@ -2133,7 +2130,7 @@ sp_head::show_create_procedure(THD *thd)
|
||||
DBUG_RETURN(1);
|
||||
protocol->prepare_for_resend();
|
||||
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)
|
||||
protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
|
||||
else
|
||||
@ -2176,23 +2173,18 @@ sp_head::show_create_function(THD *thd)
|
||||
String buffer(buff, sizeof(buff), system_charset_info);
|
||||
int res;
|
||||
List<Item> field_list;
|
||||
byte *sql_mode_str;
|
||||
ulong sql_mode_len;
|
||||
LEX_STRING sql_mode;
|
||||
bool full_access;
|
||||
DBUG_ENTER("sp_head::show_create_function");
|
||||
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))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
sql_mode_str=
|
||||
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
|
||||
m_sql_mode,
|
||||
&sql_mode_len);
|
||||
sys_var_thd_sql_mode::symbolic_mode_representation(thd, m_sql_mode,
|
||||
&sql_mode);
|
||||
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=
|
||||
new Item_empty_string("Create Function", max(buffer.length(),1024));
|
||||
definition->maybe_null= TRUE;
|
||||
@ -2203,7 +2195,7 @@ sp_head::show_create_function(THD *thd)
|
||||
DBUG_RETURN(1);
|
||||
protocol->prepare_for_resend();
|
||||
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)
|
||||
protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
|
||||
else
|
||||
|
@ -953,7 +953,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
|
||||
|
||||
exit:
|
||||
(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
|
||||
change the client's selected database to nothing (to have an empty
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "sp.h"
|
||||
#include "sp_cache.h"
|
||||
#include "events.h"
|
||||
#include "event_data_objects.h"
|
||||
#include "sql_trigger.h"
|
||||
|
||||
/* Used in error handling only */
|
||||
@ -3181,13 +3180,16 @@ end_with_restore_list:
|
||||
|
||||
switch (lex->sql_command) {
|
||||
case SQLCOM_CREATE_EVENT:
|
||||
res= Events::get_instance()->
|
||||
create_event(thd, lex->event_parse_data,
|
||||
lex->create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS);
|
||||
{
|
||||
bool if_not_exists= (lex->create_info.options &
|
||||
HA_LEX_CREATE_IF_NOT_EXISTS);
|
||||
res= Events::create_event(thd, lex->event_parse_data, if_not_exists);
|
||||
break;
|
||||
}
|
||||
case SQLCOM_ALTER_EVENT:
|
||||
res= Events::get_instance()->update_event(thd, lex->event_parse_data,
|
||||
lex->spname);
|
||||
res= Events::update_event(thd, lex->event_parse_data,
|
||||
lex->spname ? &lex->spname->m_db : NULL,
|
||||
lex->spname ? &lex->spname->m_name : NULL);
|
||||
break;
|
||||
default:
|
||||
DBUG_ASSERT(0);
|
||||
@ -3205,39 +3207,16 @@ end_with_restore_list:
|
||||
}
|
||||
/* lex->unit.cleanup() is called outside, no need to call it here */
|
||||
break;
|
||||
case SQLCOM_DROP_EVENT:
|
||||
case SQLCOM_SHOW_CREATE_EVENT:
|
||||
{
|
||||
DBUG_ASSERT(lex->spname);
|
||||
if (! lex->spname->m_db.str)
|
||||
{
|
||||
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
|
||||
goto error;
|
||||
}
|
||||
if (check_access(thd, EVENT_ACL, lex->spname->m_db.str, 0, 0, 0,
|
||||
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);
|
||||
}
|
||||
res= Events::show_create_event(thd, lex->spname->m_db,
|
||||
lex->spname->m_name);
|
||||
break;
|
||||
case SQLCOM_DROP_EVENT:
|
||||
if (!(res= Events::drop_event(thd,
|
||||
lex->spname->m_db, lex->spname->m_name,
|
||||
lex->drop_if_exists)))
|
||||
send_ok(thd);
|
||||
break;
|
||||
}
|
||||
case SQLCOM_CREATE_FUNCTION: // UDF function
|
||||
{
|
||||
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)
|
||||
{
|
||||
CHARSET_INFO *cs= system_charset_info;
|
||||
byte *sql_mode_str;
|
||||
ulong sql_mode_len;
|
||||
LEX_STRING sql_mode_rep;
|
||||
|
||||
restore_record(table, s->default_values);
|
||||
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[15]->store(STRING_WITH_LEN("NEW"), cs);
|
||||
|
||||
sql_mode_str=
|
||||
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
|
||||
sql_mode,
|
||||
&sql_mode_len);
|
||||
table->field[17]->store((const char*)sql_mode_str, sql_mode_len, cs);
|
||||
sys_var_thd_sql_mode::symbolic_mode_representation(thd, sql_mode,
|
||||
&sql_mode_rep);
|
||||
table->field[17]->store(sql_mode_rep.str, sql_mode_rep.length, cs);
|
||||
table->field[18]->store((const char *)definer_buffer->str, definer_buffer->length, cs);
|
||||
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;
|
||||
TIME time;
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -4349,13 +4346,11 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
|
||||
|
||||
/* SQL_MODE */
|
||||
{
|
||||
byte *sql_mode_str;
|
||||
ulong sql_mode_len= 0;
|
||||
sql_mode_str=
|
||||
sys_var_thd_sql_mode::symbolic_mode_representation(thd, et.sql_mode,
|
||||
&sql_mode_len);
|
||||
LEX_STRING sql_mode;
|
||||
sys_var_thd_sql_mode::symbolic_mode_representation(thd, et.sql_mode,
|
||||
&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;
|
||||
|
@ -537,6 +537,6 @@ Estimated memory (with thread stack): %ld\n",
|
||||
(long) (thread_count * thread_stack + info.hblkhd + info.arena));
|
||||
#endif
|
||||
|
||||
Events::get_instance()->dump_internal_status();
|
||||
Events::dump_internal_status();
|
||||
puts("");
|
||||
}
|
||||
|
245
sql/table.cc
245
sql/table.cc
@ -250,7 +250,7 @@ void free_table_share(TABLE_SHARE *share)
|
||||
Currently these are:
|
||||
|
||||
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_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[1]) == 'i' &&
|
||||
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,152 +2439,142 @@ bool check_column_name(const char *name)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
Checks whether a table is intact. Should be done *just* after the table has
|
||||
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
|
||||
@param[in] table The table to check
|
||||
@param[in] table_f_count Expected number of columns in the table
|
||||
@param[in] table_def Expected structure of the table (column name
|
||||
and type)
|
||||
|
||||
RETURNS
|
||||
FALSE OK
|
||||
TRUE There was an error
|
||||
@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
|
||||
table_check_intact(TABLE *table, const uint table_f_count,
|
||||
const TABLE_FIELD_W_TYPE *table_def,
|
||||
time_t *last_create_time, int error_num)
|
||||
const TABLE_FIELD_W_TYPE *table_def)
|
||||
{
|
||||
uint i;
|
||||
my_bool error= FALSE;
|
||||
my_bool fields_diff_count;
|
||||
DBUG_ENTER("table_check_intact");
|
||||
DBUG_PRINT("info",("table: %s expected_count: %d last_create_time: %ld",
|
||||
table->alias, table_f_count, *last_create_time));
|
||||
DBUG_PRINT("info",("table: %s expected_count: %d",
|
||||
table->alias, table_f_count));
|
||||
|
||||
if ((fields_diff_count= (table->s->fields != table_f_count)) ||
|
||||
(*last_create_time != table->file->stats.create_time))
|
||||
fields_diff_count= (table->s->fields != table_f_count);
|
||||
if (fields_diff_count)
|
||||
{
|
||||
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);
|
||||
DBUG_PRINT("info", ("Column count has changed, checking the definition"));
|
||||
|
||||
}
|
||||
else if (MYSQL_VERSION_ID == table->s->mysql_version)
|
||||
{
|
||||
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;
|
||||
}
|
||||
/* 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);
|
||||
}
|
||||
/* definitely something has changed */
|
||||
char buffer[255];
|
||||
for (i=0 ; i < table_f_count; i++, table_def++)
|
||||
else if (MYSQL_VERSION_ID == table->s->mysql_version)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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];
|
||||
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 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
|
||||
if (strncmp(field->field_name, table_def->name.str,
|
||||
table_def->name.length))
|
||||
{
|
||||
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);
|
||||
/*
|
||||
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;
|
||||
}
|
||||
}
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_PRINT("info", ("Table seems ok without thorough checking."));
|
||||
*last_create_time= table->file->stats.create_time;
|
||||
}
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
18
sql/table.h
18
sql/table.h
@ -689,6 +689,21 @@ class index_hint;
|
||||
typedef struct st_table_list
|
||||
{
|
||||
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
|
||||
views as leaves (unlike 'next_leaf' below). Created at parse time
|
||||
@ -1097,8 +1112,7 @@ typedef struct st_table_field_w_type
|
||||
|
||||
my_bool
|
||||
table_check_intact(TABLE *table, const uint table_f_count,
|
||||
const TABLE_FIELD_W_TYPE *table_def,
|
||||
time_t *last_create_time, int error_num);
|
||||
const TABLE_FIELD_W_TYPE *table_def);
|
||||
|
||||
static inline my_bitmap_map *tmp_use_all_columns(TABLE *table,
|
||||
MY_BITMAP *bitmap)
|
||||
|
Reference in New Issue
Block a user