Commit fa1d637e authored by unknown's avatar unknown

A set of changes aiming to make the Event Scheduler more user-friendly

when there are no up-to-date system tables to support it:
 - initialize the scheduler before reporting "Ready for connections".
   This ensures that warnings, if any, are printed before "Ready for
   connections", and this message is not mangled.
 - do not abort the scheduler if there are no system tables
 - check the tables once at start up, remember the status and disable
   the scheduler if the tables are not up to date.
   If one attempts to use the scheduler with bad tables,
   issue an error message.
 - clean up the behaviour of the module under LOCK TABLES and pre-locking
   mode
 - make sure implicit commit of Events DDL works as expected.
 - add more tests


Collateral clean ups in the events code.

This patch fixes Bug#23631 Events: SHOW VARIABLES doesn't work 
when mysql.event is damaged


mysql-test/r/events.result:
  Update results.
mysql-test/r/events_bugs.result:
  Update results.
mysql-test/r/events_restart_phase1.result:
  Update results.
mysql-test/r/events_restart_phase2.result:
  Update results.
mysql-test/r/events_restart_phase3.result:
  Update results.
mysql-test/r/events_scheduling.result:
  Update results.
mysql-test/r/events_time_zone.result:
  Update results.
mysql-test/t/events.test:
  Add new tests for tampering with mysql.event and some more
  tests for sub-statements, LOCK TABLES mode and pre-locking.
mysql-test/t/events_bugs.test:
  Move the non-concurrent part of test for Bug 16420 to this file.
mysql-test/t/events_restart_phase1.test:
  Rewrite events_restart_* tests to take into account that now
  we check mysql.event table only once, at server startup.
mysql-test/t/events_restart_phase2.test:
  Rewrite events_restart_* tests to take into account that now
  we check mysql.event table only once, at server startup.
mysql-test/t/events_restart_phase3.test:
  Rewrite events_restart_* tests to take into account that now
  we check mysql.event table only once, at server startup.
mysql-test/t/events_scheduling.test:
  Add more coverage for event_scheduler global variable.
mysql-test/t/events_time_zone.test:
  Move the non-concurrent part of the tests for Bug 16420 to 
  events_bugs.test
sql/event_data_objects.cc:
  Move update_timing_fields functionality to Event_db_repository.
  Make loading of events from a table record more robust to tampering
  with the table - now we do not check mysql.event on every table open.
sql/event_data_objects.h:
  Cleanup.
sql/event_db_repository.cc:
  Now Event_db_repository is responsible for table I/O only.
  All the logic of events DDL is handled outside, in Events class please
  refer to the added test coverage to see how this change affected
  the behavior of Event Scheduler.
  Dependency on sp_head.h and sp.h removed.
  Make this module robust to tweaks with mysql.event table.
  Move check_system_tables from events.cc to this file
sql/event_db_repository.h:
  Cleanup declarations (remove unused ones, change return type to bool
  from int).
sql/event_queue.cc:
  Update to adapt to the new start up scheme of the Event Scheduler.
sql/event_queue.h:
  Cleanup declarations.
sql/event_scheduler.cc:
  Make all the error messages uniform:
  [SEVERITY] Event Scheduler: [user][schema.event] message
  Using append_identifier for error logging was an overkill - we may 
  need it only if the system character set may have NUL (null character)
  as part of a valid identifier, this is currently never the case, 
  whereas additional quoting did not look nice in the log.
sql/event_scheduler.h:
  Cleanup the headers.
sql/events.cc:
  Use a different start up procedure of Event Scheduler:
  - at start up, try to check the system tables first.
  If they are not up-to-date, disable the scheduler.
  - try to load all the active events. In case of a load error, abort
  start up.
  - do not parse an event on start up. Parsing only gives some information
  about event validity, but far not all.
  Consolidate the business logic of Events DDL in this module.
  Now opt_event_scheduler may change after start up and thus is protected
  by LOCK_event_metadata mutex.
sql/events.h:
  Use all-static-data-members approach to implement Singleton pattern.
sql/mysqld.cc:
  New invocation scheme of Events. Move some logic to events.cc.
  Initialize the scheduler before reporting "Ready for connections".
sql/set_var.cc:
  Clean up sys_var_thd_sql_mode::symbolic_mode_representation
  to work with a LEX_STRING.
  Move more logic related to @@events_scheduler global variable to Events
  module.
sql/set_var.h:
  Update declarations.
sql/share/errmsg.txt:
  If someone tampered with mysql.event table after the server has
  started we no longer give him/her a complete report what was actually 
  broken. Do not send the user to look at the error log in such case,
  as there is nothing there (check_table_intact is not executed).
sql/sp_head.cc:
  Update to a new declaration of 
  sys_var_thd_sql_mode::symbolic_mode_representation
sql/sql_db.cc:
  New invocation scheme of Events module.
sql/sql_parse.cc:
  Move more logic to Events module. Make sure that we are consistent
  in the way access rights are checked for Events DDL: always
  after committing the current transaction and checking the system tables.
sql/sql_show.cc:
  Update to the new declarations of 
  sys_var_thd_sql_mode::symbolic_mode_representation
sql/sql_test.cc:
  New invocation scheme of events.
sql/table.cc:
  mysql.event is a system table.
  Update check_table_intact to be concurrent, more verbose, and less smart.
sql/table.h:
  Add a helper method.
mysql-test/r/events_trans.result:
  New BitKeeper file ``mysql-test/r/events_trans.result''
mysql-test/t/events_trans.test:
  New BitKeeper file ``mysql-test/t/events_trans.test'':
  test cases for Event Scheduler that require a transactional
  storage engine.
parent fce72805
This diff is collapsed.
create database if not exists events_test; drop database if exists events_test;
drop database if exists mysqltest_db1;
drop database if exists mysqltest_db2;
create database events_test;
use events_test; use events_test;
CREATE EVENT lower_case ON SCHEDULE EVERY 1 MINUTE DO SELECT 1; CREATE EVENT lower_case ON SCHEDULE EVERY 1 MINUTE DO SELECT 1;
CREATE EVENT Lower_case ON SCHEDULE EVERY 2 MINUTE DO SELECT 2; CREATE EVENT Lower_case ON SCHEDULE EVERY 2 MINUTE DO SELECT 2;
...@@ -381,4 +384,149 @@ ERROR 42000: Access denied; you need the SUPER privilege for this operation ...@@ -381,4 +384,149 @@ ERROR 42000: Access denied; you need the SUPER privilege for this operation
DROP EVENT e1; DROP EVENT e1;
ERROR HY000: Unknown event 'e1' ERROR HY000: Unknown event 'e1'
DROP USER mysqltest_u1@localhost; DROP USER mysqltest_u1@localhost;
SET GLOBAL EVENT_SCHEDULER= OFF;
SET @save_time_zone= @@TIME_ZONE;
SET TIME_ZONE= '+00:00';
SET TIMESTAMP= UNIX_TIMESTAMP('2005-12-31 23:58:59');
CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
SHOW EVENTS;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
events_test e1 root@localhost +00:00 RECURRING NULL 1 DAY 2005-12-31 23:58:59 NULL ENABLED
SET TIME_ZONE= '-01:00';
ALTER EVENT e1 ON SCHEDULE EVERY 1 DAY STARTS '2000-01-01 00:00:00';
SHOW EVENTS;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
events_test e1 root@localhost -01:00 RECURRING NULL 1 DAY 2000-01-01 00:00:00 NULL ENABLED
SET TIME_ZONE= '+02:00';
ALTER EVENT e1 ON SCHEDULE AT '2000-01-02 00:00:00'
ON COMPLETION PRESERVE DISABLE;
SHOW EVENTS;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
events_test e1 root@localhost +02:00 ONE TIME 2000-01-02 00:00:00 NULL NULL NULL NULL DISABLED
SET TIME_ZONE= '-03:00';
ALTER EVENT e1 ON SCHEDULE EVERY 1 DAY ENDS '2030-01-03 00:00:00'
ON COMPLETION PRESERVE DISABLE;
SHOW EVENTS;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
events_test e1 root@localhost -03:00 RECURRING NULL 1 DAY 2005-12-31 20:58:59 2030-01-03 00:00:00 DISABLED
SET TIME_ZONE= '+04:00';
ALTER EVENT e1 DO SELECT 2;
SHOW EVENTS;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
events_test e1 root@localhost -03:00 RECURRING NULL 1 DAY 2005-12-31 20:58:59 2030-01-03 00:00:00 ENABLED
DROP EVENT e1;
SET TIME_ZONE='+05:00';
CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
SELECT 1;
SET TIMESTAMP= @@TIMESTAMP + 1;
SET TIME_ZONE='-05:00';
CREATE EVENT e2 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
SELECT 1;
SET TIMESTAMP= @@TIMESTAMP + 1;
SET TIME_ZONE='+00:00';
CREATE EVENT e3 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
SELECT 1;
SELECT * FROM INFORMATION_SCHEMA.EVENTS ORDER BY event_name;
EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER TIME_ZONE EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD SQL_MODE STARTS ENDS STATUS ON_COMPLETION CREATED LAST_ALTERED LAST_EXECUTED EVENT_COMMENT
NULL events_test e1 root@localhost +05:00 SQL SELECT 1 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED NOT PRESERVE 2005-12-31 23:58:59 2005-12-31 23:58:59 NULL
NULL events_test e2 root@localhost -05:00 SQL SELECT 1 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED NOT PRESERVE 2005-12-31 23:59:00 2005-12-31 23:59:00 NULL
NULL events_test e3 root@localhost +00:00 SQL SELECT 1 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED NOT PRESERVE 2005-12-31 23:59:01 2005-12-31 23:59:01 NULL
SHOW EVENTS;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
events_test e1 root@localhost +05:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED
events_test e2 root@localhost -05:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED
events_test e3 root@localhost +00:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED
SHOW CREATE EVENT e1;
Event sql_mode time_zone Create Event
e1 +05:00 CREATE EVENT `e1` ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' ON COMPLETION NOT PRESERVE ENABLE DO SELECT 1
SHOW CREATE EVENT e2;
Event sql_mode time_zone Create Event
e2 -05:00 CREATE EVENT `e2` ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' ON COMPLETION NOT PRESERVE ENABLE DO SELECT 1
SHOW CREATE EVENT e3;
Event sql_mode time_zone Create Event
e3 +00:00 CREATE EVENT `e3` ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' ON COMPLETION NOT PRESERVE ENABLE DO SELECT 1
The following should fail, and nothing should be altered.
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00';
ERROR HY000: Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been altered
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00' DISABLE;
ERROR HY000: Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been altered
The following should give warnings, and nothing should be created.
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00'
DO
SELECT 1;
Warnings:
Note 1584 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been created
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00' DISABLE
DO
SELECT 1;
Warnings:
Note 1584 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been created
CREATE EVENT e4 ON SCHEDULE AT '1999-01-01 00:00:00' DO
SELECT 1;
Warnings:
Note 1584 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been created
CREATE EVENT e4 ON SCHEDULE AT '1999-01-01 00:00:00' DISABLE
DO
SELECT 1;
Warnings:
Note 1584 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. Event has not been created
SHOW EVENTS;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
events_test e1 root@localhost +05:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED
events_test e2 root@localhost -05:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED
events_test e3 root@localhost +00:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED
The following should succeed giving a warning.
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE;
Warnings:
Note 1533 Event execution time is in the past. Event has been disabled
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE
DO
SELECT 1;
Warnings:
Note 1533 Event execution time is in the past. Event has been disabled
CREATE EVENT e5 ON SCHEDULE AT '1999-01-01 00:00:00'
ON COMPLETION PRESERVE
DO
SELECT 1;
Warnings:
Note 1533 Event execution time is in the past. Event has been disabled
The following should succeed without warnings.
ALTER EVENT e2 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00';
ALTER EVENT e3 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE DISABLE;
CREATE EVENT e6 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00' DO
SELECT 1;
CREATE EVENT e7 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE DISABLE
DO
SELECT 1;
CREATE EVENT e8 ON SCHEDULE AT '1999-01-01 00:00:00'
ON COMPLETION PRESERVE DISABLE
DO
SELECT 1;
SHOW EVENTS;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
events_test e1 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 1999-01-02 00:00:00 DISABLED
events_test e2 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 NULL ENABLED
events_test e3 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 1999-01-02 00:00:00 DISABLED
events_test e4 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 1999-01-02 00:00:00 DISABLED
events_test e5 root@localhost +00:00 ONE TIME 1999-01-01 00:00:00 NULL NULL NULL NULL DISABLED
events_test e6 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 NULL ENABLED
events_test e7 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 1999-01-02 00:00:00 DISABLED
events_test e8 root@localhost +00:00 ONE TIME 1999-01-01 00:00:00 NULL NULL NULL NULL DISABLED
DROP EVENT e8;
DROP EVENT e7;
DROP EVENT e6;
DROP EVENT e5;
DROP EVENT e4;
DROP EVENT e3;
DROP EVENT e2;
DROP EVENT e1;
SET TIME_ZONE=@save_time_zone;
drop database events_test; drop database events_test;
create database if not exists mysqltest_events_test;
use mysqltest_events_test;
set global event_scheduler=off; set global event_scheduler=off;
drop database if exists events_test;
create database events_test;
use events_test;
create table execution_log(name char(10)); create table execution_log(name char(10));
create event abc1 on schedule every 1 second do insert into execution_log value('abc1'); create event abc1 on schedule every 1 second do
create event abc2 on schedule every 1 second do insert into execution_log value('abc2'); insert into execution_log value('abc1');
create event abc3 on schedule every 1 second do insert into execution_log value('abc3'); create event abc2 on schedule every 1 second do
select name from execution_log; insert into execution_log value('abc2');
name create event abc3 on schedule every 1 second do
insert into mysql.event values ('db1','bad','select 42','root@localhost',NULL,1000,'MICROSECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment1','SYSTEM'); insert into execution_log value('abc3');
insert into mysql.event values ('db1','bad2','sect','root@localhost',NULL,1000,'SECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment2','SYSTEM'); create table event_like like mysql.event;
insert into event_like select * from mysql.event;
alter table mysql.event
change column body body longtext character set utf8 collate utf8_bin;
"Now we restart the server" "Now we restart the server"
use mysqltest_events_test; use events_test;
"Should get 0 rows because the queue aborted run select @@event_scheduler;
select distinct name from execution_log order by name; @@event_scheduler
name DISABLED
delete from mysql.event where name like 'bad%'; show events;
"Now restart the server again" ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
select event_name from information_schema.events;
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
show create event intact_check;
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
drop event no_such_event;
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
create event intact_check_1 on schedule every 5 hour do select 5;
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
alter event intact_check_1 on schedule every 8 hour do select 8;
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
alter event intact_check_1 rename to intact_check_2;
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
drop event intact_check_1;
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
drop event intact_check_2;
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
drop event intact_check;
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
set global event_scheduler=on;
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
set global event_scheduler=off;
ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
show variables like 'event_scheduler';
Variable_name Value
event_scheduler DISABLED
Make sure that we still can create and drop databases,
and no warnings are produced.
drop database if exists mysqltest_database_not_exists;
Warnings:
Note 1008 Can't drop database 'mysqltest_database_not_exists'; database doesn't exist
create database mysqltest_db1;
drop database mysqltest_db1;
Restore the original mysql.event table
drop table mysql.event;
rename table event_like to mysql.event;
Now let's restart the server again
use mysqltest_events_test; use events_test;
select @@event_scheduler;
@@event_scheduler
ON
"Should get 3 rows : abc1, abc2, abc3 "Should get 3 rows : abc1, abc2, abc3
select distinct name from execution_log order by name; select distinct name from execution_log order by name;
name name
abc1 abc1
abc2 abc2
abc3 abc3
drop event abc1;
drop event abc2;
drop event abc3;
drop table execution_log; drop table execution_log;
drop database mysqltest_events_test; drop database events_test;
CREATE DATABASE IF NOT EXISTS events_test; CREATE DATABASE IF NOT EXISTS events_test;
USE events_test; USE events_test;
SET GLOBAL event_scheduler=OFF; SET GLOBAL event_scheduler=OFF;
Try agian to make sure it's allowed
SET GLOBAL event_scheduler=OFF;
SHOW VARIABLES LIKE 'event_scheduler'; SHOW VARIABLES LIKE 'event_scheduler';
Variable_name Value Variable_name Value
event_scheduler OFF event_scheduler OFF
...@@ -13,6 +15,8 @@ SHOW VARIABLES LIKE 'event_scheduler'; ...@@ -13,6 +15,8 @@ SHOW VARIABLES LIKE 'event_scheduler';
Variable_name Value Variable_name Value
event_scheduler OFF event_scheduler OFF
SET GLOBAL event_scheduler=ON; SET GLOBAL event_scheduler=ON;
Try again to make sure it's allowed
SET GLOBAL event_scheduler=ON;
SHOW VARIABLES LIKE 'event_scheduler'; SHOW VARIABLES LIKE 'event_scheduler';
Variable_name Value Variable_name Value
event_scheduler ON event_scheduler ON
......
...@@ -3,148 +3,6 @@ CREATE DATABASE mysqltest_db1; ...@@ -3,148 +3,6 @@ CREATE DATABASE mysqltest_db1;
USE mysqltest_db1; USE mysqltest_db1;
SET GLOBAL EVENT_SCHEDULER= OFF; SET GLOBAL EVENT_SCHEDULER= OFF;
SET @save_time_zone= @@TIME_ZONE; SET @save_time_zone= @@TIME_ZONE;
SET TIME_ZONE= '+00:00';
SET TIMESTAMP= UNIX_TIMESTAMP('2005-12-31 23:58:59');
CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
SHOW EVENTS;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
mysqltest_db1 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
mysqltest_db1 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
mysqltest_db1 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
mysqltest_db1 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
mysqltest_db1 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;
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 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
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
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
SHOW EVENTS;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status
mysqltest_db1 e1 root@localhost +05:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED
mysqltest_db1 e2 root@localhost -05:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED
mysqltest_db1 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
mysqltest_db1 e1 root@localhost +05:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED
mysqltest_db1 e2 root@localhost -05:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED
mysqltest_db1 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
mysqltest_db1 e1 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 1999-01-02 00:00:00 DISABLED
mysqltest_db1 e2 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 NULL ENABLED
mysqltest_db1 e3 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 1999-01-02 00:00:00 DISABLED
mysqltest_db1 e4 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 1999-01-02 00:00:00 DISABLED
mysqltest_db1 e5 root@localhost +00:00 ONE TIME 1999-01-01 00:00:00 NULL NULL NULL NULL DISABLED
mysqltest_db1 e6 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 NULL ENABLED
mysqltest_db1 e7 root@localhost +00:00 RECURRING NULL 1 HOUR 1999-01-01 00:00:00 1999-01-02 00:00:00 DISABLED
mysqltest_db1 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;
CREATE TABLE t_step (step INT); CREATE TABLE t_step (step INT);
INSERT INTO t_step VALUES (@step); INSERT INTO t_step VALUES (@step);
CREATE FUNCTION round_to_step(i INT, n INT) RETURNS INT CREATE FUNCTION round_to_step(i INT, n INT) RETURNS INT
......
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;
This diff is collapsed.
# Can't test with embedded server that doesn't support grants # Can't test with embedded server that doesn't support grants
-- source include/not_embedded.inc -- source include/not_embedded.inc
create database if not exists events_test; --disable_warnings
drop database if exists events_test;
drop database if exists mysqltest_db1;
drop database if exists mysqltest_db2;
--enable_warnings
create database events_test;
use events_test; use events_test;
# #
...@@ -428,6 +433,184 @@ connection default; ...@@ -428,6 +433,184 @@ connection default;
DROP USER mysqltest_u1@localhost; DROP USER mysqltest_u1@localhost;
#
# BUG#16420: Events: timestamps become UTC
# BUG#26429: SHOW CREATE EVENT is incorrect for an event that
# STARTS NOW()
# BUG#26431: Impossible to re-create an event from backup if its
# STARTS clause is in the past
# WL#3698: Events: execution in local time zone
#
# Here we only check non-concurrent aspects of the patch.
# For the actual tests of time zones please see events_time_zone.test
#
SET GLOBAL EVENT_SCHEDULER= OFF;
SET @save_time_zone= @@TIME_ZONE;
#----------------------------------------------------------------------
# We will use a separate connection because SET TIMESTAMP will stop
# the clock in that connection.
SET TIME_ZONE= '+00:00';
SET TIMESTAMP= UNIX_TIMESTAMP('2005-12-31 23:58:59');
# Test when event time zone is updated on ALTER EVENT.
#
CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
SHOW EVENTS;
# Test storing and updating of the event time zone.
#
SET TIME_ZONE= '-01:00';
ALTER EVENT e1 ON SCHEDULE EVERY 1 DAY STARTS '2000-01-01 00:00:00';
SHOW EVENTS;
# This will update event time zone.
SET TIME_ZONE= '+02:00';
ALTER EVENT e1 ON SCHEDULE AT '2000-01-02 00:00:00'
ON COMPLETION PRESERVE DISABLE;
SHOW EVENTS;
# This will update event time zone.
SET TIME_ZONE= '-03:00';
ALTER EVENT e1 ON SCHEDULE EVERY 1 DAY ENDS '2030-01-03 00:00:00'
ON COMPLETION PRESERVE DISABLE;
SHOW EVENTS;
# This will not update event time zone, as no time is being adjusted.
SET TIME_ZONE= '+04:00';
ALTER EVENT e1 DO SELECT 2;
SHOW EVENTS;
DROP EVENT e1;
#----------------------------------------------------------------------
# Create some events.
SET TIME_ZONE='+05:00';
CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
SELECT 1;
SET TIMESTAMP= @@TIMESTAMP + 1;
SET TIME_ZONE='-05:00';
CREATE EVENT e2 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
SELECT 1;
SET TIMESTAMP= @@TIMESTAMP + 1;
SET TIME_ZONE='+00:00';
CREATE EVENT e3 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
SELECT 1;
# Test INFORMATION_SCHEMA.EVENTS.
#
SELECT * FROM INFORMATION_SCHEMA.EVENTS ORDER BY event_name;
# Test SHOW EVENTS.
#
SHOW EVENTS;
# Test SHOW CREATE EVENT.
#
SHOW CREATE EVENT e1;
SHOW CREATE EVENT e2;
SHOW CREATE EVENT e3;
#----------------------------------------------------------------------
# Test times in the past.
#
--echo The following should fail, and nothing should be altered.
--error ER_EVENT_CANNOT_ALTER_IN_THE_PAST
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00';
--error ER_EVENT_CANNOT_ALTER_IN_THE_PAST
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00' DISABLE;
--echo The following should give warnings, and nothing should be created.
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00'
DO
SELECT 1;
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00' DISABLE
DO
SELECT 1;
CREATE EVENT e4 ON SCHEDULE AT '1999-01-01 00:00:00' DO
SELECT 1;
CREATE EVENT e4 ON SCHEDULE AT '1999-01-01 00:00:00' DISABLE
DO
SELECT 1;
SHOW EVENTS;
--echo The following should succeed giving a warning.
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE;
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE
DO
SELECT 1;
CREATE EVENT e5 ON SCHEDULE AT '1999-01-01 00:00:00'
ON COMPLETION PRESERVE
DO
SELECT 1;
--echo The following should succeed without warnings.
ALTER EVENT e2 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00';
ALTER EVENT e3 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE DISABLE;
CREATE EVENT e6 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00' DO
SELECT 1;
CREATE EVENT e7 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE DISABLE
DO
SELECT 1;
CREATE EVENT e8 ON SCHEDULE AT '1999-01-01 00:00:00'
ON COMPLETION PRESERVE DISABLE
DO
SELECT 1;
SHOW EVENTS;
DROP EVENT e8;
DROP EVENT e7;
DROP EVENT e6;
DROP EVENT e5;
DROP EVENT e4;
DROP EVENT e3;
DROP EVENT e2;
DROP EVENT e1;
SET TIME_ZONE=@save_time_zone;
# #
# End of tests # End of tests
# #
......
# Can't test with embedded server that doesn't support grants # Can't test with embedded server that doesn't support grants
-- source include/not_embedded.inc -- source include/not_embedded.inc
#
# Test that when the server is restarted, it checks mysql.event table,
# and disables the scheduler if it's not up to date.
#
# Switch off the scheduler for now.
set global event_scheduler=off;
--disable_warnings --disable_warnings
create database if not exists mysqltest_events_test; drop database if exists events_test;
--enable_warnings --enable_warnings
create database events_test;
use mysqltest_events_test; use events_test;
set global event_scheduler=off;
create table execution_log(name char(10)); create table execution_log(name char(10));
create event abc1 on schedule every 1 second do insert into execution_log value('abc1');
create event abc2 on schedule every 1 second do insert into execution_log value('abc2');
create event abc3 on schedule every 1 second do insert into execution_log value('abc3');
--sleep 1.5
select name from execution_log;
insert into mysql.event values ('db1','bad','select 42','root@localhost',NULL,1000,'MICROSECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment1','SYSTEM'); create event abc1 on schedule every 1 second do
insert into mysql.event values ('db1','bad2','sect','root@localhost',NULL,1000,'SECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment2','SYSTEM'); insert into execution_log value('abc1');
create event abc2 on schedule every 1 second do
insert into execution_log value('abc2');
create event abc3 on schedule every 1 second do
insert into execution_log value('abc3');
#
# There are various conditions when a server would regard mysql.event
# table as damaged:
# - the table has more column than specified in the compiled in value, but
# the version of the server which created the table is the same
# - the column count in the table is less than the compiled in value
# - some column has an incompatible type specification (for what is an
# incompatible type specification please refer to the comments in the source
#
# Unfortunately, in order to test a condition, we need to restart the
# server. Therefore, here we test only one simple case: changing the data
# type of the 'body' field to blob.
#
# First, let's do a backup to not depend on actual definition of mysql.event
create table event_like like mysql.event;
insert into event_like select * from mysql.event;
# Now let's alter the table and restart the server
alter table mysql.event
change column body body longtext character set utf8 collate utf8_bin;
--echo "Now we restart the server" --echo "Now we restart the server"
# Can't test with embedded server that doesn't support grants # Can't test with embedded server that doesn't support grants
-- source include/not_embedded.inc -- source include/not_embedded.inc
use mysqltest_events_test; use events_test;
--sleep 1.5 # Event scheduler should be disabled: the system tables are damaged
--echo "Should get 0 rows because the queue aborted run select @@event_scheduler;
select distinct name from execution_log order by name; # Try various Event Scheduler operation and check the output.
delete from mysql.event where name like 'bad%'; --error ER_EVENTS_DB_ERROR
--echo "Now restart the server again" show events;
--error ER_EVENTS_DB_ERROR
select event_name from information_schema.events;
--error ER_EVENTS_DB_ERROR
show create event intact_check;
--error ER_EVENTS_DB_ERROR
drop event no_such_event;
--error ER_EVENTS_DB_ERROR
create event intact_check_1 on schedule every 5 hour do select 5;
--error ER_EVENTS_DB_ERROR
alter event intact_check_1 on schedule every 8 hour do select 8;
--error ER_EVENTS_DB_ERROR
alter event intact_check_1 rename to intact_check_2;
--error ER_EVENTS_DB_ERROR
drop event intact_check_1;
--error ER_EVENTS_DB_ERROR
drop event intact_check_2;
--error ER_EVENTS_DB_ERROR
drop event intact_check;
--error ER_EVENTS_DB_ERROR
set global event_scheduler=on;
--error ER_EVENTS_DB_ERROR
set global event_scheduler=off;
show variables like 'event_scheduler';
--echo Make sure that we still can create and drop databases,
--echo and no warnings are produced.
drop database if exists mysqltest_database_not_exists;
create database mysqltest_db1;
drop database mysqltest_db1;
--echo Restore the original mysql.event table
drop table mysql.event;
rename table event_like to mysql.event;
--echo Now let's restart the server again
# Can't test with embedded server that doesn't support grants # Can't test with embedded server that doesn't support grants
-- source include/not_embedded.inc -- source include/not_embedded.inc
#
use mysqltest_events_test; # We need this file primarily to make sure that the scheduler is restarted
--sleep 2 # and enabled after we have restored mysql.event table.
# This is the final step of the "cleanup".
#
# Make sure also that events are executed OK after restart, just in case.
use events_test;
# Make sure the scheduler was started successfully
select @@event_scheduler;
let $wait_condition=select count(distinct name)=3 from execution_log;
--source include/wait_condition.inc
--echo "Should get 3 rows : abc1, abc2, abc3 --echo "Should get 3 rows : abc1, abc2, abc3
select distinct name from execution_log order by name; select distinct name from execution_log order by name;
drop event abc1;
drop event abc2;
drop event abc3;
drop table execution_log; drop table execution_log;
# Will drop all events
drop database mysqltest_events_test; drop database events_test;
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
CREATE DATABASE IF NOT EXISTS events_test; CREATE DATABASE IF NOT EXISTS events_test;
USE events_test; USE events_test;
SET GLOBAL event_scheduler=OFF;
--echo Try agian to make sure it's allowed
SET GLOBAL event_scheduler=OFF; SET GLOBAL event_scheduler=OFF;
SHOW VARIABLES LIKE 'event_scheduler'; SHOW VARIABLES LIKE 'event_scheduler';
SET GLOBAL event_scheduler=1; SET GLOBAL event_scheduler=1;
...@@ -12,6 +14,8 @@ SHOW VARIABLES LIKE 'event_scheduler'; ...@@ -12,6 +14,8 @@ SHOW VARIABLES LIKE 'event_scheduler';
SET GLOBAL event_scheduler=0; SET GLOBAL event_scheduler=0;
SHOW VARIABLES LIKE 'event_scheduler'; SHOW VARIABLES LIKE 'event_scheduler';
SET GLOBAL event_scheduler=ON; SET GLOBAL event_scheduler=ON;
--echo Try again to make sure it's allowed
SET GLOBAL event_scheduler=ON;
SHOW VARIABLES LIKE 'event_scheduler'; SHOW VARIABLES LIKE 'event_scheduler';
--error ER_WRONG_VALUE_FOR_VAR --error ER_WRONG_VALUE_FOR_VAR
SET GLOBAL event_scheduler=DISABLED; SET GLOBAL event_scheduler=DISABLED;
......
...@@ -20,6 +20,7 @@ let $old_db= `SELECT DATABASE()`; ...@@ -20,6 +20,7 @@ let $old_db= `SELECT DATABASE()`;
USE mysqltest_db1; USE mysqltest_db1;
SET GLOBAL EVENT_SCHEDULER= OFF; SET GLOBAL EVENT_SCHEDULER= OFF;
SET @save_time_zone= @@TIME_ZONE;
# #
...@@ -31,176 +32,6 @@ SET GLOBAL EVENT_SCHEDULER= OFF; ...@@ -31,176 +32,6 @@ SET GLOBAL EVENT_SCHEDULER= OFF;
# WL#3698: Events: execution in local time zone # WL#3698: Events: execution in local time zone
# #
SET @save_time_zone= @@TIME_ZONE;
#----------------------------------------------------------------------
# We will use a separate connection because SET TIMESTAMP will stop
# the clock in that connection.
connect (conn1, localhost, root, , mysqltest_db1);
SET TIME_ZONE= '+00:00';
SET TIMESTAMP= UNIX_TIMESTAMP('2005-12-31 23:58:59');
# Test when event time zone is updated on ALTER EVENT.
#
CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
SHOW EVENTS;
# Test storing and updating of the event time zone.
#
SET TIME_ZONE= '-01:00';
ALTER EVENT e1 ON SCHEDULE EVERY 1 DAY STARTS '2000-01-01 00:00:00';
SHOW EVENTS;
# This will update event time zone.
SET TIME_ZONE= '+02:00';
ALTER EVENT e1 ON SCHEDULE AT '2000-01-02 00:00:00'
ON COMPLETION PRESERVE DISABLE;
SHOW EVENTS;
# This will update event time zone.
SET TIME_ZONE= '-03:00';
ALTER EVENT e1 ON SCHEDULE EVERY 1 DAY ENDS '2030-01-03 00:00:00'
ON COMPLETION PRESERVE DISABLE;
SHOW EVENTS;
# This will not update event time zone, as no time is being adjusted.
SET TIME_ZONE= '+04:00';
ALTER EVENT e1 DO SELECT 2;
SHOW EVENTS;
DROP EVENT e1;
#----------------------------------------------------------------------
# Create some events.
SET TIME_ZONE='+05:00';
CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
SELECT 1;
SET TIMESTAMP= @@TIMESTAMP + 1;
SET TIME_ZONE='-05:00';
CREATE EVENT e2 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
SELECT 1;
SET TIMESTAMP= @@TIMESTAMP + 1;
SET TIME_ZONE='+00:00';
CREATE EVENT e3 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
SELECT 1;
# Test INFORMATION_SCHEMA.EVENTS.
#
SELECT * FROM INFORMATION_SCHEMA.EVENTS;
# Test SHOW EVENTS.
#
SHOW EVENTS;
# Test SHOW CREATE EVENT.
#
SHOW CREATE EVENT e1;
SHOW CREATE EVENT e2;
SHOW CREATE EVENT e3;
#----------------------------------------------------------------------
# Test times in the past.
#
--echo The following should fail, and nothing should be altered.
--error ER_EVENT_CANNOT_ALTER_IN_THE_PAST
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00';
--error ER_EVENT_CANNOT_ALTER_IN_THE_PAST
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00' DISABLE;
--echo The following should give warnings, and nothing should be created.
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00'
DO
SELECT 1;
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00' DISABLE
DO
SELECT 1;
CREATE EVENT e4 ON SCHEDULE AT '1999-01-01 00:00:00' DO
SELECT 1;
CREATE EVENT e4 ON SCHEDULE AT '1999-01-01 00:00:00' DISABLE
DO
SELECT 1;
SHOW EVENTS;
--echo The following should succeed giving a warning.
ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE;
CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE
DO
SELECT 1;
CREATE EVENT e5 ON SCHEDULE AT '1999-01-01 00:00:00'
ON COMPLETION PRESERVE
DO
SELECT 1;
--echo The following should succeed without warnings.
ALTER EVENT e2 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00';
ALTER EVENT e3 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE DISABLE;
CREATE EVENT e6 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00' DO
SELECT 1;
CREATE EVENT e7 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'
ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE DISABLE
DO
SELECT 1;
CREATE EVENT e8 ON SCHEDULE AT '1999-01-01 00:00:00'
ON COMPLETION PRESERVE DISABLE
DO
SELECT 1;
SHOW EVENTS;
DROP EVENT e8;
DROP EVENT e7;
DROP EVENT e6;
DROP EVENT e5;
DROP EVENT e4;
DROP EVENT e3;
DROP EVENT e2;
DROP EVENT e1;
disconnect conn1;
connection default;
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# Create rounding function. # Create rounding function.
......
#
# 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 @@ ...@@ -20,8 +20,6 @@
#include "event_db_repository.h" #include "event_db_repository.h"
#include "sp_head.h" #include "sp_head.h"
/* That's a provisional solution */
extern Event_db_repository events_event_db_repository;
#define EVEX_MAX_INTERVAL_VALUE 1000000000L #define EVEX_MAX_INTERVAL_VALUE 1000000000L
...@@ -215,7 +213,7 @@ Event_parse_data::init_body(THD *thd) ...@@ -215,7 +213,7 @@ Event_parse_data::init_body(THD *thd)
++body_begin; ++body_begin;
--body.length; --body.length;
} }
body.str= thd->strmake((char *)body_begin, body.length); body.str= thd->strmake(body_begin, body.length);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -694,7 +692,7 @@ Event_basic::load_string_fields(Field **fields, ...) ...@@ -694,7 +692,7 @@ Event_basic::load_string_fields(Field **fields, ...)
va_start(args, fields); va_start(args, fields);
field_name= (enum enum_events_table_field) va_arg(args, int); field_name= (enum enum_events_table_field) va_arg(args, int);
while (field_name != ET_FIELD_COUNT) while (field_name < ET_FIELD_COUNT)
{ {
field_value= va_arg(args, LEX_STRING *); field_value= va_arg(args, LEX_STRING *);
if ((field_value->str= get_field(&mem_root, fields[field_name])) == NullS) if ((field_value->str= get_field(&mem_root, fields[field_name])) == NullS)
...@@ -858,13 +856,19 @@ Event_job_data::load_from_row(THD *thd, TABLE *table) ...@@ -858,13 +856,19 @@ Event_job_data::load_from_row(THD *thd, TABLE *table)
if (!table) if (!table)
goto error; goto error;
if (table->s->fields != ET_FIELD_COUNT) if (table->s->fields < ET_FIELD_COUNT)
goto error; goto error;
LEX_STRING tz_name; LEX_STRING tz_name;
load_string_fields(table->field, ET_FIELD_DB, &dbname, ET_FIELD_NAME, &name, if (load_string_fields(table->field,
ET_FIELD_BODY, &body, ET_FIELD_DEFINER, &definer, ET_FIELD_DB, &dbname,
ET_FIELD_TIME_ZONE, &tz_name, ET_FIELD_COUNT); ET_FIELD_NAME, &name,
ET_FIELD_BODY, &body,
ET_FIELD_DEFINER, &definer,
ET_FIELD_TIME_ZONE, &tz_name,
ET_FIELD_COUNT))
goto error;
if (load_time_zone(thd, tz_name)) if (load_time_zone(thd, tz_name))
goto error; goto error;
...@@ -910,19 +914,24 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table) ...@@ -910,19 +914,24 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
{ {
char *ptr; char *ptr;
TIME time; TIME time;
LEX_STRING tz_name;
DBUG_ENTER("Event_queue_element::load_from_row"); DBUG_ENTER("Event_queue_element::load_from_row");
if (!table) if (!table)
goto error; goto error;
if (table->s->fields != ET_FIELD_COUNT) if (table->s->fields < ET_FIELD_COUNT)
goto error; goto error;
LEX_STRING tz_name; if (load_string_fields(table->field,
load_string_fields(table->field, ET_FIELD_DB, &dbname, ET_FIELD_NAME, &name, ET_FIELD_DB, &dbname,
ET_FIELD_NAME, &name,
ET_FIELD_DEFINER, &definer, ET_FIELD_DEFINER, &definer,
ET_FIELD_TIME_ZONE, &tz_name, ET_FIELD_COUNT); ET_FIELD_TIME_ZONE, &tz_name,
ET_FIELD_COUNT))
goto error;
if (load_time_zone(thd, tz_name)) if (load_time_zone(thd, tz_name))
goto error; goto error;
...@@ -1039,7 +1048,11 @@ Event_timed::load_from_row(THD *thd, TABLE *table) ...@@ -1039,7 +1048,11 @@ Event_timed::load_from_row(THD *thd, TABLE *table)
if (Event_queue_element::load_from_row(thd, table)) if (Event_queue_element::load_from_row(thd, table))
goto error; goto error;
load_string_fields(table->field, ET_FIELD_BODY, &body, ET_FIELD_COUNT); if (load_string_fields(table->field,
ET_FIELD_BODY, &body,
ET_FIELD_COUNT))
goto error;
ptr= strchr(definer.str, '@'); ptr= strchr(definer.str, '@');
...@@ -1594,10 +1607,8 @@ Event_queue_element::mark_last_executed(THD *thd) ...@@ -1594,10 +1607,8 @@ Event_queue_element::mark_last_executed(THD *thd)
bool bool
Event_queue_element::update_timing_fields(THD *thd) Event_queue_element::update_timing_fields(THD *thd)
{ {
TABLE *table; Event_db_repository *db_repository= Events::get_db_repository();
Field **fields; int ret;
Open_tables_state backup;
int ret= FALSE;
DBUG_ENTER("Event_queue_element::update_timing_fields"); DBUG_ENTER("Event_queue_element::update_timing_fields");
...@@ -1607,46 +1618,13 @@ Event_queue_element::update_timing_fields(THD *thd) ...@@ -1607,46 +1618,13 @@ Event_queue_element::update_timing_fields(THD *thd)
if (!(status_changed || last_executed_changed)) if (!(status_changed || last_executed_changed))
DBUG_RETURN(0); DBUG_RETURN(0);
thd->reset_n_backup_open_tables_state(&backup); ret= db_repository->update_timing_fields_for_event(thd,
dbname, name,
if (events_event_db_repository.open_event_table(thd, TL_WRITE, &table)) last_executed_changed,
{ last_executed,
ret= TRUE; status_changed,
goto done; (ulonglong) status);
} last_executed_changed= status_changed= FALSE;
fields= table->field;
if ((ret= events_event_db_repository.
find_named_event(thd, dbname, name, table)))
goto done;
store_record(table,record[1]);
/* Don't update create on row update. */
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
if (last_executed_changed)
{
TIME time;
my_tz_UTC->gmt_sec_to_TIME(&time, last_executed);
fields[ET_FIELD_LAST_EXECUTED]->set_notnull();
fields[ET_FIELD_LAST_EXECUTED]->store_time(&time,
MYSQL_TIMESTAMP_DATETIME);
last_executed_changed= FALSE;
}
if (status_changed)
{
fields[ET_FIELD_STATUS]->set_notnull();
fields[ET_FIELD_STATUS]->store((longlong)status, TRUE);
status_changed= FALSE;
}
if ((table->file->ha_update_row(table->record[1], table->record[0])))
ret= TRUE;
done:
close_thread_tables(thd);
thd->restore_backup_open_tables_state(&backup);
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#define EVEX_GET_FIELD_FAILED -2 #define EVEX_GET_FIELD_FAILED -2
#define EVEX_COMPILE_ERROR -3 #define EVEX_COMPILE_ERROR -3
#define EVEX_GENERAL_ERROR -4
#define EVEX_BAD_PARAMS -5 #define EVEX_BAD_PARAMS -5
#define EVEX_MICROSECOND_UNSUP -6 #define EVEX_MICROSECOND_UNSUP -6
...@@ -173,8 +172,6 @@ public: ...@@ -173,8 +172,6 @@ public:
ulong sql_mode; ulong sql_mode;
uint execution_count;
Event_job_data(); Event_job_data();
virtual ~Event_job_data(); virtual ~Event_job_data();
......
This diff is collapsed.
...@@ -15,7 +15,12 @@ ...@@ -15,7 +15,12 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define EVEX_OPEN_TABLE_FAILED -1 /*
@file
This is a private header file of Events module. Please do not include it
directly. All public declarations of Events module should be stored in
events.h and event_data_objects.h.
*/
enum enum_events_table_field enum enum_events_table_field
{ {
...@@ -69,17 +74,28 @@ public: ...@@ -69,17 +74,28 @@ public:
drop_schema_events(THD *thd, LEX_STRING schema); drop_schema_events(THD *thd, LEX_STRING schema);
bool bool
find_named_event(THD *thd, LEX_STRING db, LEX_STRING name, TABLE *table); find_named_event(LEX_STRING db, LEX_STRING name, TABLE *table);
bool bool
load_named_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_basic *et); load_named_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_basic *et);
int bool
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table); open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
int bool
fill_schema_events(THD *thd, TABLE_LIST *tables, const char *db); fill_schema_events(THD *thd, TABLE_LIST *tables, const char *db);
bool
update_timing_fields_for_event(THD *thd,
LEX_STRING event_db_name,
LEX_STRING event_name,
bool update_last_executed,
my_time_t last_executed,
bool update_status,
ulonglong status);
public:
static bool
check_system_tables(THD *thd);
private: private:
void void
drop_events_by_field(THD *thd, enum enum_events_table_field field, drop_events_by_field(THD *thd, enum enum_events_table_field field,
...@@ -91,9 +107,7 @@ private: ...@@ -91,9 +107,7 @@ private:
bool bool
table_scan_all_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table); table_scan_all_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table);
static bool private:
check_system_tables(THD *thd);
/* Prevent use of these */ /* Prevent use of these */
Event_db_repository(const Event_db_repository &); Event_db_repository(const Event_db_repository &);
void operator=(Event_db_repository &); void operator=(Event_db_repository &);
......
...@@ -72,39 +72,21 @@ event_queue_element_compare_q(void *vptr, byte* a, byte *b) ...@@ -72,39 +72,21 @@ event_queue_element_compare_q(void *vptr, byte* a, byte *b)
Event_queue::Event_queue() Event_queue::Event_queue()
:mutex_last_unlocked_at_line(0), mutex_last_locked_at_line(0), :mutex_last_unlocked_at_line(0), mutex_last_locked_at_line(0),
mutex_last_attempted_lock_at_line(0), mutex_last_attempted_lock_at_line(0),
mutex_queue_data_locked(FALSE), mutex_queue_data_attempting_lock(FALSE) mutex_queue_data_locked(FALSE),
mutex_queue_data_attempting_lock(FALSE),
next_activation_at(0)
{ {
mutex_last_unlocked_in_func= mutex_last_locked_in_func= mutex_last_unlocked_in_func= mutex_last_locked_in_func=
mutex_last_attempted_lock_in_func= ""; mutex_last_attempted_lock_in_func= "";
next_activation_at= 0;
}
/*
Inits mutexes.
SYNOPSIS
Event_queue::init_mutexes()
*/
void
Event_queue::init_mutexes()
{
pthread_mutex_init(&LOCK_event_queue, MY_MUTEX_INIT_FAST); pthread_mutex_init(&LOCK_event_queue, MY_MUTEX_INIT_FAST);
pthread_cond_init(&COND_queue_state, NULL); pthread_cond_init(&COND_queue_state, NULL);
} }
/* Event_queue::~Event_queue()
Destroys mutexes.
SYNOPSIS
Event_queue::deinit_mutexes()
*/
void
Event_queue::deinit_mutexes()
{ {
deinit_queue();
pthread_mutex_destroy(&LOCK_event_queue); pthread_mutex_destroy(&LOCK_event_queue);
pthread_cond_destroy(&COND_queue_state); pthread_cond_destroy(&COND_queue_state);
} }
...@@ -176,33 +158,47 @@ Event_queue::deinit_queue() ...@@ -176,33 +158,47 @@ Event_queue::deinit_queue()
/** /**
Adds an event to the queue. Adds an event to the queue.
SYNOPSIS Compute the next execution time for an event, and if it is still
Event_queue::create_event() active, add it to the queue. Otherwise delete it.
dbname The schema of the new event The object is left intact in case of an error. Otherwise
name The name of the new event the queue container assumes ownership of it.
@param[in] thd thread handle
@param[in] new_element a new element to add to the queue
@param[out] created set to TRUE if no error and the element is
added to the queue, FALSE otherwise
@retval TRUE an error occured. The value of created is undefined,
the element was not deleted.
@retval FALSE success
*/ */
void bool
Event_queue::create_event(THD *thd, Event_queue_element *new_element) Event_queue::create_event(THD *thd, Event_queue_element *new_element,
bool *created)
{ {
DBUG_ENTER("Event_queue::create_event"); DBUG_ENTER("Event_queue::create_event");
DBUG_PRINT("enter", ("thd: 0x%lx et=%s.%s", (long) thd, DBUG_PRINT("enter", ("thd: 0x%lx et=%s.%s", (long) thd,
new_element->dbname.str, new_element->name.str)); new_element->dbname.str, new_element->name.str));
/* Will do nothing if the event is disabled */
new_element->compute_next_execution_time();
if (new_element->status == Event_queue_element::DISABLED) if (new_element->status == Event_queue_element::DISABLED)
delete new_element;
else
{ {
new_element->compute_next_execution_time(); delete new_element;
*created= FALSE;
DBUG_RETURN(FALSE);
}
DBUG_PRINT("info", ("new event in the queue: 0x%lx", (long) new_element)); DBUG_PRINT("info", ("new event in the queue: 0x%lx", (long) new_element));
LOCK_QUEUE_DATA(); LOCK_QUEUE_DATA();
queue_insert_safe(&queue, (byte *) new_element); *created= (queue_insert_safe(&queue, (byte *) new_element) == FALSE);
dbug_dump_queue(thd->query_start()); dbug_dump_queue(thd->query_start());
pthread_cond_broadcast(&COND_queue_state); pthread_cond_broadcast(&COND_queue_state);
UNLOCK_QUEUE_DATA(); UNLOCK_QUEUE_DATA();
}
DBUG_VOID_RETURN; DBUG_RETURN(!*created);
} }
......
...@@ -25,23 +25,16 @@ class Event_queue ...@@ -25,23 +25,16 @@ class Event_queue
{ {
public: public:
Event_queue(); Event_queue();
~Event_queue();
void
init_mutexes();
void
deinit_mutexes();
bool bool
init_queue(THD *thd); init_queue(THD *thd);
void
deinit_queue();
/* Methods for queue management follow */ /* Methods for queue management follow */
void bool
create_event(THD *thd, Event_queue_element *new_element); create_event(THD *thd, Event_queue_element *new_element,
bool *created);
void void
update_event(THD *thd, LEX_STRING dbname, LEX_STRING name, update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
...@@ -64,9 +57,23 @@ public: ...@@ -64,9 +57,23 @@ public:
void void
dump_internal_status(); dump_internal_status();
private:
void void
empty_queue(); empty_queue();
protected:
void
deinit_queue();
/* helper functions for working with mutexes & conditionals */
void
lock_data(const char *func, uint line);
void
unlock_data(const char *func, uint line);
void
cond_wait(THD *thd, struct timespec *abstime, const char* msg,
const char *func, uint line);
void void
find_n_remove_event(LEX_STRING db, LEX_STRING name); find_n_remove_event(LEX_STRING db, LEX_STRING name);
...@@ -98,16 +105,6 @@ protected: ...@@ -98,16 +105,6 @@ protected:
bool mutex_queue_data_attempting_lock; bool mutex_queue_data_attempting_lock;
bool waiting_on_cond; bool waiting_on_cond;
/* helper functions for working with mutexes & conditionals */
void
lock_data(const char *func, uint line);
void
unlock_data(const char *func, uint line);
void
cond_wait(THD *thd, struct timespec *abstime, const char* msg,
const char *func, uint line);
}; };
#endif /* _EVENT_QUEUE_H_ */ #endif /* _EVENT_QUEUE_H_ */
...@@ -37,7 +37,6 @@ extern pthread_attr_t connection_attrib; ...@@ -37,7 +37,6 @@ extern pthread_attr_t connection_attrib;
Event_db_repository *Event_worker_thread::db_repository; Event_db_repository *Event_worker_thread::db_repository;
Events *Event_worker_thread::events_facade;
static static
...@@ -80,11 +79,11 @@ Event_worker_thread::print_warnings(THD *thd, Event_job_data *et) ...@@ -80,11 +79,11 @@ Event_worker_thread::print_warnings(THD *thd, Event_job_data *et)
prefix.length(0); prefix.length(0);
prefix.append("Event Scheduler: ["); prefix.append("Event Scheduler: [");
append_identifier(thd, &prefix, et->definer.str, et->definer.length); prefix.append(et->definer.str, et->definer.length, system_charset_info);
prefix.append("][", 2); prefix.append("][", 2);
append_identifier(thd,&prefix, et->dbname.str, et->dbname.length); prefix.append(et->dbname.str, et->dbname.length, system_charset_info);
prefix.append('.'); prefix.append('.');
append_identifier(thd,&prefix, et->name.str, et->name.length); prefix.append(et->name.str, et->name.length, system_charset_info);
prefix.append("] ", 2); prefix.append("] ", 2);
List_iterator_fast<MYSQL_ERROR> it(thd->warn_list); List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
...@@ -95,7 +94,6 @@ Event_worker_thread::print_warnings(THD *thd, Event_job_data *et) ...@@ -95,7 +94,6 @@ Event_worker_thread::print_warnings(THD *thd, Event_job_data *et)
err_msg.length(0); err_msg.length(0);
err_msg.append(prefix); err_msg.append(prefix);
err_msg.append(err->msg, strlen(err->msg), system_charset_info); err_msg.append(err->msg, strlen(err->msg), system_charset_info);
err_msg.append("]");
DBUG_ASSERT(err->level < 3); DBUG_ASSERT(err->level < 3);
(sql_print_message_handlers[err->level])("%*s", err_msg.length(), (sql_print_message_handlers[err->level])("%*s", err_msg.length(),
err_msg.c_ptr()); err_msg.c_ptr());
...@@ -239,7 +237,7 @@ event_scheduler_thread(void *arg) ...@@ -239,7 +237,7 @@ event_scheduler_thread(void *arg)
} }
/* /**
Function that executes an event in a child thread. Setups the Function that executes an event in a child thread. Setups the
environment for the event execution and cleans after that. environment for the event execution and cleans after that.
...@@ -266,7 +264,7 @@ event_worker_thread(void *arg) ...@@ -266,7 +264,7 @@ event_worker_thread(void *arg)
} }
/* /**
Function that executes an event in a child thread. Setups the Function that executes an event in a child thread. Setups the
environment for the event execution and cleans after that. environment for the event execution and cleans after that.
...@@ -315,17 +313,27 @@ Event_worker_thread::run(THD *thd, Event_queue_element_for_exec *event) ...@@ -315,17 +313,27 @@ Event_worker_thread::run(THD *thd, Event_queue_element_for_exec *event)
print_warnings(thd, job_data); print_warnings(thd, job_data);
switch (ret) {
case 0:
sql_print_information("Event Scheduler: " sql_print_information("Event Scheduler: "
"[%s.%s of %s] executed in thread %lu. " "[%s].[%s.%s] executed successfully in thread %lu.",
"RetCode=%d", job_data->dbname.str, job_data->name.str, job_data->definer.str,
job_data->definer.str, thd->thread_id, ret);
if (ret == EVEX_COMPILE_ERROR)
sql_print_information("Event Scheduler: "
"COMPILE ERROR for event %s.%s of %s",
job_data->dbname.str, job_data->name.str, job_data->dbname.str, job_data->name.str,
job_data->definer.str); thd->thread_id);
else if (ret == EVEX_MICROSECOND_UNSUP) break;
sql_print_information("Event Scheduler: MICROSECOND is not supported"); case EVEX_COMPILE_ERROR:
sql_print_information("Event Scheduler: "
"[%s].[%s.%s] event compilation failed.",
job_data->definer.str,
job_data->dbname.str, job_data->name.str);
break;
default:
sql_print_information("Event Scheduler: "
"[%s].[%s.%s] event execution failed.",
job_data->definer.str,
job_data->dbname.str, job_data->name.str);
break;
}
end: end:
delete job_data; delete job_data;
...@@ -349,66 +357,34 @@ end: ...@@ -349,66 +357,34 @@ end:
problem. However, this comes at the price of introduction bi-directional problem. However, this comes at the price of introduction bi-directional
association between class Events and class Event_worker_thread. association between class Events and class Event_worker_thread.
*/ */
events_facade->drop_event(thd, event->dbname, event->name, FALSE); Events::drop_event(thd, event->dbname, event->name, FALSE);
} }
DBUG_PRINT("info", ("Done with Event %s.%s", event->dbname.str, DBUG_PRINT("info", ("Done with Event %s.%s", event->dbname.str,
event->name.str)); event->name.str));
delete event; delete event;
deinit_event_thread(thd); deinit_event_thread(thd);
pthread_exit(0); /*
} Do not pthread_exit since we want local destructors for stack objects
to be invoked.
*/
/*
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::Event_scheduler(Event_queue *queue_arg)
Event_scheduler::deinit_scheduler() {} :state(UNINITIALIZED),
scheduler_thd(NULL),
queue(queue_arg),
/* started_events(0)
Inits scheduler's threading primitives.
SYNOPSIS
Event_scheduler::init_mutexes()
*/
void
Event_scheduler::init_mutexes()
{ {
pthread_mutex_init(&LOCK_scheduler_state, MY_MUTEX_INIT_FAST); pthread_mutex_init(&LOCK_scheduler_state, MY_MUTEX_INIT_FAST);
pthread_cond_init(&COND_state, NULL); pthread_cond_init(&COND_state, NULL);
} }
/* Event_scheduler::~Event_scheduler()
Deinits scheduler's threading primitives.
SYNOPSIS
Event_scheduler::deinit_mutexes()
*/
void
Event_scheduler::deinit_mutexes()
{ {
stop(); /* does nothing if not running */
pthread_mutex_destroy(&LOCK_scheduler_state); pthread_mutex_destroy(&LOCK_scheduler_state);
pthread_cond_destroy(&COND_state); pthread_cond_destroy(&COND_state);
} }
...@@ -639,6 +615,9 @@ Event_scheduler::is_running() ...@@ -639,6 +615,9 @@ Event_scheduler::is_running()
Stops the scheduler (again). Waits for acknowledgement from the Stops the scheduler (again). Waits for acknowledgement from the
scheduler that it has stopped - synchronous stopping. scheduler that it has stopped - synchronous stopping.
Already running events will not be stopped. If the user needs
them stopped manual intervention is needed.
SYNOPSIS SYNOPSIS
Event_scheduler::stop() Event_scheduler::stop()
......
...@@ -15,7 +15,8 @@ ...@@ -15,7 +15,8 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* /**
@file
This file is internal to Events module. Please do not include it directly. This file is internal to Events module. Please do not include it directly.
All public declarations of Events module are in events.h and All public declarations of Events module are in events.h and
event_data_objects.h. event_data_objects.h.
...@@ -41,10 +42,9 @@ class Event_worker_thread ...@@ -41,10 +42,9 @@ class Event_worker_thread
{ {
public: public:
static void static void
init(Events *events, Event_db_repository *db_repo) init(Event_db_repository *db_repository_arg)
{ {
db_repository= db_repo; db_repository= db_repository_arg;
events_facade= events;
} }
void void
...@@ -55,15 +55,15 @@ private: ...@@ -55,15 +55,15 @@ private:
print_warnings(THD *thd, Event_job_data *et); print_warnings(THD *thd, Event_job_data *et);
static Event_db_repository *db_repository; static Event_db_repository *db_repository;
static Events *events_facade;
}; };
class Event_scheduler class Event_scheduler
{ {
public: public:
Event_scheduler():state(UNINITIALIZED){} Event_scheduler(Event_queue *event_queue_arg);
~Event_scheduler(){} ~Event_scheduler();
/* State changing methods follow */ /* State changing methods follow */
...@@ -80,17 +80,6 @@ public: ...@@ -80,17 +80,6 @@ public:
bool bool
run(THD *thd); run(THD *thd);
void
init_scheduler(Event_queue *queue);
void
deinit_scheduler();
void
init_mutexes();
void
deinit_mutexes();
/* Information retrieving methods follow */ /* Information retrieving methods follow */
bool bool
......
This diff is collapsed.
This diff is collapsed.
...@@ -890,7 +890,7 @@ static void close_connections(void) ...@@ -890,7 +890,7 @@ static void close_connections(void)
} }
(void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list (void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
Events::get_instance()->deinit(); Events::deinit();
end_slave(); end_slave();
if (thread_count) if (thread_count)
...@@ -1335,7 +1335,7 @@ static void clean_up_mutexes() ...@@ -1335,7 +1335,7 @@ static void clean_up_mutexes()
(void) pthread_mutex_destroy(&LOCK_bytes_sent); (void) pthread_mutex_destroy(&LOCK_bytes_sent);
(void) pthread_mutex_destroy(&LOCK_bytes_received); (void) pthread_mutex_destroy(&LOCK_bytes_received);
(void) pthread_mutex_destroy(&LOCK_user_conn); (void) pthread_mutex_destroy(&LOCK_user_conn);
Events::get_instance()->destroy_mutexes(); Events::destroy_mutexes();
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
(void) pthread_mutex_destroy(&LOCK_des_key_file); (void) pthread_mutex_destroy(&LOCK_des_key_file);
#ifndef HAVE_YASSL #ifndef HAVE_YASSL
...@@ -3062,7 +3062,7 @@ static int init_thread_environment() ...@@ -3062,7 +3062,7 @@ static int init_thread_environment()
(void) pthread_mutex_init(&LOCK_server_started, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_server_started, MY_MUTEX_INIT_FAST);
(void) pthread_cond_init(&COND_server_started,NULL); (void) pthread_cond_init(&COND_server_started,NULL);
sp_cache_init(); sp_cache_init();
Events::get_instance()->init_mutexes(); Events::init_mutexes();
/* Parameter for threads created for connections */ /* Parameter for threads created for connections */
(void) pthread_attr_init(&connection_attrib); (void) pthread_attr_init(&connection_attrib);
(void) pthread_attr_setdetachstate(&connection_attrib, (void) pthread_attr_setdetachstate(&connection_attrib,
...@@ -3841,21 +3841,15 @@ we force server id to 2, but this MySQL server will not act as a slave."); ...@@ -3841,21 +3841,15 @@ we force server id to 2, but this MySQL server will not act as a slave.");
create_shutdown_thread(); create_shutdown_thread();
create_maintenance_thread(); create_maintenance_thread();
if (Events::init(opt_noacl))
unireg_abort(1);
sql_print_information(ER(ER_STARTUP),my_progname,server_version, sql_print_information(ER(ER_STARTUP),my_progname,server_version,
((unix_sock == INVALID_SOCKET) ? (char*) "" ((unix_sock == INVALID_SOCKET) ? (char*) ""
: mysqld_unix_port), : mysqld_unix_port),
mysqld_port, mysqld_port,
MYSQL_COMPILATION_COMMENT); MYSQL_COMPILATION_COMMENT);
if (!opt_noacl)
{
if (Events::get_instance()->init())
unireg_abort(1);
}
else
{
Events::opt_event_scheduler = Events::EVENTS_DISABLED;
}
/* Signal threads waiting for server to be started */ /* Signal threads waiting for server to be started */
pthread_mutex_lock(&LOCK_server_started); pthread_mutex_lock(&LOCK_server_started);
...@@ -7568,32 +7562,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), ...@@ -7568,32 +7562,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
} }
#endif #endif
case OPT_EVENT_SCHEDULER: case OPT_EVENT_SCHEDULER:
if (!argument) if (Events::set_opt_event_scheduler(argument))
Events::opt_event_scheduler= Events::EVENTS_DISABLED;
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); exit(1);
case 5: /* OPT_DISABLED */
Events::opt_event_scheduler= Events::EVENTS_DISABLED;
break;
case 2: /* OPT_ON */
case 4: /* 1 */
Events::opt_event_scheduler= Events::EVENTS_ON;
break;
case 1: /* OPT_OFF */
case 3: /* 0 */
Events::opt_event_scheduler= Events::EVENTS_OFF;
break;
}
}
break; break;
case (int) OPT_SKIP_NEW: case (int) OPT_SKIP_NEW:
opt_specialflag|= SPECIAL_NO_NEW_FUNC; opt_specialflag|= SPECIAL_NO_NEW_FUNC;
......
This diff is collapsed.
...@@ -61,7 +61,7 @@ public: ...@@ -61,7 +61,7 @@ public:
sys_vars++; sys_vars++;
} }
virtual bool check(THD *thd, set_var *var); virtual bool check(THD *thd, set_var *var);
bool check_enum(THD *thd, set_var *var, TYPELIB *enum_names); bool check_enum(THD *thd, set_var *var, const TYPELIB *enum_names);
bool check_set(THD *thd, set_var *var, TYPELIB *enum_names); bool check_set(THD *thd, set_var *var, TYPELIB *enum_names);
virtual bool update(THD *thd, set_var *var)=0; virtual bool update(THD *thd, set_var *var)=0;
virtual void set_default(THD *thd_arg, enum_var_type type) {} virtual void set_default(THD *thd_arg, enum_var_type type) {}
...@@ -440,8 +440,8 @@ public: ...@@ -440,8 +440,8 @@ public:
} }
void set_default(THD *thd, enum_var_type type); void set_default(THD *thd, enum_var_type type);
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
static byte *symbolic_mode_representation(THD *thd, ulonglong sql_mode, static bool symbolic_mode_representation(THD *thd, ulonglong sql_mode,
ulong *length); LEX_STRING *rep);
}; };
......
...@@ -5884,8 +5884,8 @@ ER_COL_COUNT_DOESNT_MATCH_CORRUPTED ...@@ -5884,8 +5884,8 @@ ER_COL_COUNT_DOESNT_MATCH_CORRUPTED
eng "Column count of mysql.%s is wrong. Expected %d, found %d. The table is probably corrupted" eng "Column count of mysql.%s is wrong. Expected %d, found %d. The table is probably corrupted"
ger "Spaltenanzahl von mysql.%s falsch. %d erwartet, aber %d gefunden. Tabelle ist wahrscheinlich beschdigt" ger "Spaltenanzahl von mysql.%s falsch. %d erwartet, aber %d gefunden. Tabelle ist wahrscheinlich beschdigt"
ER_CANNOT_LOAD_FROM_TABLE ER_CANNOT_LOAD_FROM_TABLE
eng "Cannot load from mysql.%s. The table is probably corrupted. Please see the error log for details" eng "Cannot load from mysql.%s. The table is probably corrupted"
ger "Kann mysql.%s nicht einlesen. Tabelle ist wahrscheinlich beschdigt, siehe Fehlerlog" ger "Kann mysql.%s nicht einlesen. Tabelle ist wahrscheinlich beschdigt"
ER_EVENT_CANNOT_DELETE ER_EVENT_CANNOT_DELETE
eng "Failed to delete the event from mysql.event" eng "Failed to delete the event from mysql.event"
ger "Lschen des Events aus mysql.event fehlgeschlagen" ger "Lschen des Events aus mysql.event fehlgeschlagen"
......
This diff is collapsed.
...@@ -953,7 +953,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) ...@@ -953,7 +953,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
exit: exit:
(void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */ (void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */
Events::get_instance()->drop_schema_events(thd, db); Events::drop_schema_events(thd, db);
/* /*
If this database was the client's selected database, we silently If this database was the client's selected database, we silently
change the client's selected database to nothing (to have an empty change the client's selected database to nothing (to have an empty
......
This diff is collapsed.
This diff is collapsed.
...@@ -537,6 +537,6 @@ Estimated memory (with thread stack): %ld\n", ...@@ -537,6 +537,6 @@ Estimated memory (with thread stack): %ld\n",
(long) (thread_count * thread_stack + info.hblkhd + info.arena)); (long) (thread_count * thread_stack + info.hblkhd + info.arena));
#endif #endif
Events::get_instance()->dump_internal_status(); Events::dump_internal_status();
puts(""); puts("");
} }
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment