From 772eddf08111dbc5a365fabe3433060bb1fac595 Mon Sep 17 00:00:00 2001
From: unknown <andrey@lmy004.>
Date: Mon, 10 Jul 2006 13:44:43 +0200
Subject: [PATCH] WL#3337 (Event scheduler new architecture) This patch
 introduces specialized Event data objects Event_basic as parent.
 Event_queue_element used for queue storage Event_timed used for SHOW EVENTS/
 I_S.EVENTS / SHOW CREATE EVENT Event_job_data using during execution. Methods
 were moved out of Event_timed to other classes.

This patch also introduces Events::LOCK_event_metadata.
This patch gives new implementation of Events::dump_internal_status().
Now both the Event_scheduler and Event_queue return information during
their ::dump_internal_status().

Shortened a bit the runtime for executing events test cases.


mysql-test/r/events.result:
  update results
mysql-test/r/events_bugs.result:
  update results
mysql-test/r/events_logs_tests.result:
  update results
mysql-test/r/events_scheduling.result:
  update results
mysql-test/t/events.test:
  update test
  make --sleep more appropriate . saving some time could mean failure on loaded boxes though :(
  add tests for previously uncovered branches.
mysql-test/t/events_bugs.test:
  update test
  make --sleep more appropriate . saving some time could mean failure on loaded boxes though :(
  add tests for previously uncovered branches.
mysql-test/t/events_logs_tests.test:
  make the test shorter by time
mysql-test/t/events_scheduling.test:
  when selecting always use ORDER BY
mysql-test/t/events_stress.test:
  sleep 2.5secs for shorter stress test
sql/event_data_objects.cc:
  Event_timed is no more used during execution.
  Event_timed is no more used during in the memory queue.
  Event_timed is only used for SHOW CREATE EVENT/ I_S.EVENTS/ SHOW EVENTS
  Event_basic is the parent of almost all Event data objects.
  Event_basic -> Event_queue_element (used for the memory queue) -> Event_timed
  Event_basic -> Event_job_data (the object used for execution)
  Sql_alloc -> Event_parse_data (used during parsing)
sql/event_data_objects.h:
  Event_timed is no more used during execution.
  Event_timed is no more used during in the memory queue.
  Event_timed is only used for SHOW CREATE EVENT/ I_S.EVENTS/ SHOW EVENTS
  Event_basic is the parent of almost all Event data objects.
  Event_basic -> Event_queue_element (used for the memory queue) -> Event_timed
  Event_basic -> Event_job_data (the object used for execution)
  Sql_alloc -> Event_parse_data (used during parsing)
sql/event_db_repository.cc:
  Cosmetics.
  load_named_event now uses Event_basic, for polymorphism
  find_event uses Event_basic, to be polymorphic.
  use Field **fields= table->field and then index fields[...]
  Add documentation.
  Fix documentation.
sql/event_db_repository.h:
  Event_db_repository depends only on Event_basic's interface
sql/event_queue.cc:
  Cosmetics.
  Don't use Event_timed for the queue and giving back object for execution.
  Event_queue_element is for the queue, Event_job_data is for execution.
  Add Event_queue::dump_internal_status() for SHOW SCHEDULER STATUS command
sql/event_queue.h:
  Cosmetics.
  Don't use Event_timed for the queue and giving back object for execution.
  Event_queue_element is for the queue, Event_job_data is for execution.
  Add Event_queue::dump_internal_status() for SHOW SCHEDULER STATUS command
sql/event_scheduler_ng.cc:
  Add back Event_scheduler::cond_wait()
  Add back Event_scheduler::dump_internal_status()
  Using Event_job_data for execution. Make the scheduler thread unkillable (thd->command= COM_DAEMON).
  Add a lot of documentation.
sql/event_scheduler_ng.h:
  Add back Event_scheduler::cond_wait()
  Add back Event_scheduler::dump_internal_status()
  Using Event_job_data for execution.
sql/events.cc:
  Documentation
  Add LOCK_event_metadata
sql/events.h:
  Change the signature of Events::drop_event() not to use sp_name but LEX_STRING
sql/share/errmsg.txt:
  Fix error message
sql/sql_parse.cc:
  Events::drop_event() has new signature
---
 mysql-test/r/events.result            |   9 +-
 mysql-test/r/events_bugs.result       |  48 +-
 mysql-test/r/events_logs_tests.result |  10 +-
 mysql-test/r/events_scheduling.result |   2 +-
 mysql-test/t/events.test              |  16 +-
 mysql-test/t/events_bugs.test         |  47 +-
 mysql-test/t/events_logs_tests.test   |  15 +-
 mysql-test/t/events_scheduling.test   |   2 +-
 mysql-test/t/events_stress.test       |   4 +-
 sql/event_data_objects.cc             | 766 ++++++++++++++++++--------
 sql/event_data_objects.h              | 202 ++++---
 sql/event_db_repository.cc            | 525 ++++++------------
 sql/event_db_repository.h             |  29 +-
 sql/event_queue.cc                    | 653 ++++++++++++----------
 sql/event_queue.h                     |  49 +-
 sql/event_scheduler_ng.cc             | 455 ++++++++++++---
 sql/event_scheduler_ng.h              |  14 +-
 sql/events.cc                         | 228 +++++---
 sql/events.h                          |  17 +-
 sql/share/errmsg.txt                  |   2 +-
 sql/sql_parse.cc                      |   8 +-
 21 files changed, 1852 insertions(+), 1249 deletions(-)

diff --git a/mysql-test/r/events.result b/mysql-test/r/events.result
index a6d385e17ef..2128624786d 100644
--- a/mysql-test/r/events.result
+++ b/mysql-test/r/events.result
@@ -87,7 +87,6 @@ events_test	event_starts_test	root@localhost	RECURRING	NULL	20	SECOND	#	#	ENABLE
 DROP EVENT event_starts_test;
 create table test_nested(a int);
 create event e_43 on schedule every 1 second do set @a = 5;
-set global event_scheduler = 1;
 alter event e_43 do alter event e_43 do set @a = 4;
 ERROR HY000: Recursivity of EVENT DDL statements is forbidden when body is present
 alter event e_43 do
@@ -207,6 +206,10 @@ ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
 SHOW EVENTS;
 ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
 drop event root22;
+create event root23 on schedule every -100 year do select 1;
+ERROR HY000: INTERVAL is either not positive or too big
+create event root23 on schedule every 222222222222222222222 year do select 1;
+ERROR HY000: INTERVAL is either not positive or too big
 drop event root6;
 drop event root7;
 drop event root8;
@@ -342,7 +345,7 @@ create event закачка on schedule every 10 hour do select get_lock("test_l
 "Should have only 2 processes: the scheduler and the locked event"
 select /*2*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
 user	host	db	command	state	info
-event_scheduler	localhost	NULL	Connect	Waiting for next activation	NULL
+event_scheduler	localhost	NULL	Daemon	Waiting for next activation	NULL
 root	localhost	events_test	Connect	User lock	select get_lock("test_lock2", 20)
 "Release the mutex, the event worker should finish."
 "Release the mutex, the event worker should finish."
@@ -358,7 +361,7 @@ create event закачка21 on schedule every 10 hour do select get_lock("test
 "Should have only 3 processes: the scheduler, our conn and the locked event"
 select /*3*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
 user	host	db	command	state	info
-event_scheduler	localhost	NULL	Connect	Waiting for next activation	NULL
+event_scheduler	localhost	NULL	Daemon	Waiting for next activation	NULL
 root	localhost	events_test	Connect	User lock	select get_lock("test_lock2_1", 20)
 set global event_scheduler=2;
 "Should have only our process now:"
diff --git a/mysql-test/r/events_bugs.result b/mysql-test/r/events_bugs.result
index 416312438b4..e6115161cbb 100644
--- a/mysql-test/r/events_bugs.result
+++ b/mysql-test/r/events_bugs.result
@@ -24,8 +24,19 @@ create event e_55 on schedule every 10 hour starts 99990101000000 do drop table
 ERROR HY000: Incorrect STARTS value: '99990101000000'
 create event e_55 on schedule every 10 minute ends 99990101000000 do drop table t;
 ERROR HY000: ENDS is either invalid or before STARTS
+create event e_55 on schedule at 10000101000000 do drop table t;
+ERROR HY000: Activation (AT) time is in the past
+create event e_55 on schedule at 20000101000000 do drop table t;
+ERROR HY000: Activation (AT) time is in the past
+create event e_55 on schedule at 20200101000000 starts 10000101000000 do drop table t;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'starts 10000101000000 do drop table t' at line 1
+create event e_55 on schedule at 20200101000000 ends 10000101000000 do drop table t;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'ends 10000101000000 do drop table t' at line 1
+create event e_55 on schedule at 20200101000000 starts 10000101000000 ends 10000101000000 do drop table t;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'starts 10000101000000 ends 10000101000000 do drop table t' at line 1
+create event e_55 on schedule every 10 hour starts 10000101000000 do drop table t;
+ERROR HY000: Incorrect STARTS value: '10000101000000'
 set global event_scheduler=2;
-"Wait a bit to settle down"
 delete from mysql.event;
 set global event_scheduler= 1;
 set @old_sql_mode:=@@sql_mode;
@@ -41,7 +52,7 @@ end|
 "Now if everything is fine the event has compiled and is locked
 select /*1*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
 user	host	db	command	state	info
-event_scheduler	localhost	NULL	Connect	Waiting for next activation	NULL
+event_scheduler	localhost	NULL	Daemon	Waiting for next activation	NULL
 root	localhost	events_test	Connect	User lock	select get_lock('test_bug16407', 60)
 select release_lock('test_bug16407');
 release_lock('test_bug16407')
@@ -57,6 +68,11 @@ select event_schema, event_name, sql_mode from information_schema.events order b
 event_schema	event_name	sql_mode
 events_test	e_16407	STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
 drop event e_16407;
+set sql_mode="ansi";
+select get_lock('ee_16407_2', 60);
+get_lock('ee_16407_2', 60)
+1
+set global event_scheduler= 1;
 "Another sql_mode test"
 set sql_mode="traditional";
 create table events_smode_test(ev_name char(10), a date) engine=myisam;
@@ -64,6 +80,7 @@ create table events_smode_test(ev_name char(10), a date) engine=myisam;
 create event ee_16407_2 on schedule every 60 second do
 begin
 select get_lock('ee_16407_2', 60) /*ee_16407_2*/;
+select release_lock('ee_16407_2');
 insert into events_test.events_smode_test values('ee_16407_2','1980-19-02');
 end|
 insert into events_smode_test values ('test','1980-19-02')|
@@ -72,6 +89,7 @@ ERROR 22007: Incorrect date value: '1980-19-02' for column 'a' at row 1
 create event ee_16407_3 on schedule every 60 second do
 begin
 select get_lock('ee_16407_2', 60) /*ee_16407_3*/;
+select release_lock('ee_16407_2');
 insert into events_test.events_smode_test values ('ee_16407_3','1980-02-19');
 insert into events_test.events_smode_test values ('ee_16407_3','1980-02-29');
 end|
@@ -80,6 +98,7 @@ set sql_mode=""|
 create event ee_16407_4 on schedule every 60 second do
 begin
 select get_lock('ee_16407_2', 60) /*ee_16407_4*/;
+select release_lock('ee_16407_2');
 insert into events_test.events_smode_test values ('ee_16407_4','10-11-1956');
 end|
 select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
@@ -87,14 +106,9 @@ event_schema	event_name	sql_mode
 events_test	ee_16407_2	STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
 events_test	ee_16407_3	STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
 events_test	ee_16407_4	
-set sql_mode="ansi";
-select get_lock('ee_16407_2', 60);
-get_lock('ee_16407_2', 60)
-1
-set global event_scheduler= 1;
 select /*2*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
 user	host	db	command	state	info
-event_scheduler	localhost	NULL	Connect	Waiting for next activation	NULL
+event_scheduler	localhost	NULL	Daemon	Waiting for next activation	NULL
 root	localhost	events_test	Connect	User lock	select get_lock('ee_16407_2', 60) /*ee_16407_2*/
 root	localhost	events_test	Connect	User lock	select get_lock('ee_16407_2', 60) /*ee_16407_3*/
 root	localhost	events_test	Connect	User lock	select get_lock('ee_16407_2', 60) /*ee_16407_4*/
@@ -103,7 +117,7 @@ release_lock('ee_16407_2')
 1
 select /*3*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
 user	host	db	command	state	info
-event_scheduler	localhost	NULL	Connect	Waiting for next activation	NULL
+event_scheduler	localhost	NULL	Daemon	Waiting for next activation	NULL
 set global event_scheduler= 2;
 select * from events_smode_test order by ev_name, a;
 ev_name	a
@@ -121,28 +135,30 @@ drop event ee_16407_3;
 drop event ee_16407_4;
 "And now one last test regarding sql_mode and call of SP from an event"
 delete from events_smode_test;
+set sql_mode='ansi';
+select get_lock('ee_16407_5', 60);
+get_lock('ee_16407_5', 60)
+1
+set global event_scheduler= 1;
 set sql_mode='traditional';
 create procedure ee_16407_5_pendant() begin insert into events_test.events_smode_test values('ee_16407_5','2001-02-29'); end|
 create procedure ee_16407_6_pendant() begin insert into events_test.events_smode_test values('ee_16407_6','2004-02-29'); end|
 create event ee_16407_5 on schedule every 60 second do
 begin
 select get_lock('ee_16407_5', 60) /*ee_16407_5*/;
+select release_lock('ee_16407_5');
 call events_test.ee_16407_5_pendant();
 end|
 create event ee_16407_6 on schedule every 60 second do
 begin
 select get_lock('ee_16407_5', 60) /*ee_16407_6*/;
+select release_lock('ee_16407_5');
 call events_test.ee_16407_6_pendant();
 end|
-set sql_mode='ansi';
-select get_lock('ee_16407_5', 60);
-get_lock('ee_16407_5', 60)
-1
-set global event_scheduler= 1;
 "Should have 2 locked processes"
 select /*4*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
 user	host	db	command	state	info
-event_scheduler	localhost	NULL	Connect	Waiting for next activation	NULL
+event_scheduler	localhost	NULL	Daemon	Waiting for next activation	NULL
 root	localhost	events_test	Connect	User lock	select get_lock('ee_16407_5', 60) /*ee_16407_5*/
 root	localhost	events_test	Connect	User lock	select get_lock('ee_16407_5', 60) /*ee_16407_6*/
 select release_lock('ee_16407_5');
@@ -151,7 +167,7 @@ release_lock('ee_16407_5')
 "Should have 0 processes locked"
 select /*5*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
 user	host	db	command	state	info
-event_scheduler	localhost	NULL	Connect	Waiting for next activation	NULL
+event_scheduler	localhost	NULL	Daemon	Waiting for next activation	NULL
 select * from events_smode_test order by ev_name, a;
 ev_name	a
 ee_16407_6	2004-02-29
diff --git a/mysql-test/r/events_logs_tests.result b/mysql-test/r/events_logs_tests.result
index 9202d63fd2c..885efb404f4 100644
--- a/mysql-test/r/events_logs_tests.result
+++ b/mysql-test/r/events_logs_tests.result
@@ -9,7 +9,7 @@ SELECT user_host, argument FROM mysql.general_log WHERE argument LIKE '%alabala%
 END|
 "Check General Query Log"
 SET GLOBAL event_scheduler=2;
-create event log_general on schedule every 1 minute do SELect 'alabala', sleep(3) from dual;
+create event log_general on schedule every 1 minute do SELect 'alabala', sleep(1) from dual;
 TRUNCATE mysql.general_log;
 "1 row, the current statement!"
 call select_general_log();
@@ -19,7 +19,7 @@ SET GLOBAL event_scheduler=1;
 "Should see 3 rows - the 'SELect' is in the middle. The other two are selects from general_log"
 call select_general_log();
 user_host	argument
-USER_HOST	SELect 'alabala', sleep(3) from dual
+USER_HOST	SELect 'alabala', sleep(1) from dual
 DROP PROCEDURE select_general_log;
 DROP EVENT log_general;
 SET GLOBAL event_scheduler=2;
@@ -49,13 +49,13 @@ USER_HOST	SLEEPVAL	events_test	SELECT SLEEP(2)
 SET SESSION long_query_time=300;
 "Make it quite long"
 TRUNCATE mysql.slow_log;
-SET SESSION long_query_time=1;
 CREATE TABLE slow_event_test (slo_val tinyint, val tinyint);
 "This won't go to the slow log"
-CREATE EVENT long_event ON SCHEDULE EVERY 1 MINUTE DO INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(3);
 SELECT * FROM slow_event_test;
 slo_val	val
+SET SESSION long_query_time=1;
 SET GLOBAL event_scheduler=1;
+CREATE EVENT long_event ON SCHEDULE EVERY 1 MINUTE DO INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(1.5);
 "Sleep some more time than the actual event run will take"
 SHOW VARIABLES LIKE 'event_scheduler';
 Variable_name	Value
@@ -64,7 +64,7 @@ event_scheduler	1
 SELECT * FROM slow_event_test;
 slo_val	val
 4	0
-"Check slow log. Should not see anything because 3 is under the threshold of 4 for GLOBAL, though over SESSION which is 2"
+"Check slow log. Should not see anything because 1.5 is under the threshold of 300 for GLOBAL, though over SESSION which is 2"
 SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
 user_host	query_time	db	sql_text
 "This should go to the slow log"
diff --git a/mysql-test/r/events_scheduling.result b/mysql-test/r/events_scheduling.result
index eb44751c176..d7b7241db51 100644
--- a/mysql-test/r/events_scheduling.result
+++ b/mysql-test/r/events_scheduling.result
@@ -39,7 +39,7 @@ DROP EVENT start_n_end;
 DROP EVENT only_one_time;
 ERROR HY000: Unknown event 'only_one_time'
 "Should be preserved"
-SELECT EVENT_NAME, STATUS FROM INFORMATION_SCHEMA.EVENTS;
+SELECT EVENT_NAME, STATUS FROM INFORMATION_SCHEMA.EVENTS ORDER BY EVENT_NAME;
 EVENT_NAME	STATUS
 E19170	ENABLED
 two_time	DISABLED
diff --git a/mysql-test/t/events.test b/mysql-test/t/events.test
index 5dff48c203b..34c00a6387a 100644
--- a/mysql-test/t/events.test
+++ b/mysql-test/t/events.test
@@ -18,7 +18,7 @@ CREATE EVENT e_x2 ON SCHEDULE EVERY 1 SECOND DO DROP TABLE x_table;
 connection default;
 SHOW DATABASES LIKE 'db_x';
 SET GLOBAL event_scheduler=1;
---sleep 1.5
+--sleep 0.8
 SHOW DATABASES LIKE 'db_x';
 SHOW TABLES FROM db_x;
 SET GLOBAL event_scheduler=2;
@@ -83,7 +83,6 @@ DROP EVENT event_starts_test;
 #
 create table test_nested(a int);
 create event e_43 on schedule every 1 second do set @a = 5;
-set global event_scheduler = 1;
 --error 1562
 alter event e_43 do alter event e_43 do set @a = 4;
 delimiter |;
@@ -94,7 +93,7 @@ begin
 end|
 delimiter ;|
 set global event_scheduler = 1;
---sleep 1
+--sleep 3
 select db, name, body, status, interval_field, interval_value from mysql.event;
 drop event e_43;
 drop table test_nested;
@@ -102,7 +101,7 @@ drop table test_nested;
 --echo "Let's check whether we can use non-qualified names"
 create table non_qualif(a int);
 create event non_qualif_ev on schedule every 10 minute do insert into non_qualif values (800219);
---sleep 1
+--sleep 0.5
 select * from non_qualif;
 drop event non_qualif_ev;
 drop table non_qualif;
@@ -165,6 +164,10 @@ show create event root22;
 --error ER_NOT_SUPPORTED_YET
 SHOW EVENTS;
 drop event root22;
+--error ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG
+create event root23 on schedule every -100 year do select 1;
+--error ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG
+create event root23 on schedule every 222222222222222222222 year do select 1;
 drop event root6;
 drop event root7;
 drop event root8;
@@ -294,7 +297,7 @@ select get_lock("test_lock2", 20);
 --echo "Create an event which tries to acquire a mutex. The event locks on the mutex"
 create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20);
 --echo "Let some time pass to the event starts"
---sleep 1
+--sleep 0.5
 --echo "Should have only 2 processes: the scheduler and the locked event"
 select /*2*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;--echo "Release the mutex, the event worker should finish."
 --echo "Release the mutex, the event worker should finish."
@@ -312,10 +315,11 @@ drop event закачка;
 set global event_scheduler=1;
 select get_lock("test_lock2_1", 20);
 create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20);
---sleep 1
+--sleep 0.5
 --echo "Should have only 3 processes: the scheduler, our conn and the locked event"
 select /*3*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
 set global event_scheduler=2;
+--sleep 0.3
 --echo "Should have only our process now:"
 select /*4*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
 drop event закачка21;
diff --git a/mysql-test/t/events_bugs.test b/mysql-test/t/events_bugs.test
index 4ff114555ca..7fd4c684b4b 100644
--- a/mysql-test/t/events_bugs.test
+++ b/mysql-test/t/events_bugs.test
@@ -45,6 +45,19 @@ create event e_55 on schedule at 99990101000000 do drop table t;
 create event e_55 on schedule every 10 hour starts 99990101000000 do drop table t;
 --error ER_EVENT_ENDS_BEFORE_STARTS
 create event e_55 on schedule every 10 minute ends 99990101000000 do drop table t;
+--error ER_EVENT_EXEC_TIME_IN_THE_PAST
+create event e_55 on schedule at 10000101000000 do drop table t;
+--error ER_EVENT_EXEC_TIME_IN_THE_PAST
+create event e_55 on schedule at 20000101000000 do drop table t;
+--error ER_PARSE_ERROR
+create event e_55 on schedule at 20200101000000 starts 10000101000000 do drop table t;
+--error ER_PARSE_ERROR
+create event e_55 on schedule at 20200101000000 ends 10000101000000 do drop table t;
+--error ER_PARSE_ERROR
+create event e_55 on schedule at 20200101000000 starts 10000101000000 ends 10000101000000 do drop table t;
+--error ER_WRONG_VALUE
+create event e_55 on schedule every 10 hour starts 10000101000000 do drop table t;
+
 #
 # End  -  16396: Events: Distant-future dates become past dates
 #
@@ -53,8 +66,6 @@ create event e_55 on schedule every 10 minute ends 99990101000000 do drop table
 # Start - 16407: Events: Changes in sql_mode won't be taken into account
 #
 set global event_scheduler=2;
---echo "Wait a bit to settle down"
---sleep 1
 delete from mysql.event;
 set global event_scheduler= 1;
 set @old_sql_mode:=@@sql_mode;
@@ -67,11 +78,13 @@ begin
   drop table "hashed_num";
 end|
 delimiter ;|
---sleep 1
+--sleep 0.5
 --echo "Now if everything is fine the event has compiled and is locked
 select /*1*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
 select release_lock('test_bug16407');
+
 set global event_scheduler= 2;
+
 select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
 --echo "Let's check whether we change the sql_mode on ALTER EVENT"
 set sql_mode='traditional';
@@ -79,6 +92,10 @@ alter event e_16407 do select 1;
 select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
 drop event e_16407;
 
+set sql_mode="ansi";
+select get_lock('ee_16407_2', 60);
+
+set global event_scheduler= 1;
 --echo "Another sql_mode test"
 set sql_mode="traditional";
 create table events_smode_test(ev_name char(10), a date) engine=myisam;
@@ -87,6 +104,7 @@ delimiter |;
 create event ee_16407_2 on schedule every 60 second do
 begin
   select get_lock('ee_16407_2', 60) /*ee_16407_2*/;
+  select release_lock('ee_16407_2');
   insert into events_test.events_smode_test values('ee_16407_2','1980-19-02');
 end|
 --error ER_TRUNCATED_WRONG_VALUE
@@ -95,6 +113,7 @@ insert into events_smode_test values ('test','1980-19-02')|
 create event ee_16407_3 on schedule every 60 second do
 begin
   select get_lock('ee_16407_2', 60) /*ee_16407_3*/;
+  select release_lock('ee_16407_2');
   insert into events_test.events_smode_test values ('ee_16407_3','1980-02-19');
   insert into events_test.events_smode_test values ('ee_16407_3','1980-02-29');
 end|
@@ -103,17 +122,15 @@ set sql_mode=""|
 create event ee_16407_4 on schedule every 60 second do
 begin
   select get_lock('ee_16407_2', 60) /*ee_16407_4*/;
+  select release_lock('ee_16407_2');
   insert into events_test.events_smode_test values ('ee_16407_4','10-11-1956');
 end|
 delimiter ;|
 select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
-set sql_mode="ansi";
-select get_lock('ee_16407_2', 60);
-set global event_scheduler= 1;
---sleep 1
+--sleep 0.5
 select /*2*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
 select release_lock('ee_16407_2');
---sleep 2
+--sleep 0.8
 select /*3*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
 set global event_scheduler= 2;
 select * from events_smode_test order by ev_name, a;
@@ -126,6 +143,11 @@ drop event ee_16407_4;
 
 --echo "And now one last test regarding sql_mode and call of SP from an event"
 delete from events_smode_test;
+set sql_mode='ansi';
+select get_lock('ee_16407_5', 60);
+
+set global event_scheduler= 1;
+
 set sql_mode='traditional';
 delimiter |;
 create procedure ee_16407_5_pendant() begin insert into events_test.events_smode_test values('ee_16407_5','2001-02-29'); end|
@@ -133,22 +155,21 @@ create procedure ee_16407_6_pendant() begin insert into events_test.events_smode
 create event ee_16407_5 on schedule every 60 second do
 begin
   select get_lock('ee_16407_5', 60) /*ee_16407_5*/;
+  select release_lock('ee_16407_5');
   call events_test.ee_16407_5_pendant();
 end|
 create event ee_16407_6 on schedule every 60 second do
 begin
   select get_lock('ee_16407_5', 60) /*ee_16407_6*/;
+  select release_lock('ee_16407_5');
   call events_test.ee_16407_6_pendant();
 end|
 delimiter ;|
-set sql_mode='ansi';
-select get_lock('ee_16407_5', 60);
-set global event_scheduler= 1;
---sleep 1
+--sleep 0.5
 --echo "Should have 2 locked processes"
 select /*4*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
 select release_lock('ee_16407_5');
---sleep 2
+--sleep 0.8
 --echo "Should have 0 processes locked"
 select /*5*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
 select * from events_smode_test order by ev_name, a;
diff --git a/mysql-test/t/events_logs_tests.test b/mysql-test/t/events_logs_tests.test
index 5f4ec852cd3..0cf073f2280 100644
--- a/mysql-test/t/events_logs_tests.test
+++ b/mysql-test/t/events_logs_tests.test
@@ -14,7 +14,7 @@ END|
 delimiter ;|
 --echo "Check General Query Log"
 SET GLOBAL event_scheduler=2;
-create event log_general on schedule every 1 minute do SELect 'alabala', sleep(3) from dual;
+create event log_general on schedule every 1 minute do SELect 'alabala', sleep(1) from dual;
 TRUNCATE mysql.general_log;
 --echo "1 row, the current statement!"
 --replace_column 1 USER_HOST
@@ -22,13 +22,12 @@ call select_general_log();
 SET GLOBAL event_scheduler=1;
 --echo "Wait the scheduler to start"
 --echo "Should see 3 rows - the 'SELect' is in the middle. The other two are selects from general_log"
---sleep 2
+--sleep 0.7
 --replace_column 1 USER_HOST
 call select_general_log();
 DROP PROCEDURE select_general_log;
 DROP EVENT log_general;
 SET GLOBAL event_scheduler=2;
---sleep 1
 
 --echo "Check slow query log"
 --disable_query_log
@@ -69,18 +68,18 @@ SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
 SET SESSION long_query_time=300;
 --echo "Make it quite long"
 TRUNCATE mysql.slow_log;
-SET SESSION long_query_time=1;
 CREATE TABLE slow_event_test (slo_val tinyint, val tinyint);
 --echo "This won't go to the slow log"
-CREATE EVENT long_event ON SCHEDULE EVERY 1 MINUTE DO INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(3);
 SELECT * FROM slow_event_test;
+SET SESSION long_query_time=1;
 SET GLOBAL event_scheduler=1;
+CREATE EVENT long_event ON SCHEDULE EVERY 1 MINUTE DO INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(1.5);
 --echo "Sleep some more time than the actual event run will take"
---sleep 5
+--sleep 2
 SHOW VARIABLES LIKE 'event_scheduler';
 --echo "Check our table. Should see 1 row"
 SELECT * FROM slow_event_test;
---echo "Check slow log. Should not see anything because 3 is under the threshold of 4 for GLOBAL, though over SESSION which is 2"
+--echo "Check slow log. Should not see anything because 1.5 is under the threshold of 300 for GLOBAL, though over SESSION which is 2"
 SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
 --echo "This should go to the slow log"
 DROP EVENT long_event;
@@ -88,7 +87,7 @@ SET SESSION long_query_time=10;
 SET GLOBAL long_query_time=1;
 CREATE EVENT long_event2 ON SCHEDULE EVERY 1 MINUTE DO INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(2);
 --echo "Sleep some more time than the actual event run will take"
---sleep 3
+--sleep 2.5
 --echo "Check our table. Should see 2 rows"
 SELECT * FROM slow_event_test;
 --echo "Check slow log. Should see 1 row because 4 is over the threshold of 3 for GLOBAL, though under SESSION which is 10"
diff --git a/mysql-test/t/events_scheduling.test b/mysql-test/t/events_scheduling.test
index 987939bc162..dc4460999a7 100644
--- a/mysql-test/t/events_scheduling.test
+++ b/mysql-test/t/events_scheduling.test
@@ -34,7 +34,7 @@ DROP EVENT start_n_end;
 --error ER_EVENT_DOES_NOT_EXIST
 DROP EVENT only_one_time;
 --echo "Should be preserved"
-SELECT EVENT_NAME, STATUS FROM INFORMATION_SCHEMA.EVENTS;
+SELECT EVENT_NAME, STATUS FROM INFORMATION_SCHEMA.EVENTS ORDER BY EVENT_NAME;
 DROP EVENT two_time;
 DROP TABLE table_1;
 DROP TABLE table_2;
diff --git a/mysql-test/t/events_stress.test b/mysql-test/t/events_stress.test
index 7700a12efab..7b1efdea1ba 100644
--- a/mysql-test/t/events_stress.test
+++ b/mysql-test/t/events_stress.test
@@ -61,7 +61,7 @@ while ($1)
 --enable_query_log
 SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
 SET GLOBAL event_scheduler=1;
---sleep 12
+--sleep 2.5
 DROP DATABASE events_conn1_test2;
 
 SET GLOBAL event_scheduler=2;
@@ -100,7 +100,7 @@ while ($1)
 }
 --enable_query_log
 SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
---sleep 12
+--sleep 2.5
 connection conn2;
 --send
 DROP DATABASE events_conn2_db;
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc
index 0e984bd4c7a..7b88699273e 100644
--- a/sql/event_data_objects.cc
+++ b/sql/event_data_objects.cc
@@ -22,7 +22,7 @@
 #include "sp_head.h"
 
 
-#define EVEX_MAX_INTERVAL_VALUE 2147483647L
+#define EVEX_MAX_INTERVAL_VALUE 1000000000L
 
 
 /*
@@ -54,6 +54,8 @@ Event_parse_data::new_instance(THD *thd)
 
 Event_parse_data::Event_parse_data()
 {
+  DBUG_ENTER("Event_parse_data::Event_parse_data");
+
   item_execute_at= item_expression= item_starts= item_ends= NULL;
   status= ENABLED;
   on_completion= ON_COMPLETION_DROP;
@@ -65,8 +67,10 @@ Event_parse_data::Event_parse_data()
   set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
   starts_null= ends_null= execute_at_null= TRUE;
 
-  body.str= comment.str= 0;
+  body.str= comment.str= NULL;
   body.length= comment.length= 0;
+
+  DBUG_VOID_RETURN;
 }
 
 
@@ -120,7 +124,7 @@ void
 Event_parse_data::init_body(THD *thd)
 {
   DBUG_ENTER("Event_parse_data::init_body");
-  DBUG_PRINT("info", ("body=[%s] body_begin=0x%ld end=0x%ld", body_begin,
+  DBUG_PRINT("info", ("body=[%s] body_begin=0x%lx end=0x%lx", body_begin,
              body_begin, thd->lex->ptr));
 
   body.length= thd->lex->ptr - body_begin;
@@ -138,7 +142,7 @@ Event_parse_data::init_body(THD *thd)
       continue;
     }
 
-    /*  
+    /*
        consume closing comments
 
        This is arguably wrong, but it's the best we have until the parser is
@@ -235,17 +239,20 @@ Event_parse_data::init_definer(THD *thd)
 */
 
 int
-Event_parse_data::init_execute_at(THD *thd, Item *expr)
+Event_parse_data::init_execute_at(THD *thd)
 {
   my_bool not_used;
   TIME ltime;
   my_time_t t;
-
   TIME time_tmp;
+
   DBUG_ENTER("Event_parse_data::init_execute_at");
 
-  if (expr->fix_fields(thd, &expr))
-    DBUG_RETURN(EVEX_PARSE_ERROR);
+  if (!item_execute_at)
+    DBUG_RETURN(0);
+
+  if (item_execute_at->fix_fields(thd, &item_execute_at))
+    goto wrong_value;
   
   /* no starts and/or ends in case of execute_at */
   DBUG_PRINT("info", ("starts_null && ends_null should be 1 is %d",
@@ -256,12 +263,15 @@ Event_parse_data::init_execute_at(THD *thd, Item *expr)
   thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, 
                                             (my_time_t) thd->query_start());
 
-  if ((not_used= expr->get_date(&ltime, TIME_NO_ZERO_DATE)))
-    DBUG_RETURN(ER_WRONG_VALUE);
+  if ((not_used= item_execute_at->get_date(&ltime, TIME_NO_ZERO_DATE)))
+    goto wrong_value;
 
   if (TIME_to_ulonglong_datetime(&ltime) <
       TIME_to_ulonglong_datetime(&time_tmp))
-    DBUG_RETURN(EVEX_BAD_PARAMS);
+  {
+    my_error(ER_EVENT_EXEC_TIME_IN_THE_PAST, MYF(0));
+    DBUG_RETURN(ER_WRONG_VALUE);
+  }
 
   /*
     This may result in a 1970-01-01 date if ltime is > 2037-xx-xx.
@@ -273,12 +283,16 @@ Event_parse_data::init_execute_at(THD *thd, Item *expr)
   if (!t)
   {
     DBUG_PRINT("error", ("Execute AT after year 2037"));
-    DBUG_RETURN(ER_WRONG_VALUE);
+    goto wrong_value;
   }
 
   execute_at_null= FALSE;
   execute_at= ltime;
   DBUG_RETURN(0);
+
+wrong_value:
+  report_bad_value("AT", item_execute_at);
+  DBUG_RETURN(ER_WRONG_VALUE);
 }
 
 
@@ -291,30 +305,44 @@ Event_parse_data::init_execute_at(THD *thd, Item *expr)
       new_interval  what is the interval
 
   RETURN VALUE
-    0                  OK
-    EVEX_PARSE_ERROR   fix_fields failed
-    EVEX_BAD_PARAMS    Interval is not positive
-    EVEX_MICROSECOND_UNSUP  Microseconds are not supported.
+    0                       OK
+    EVEX_PARSE_ERROR        fix_fields failed (reported)
+    EVEX_BAD_PARAMS         Interval is not positive (reported)
+    EVEX_MICROSECOND_UNSUP  Microseconds are not supported (reported)
 */
 
 int
-Event_parse_data::init_interval(THD *thd, Item *expr, interval_type new_interval)
+Event_parse_data::init_interval(THD *thd)
 {
   String value;
   INTERVAL interval_tmp;
 
   DBUG_ENTER("Event_parse_data::init_interval");
+  if (!item_expression)
+    DBUG_RETURN(0);
+
+  switch (interval) {
+  case INTERVAL_MINUTE_MICROSECOND:
+  case INTERVAL_HOUR_MICROSECOND:
+  case INTERVAL_DAY_MICROSECOND:
+  case INTERVAL_SECOND_MICROSECOND:
+  case INTERVAL_MICROSECOND:
+    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "MICROSECOND");
+    DBUG_RETURN(EVEX_BAD_PARAMS);
+  default:
+    break;
+  }
 
-  if (expr->fix_fields(thd, &expr))
-    DBUG_RETURN(EVEX_PARSE_ERROR);
+  if (item_expression->fix_fields(thd, &item_expression))
+    goto wrong_value;
 
   value.alloc(MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN);
-  if (get_interval_value(expr, new_interval, &value, &interval_tmp))
-    DBUG_RETURN(EVEX_PARSE_ERROR);
+  if (get_interval_value(item_expression, interval, &value, &interval_tmp))
+    goto wrong_value;
 
   expression= 0;
 
-  switch (new_interval) {
+  switch (interval) {
   case INTERVAL_YEAR:
     expression= interval_tmp.year;
     break;
@@ -352,39 +380,33 @@ Event_parse_data::init_interval(THD *thd, Item *expr, interval_type new_interval
                   interval_tmp.minute)*60
                  + interval_tmp.second;
     break;
-  case INTERVAL_MINUTE_MICROSECOND: /* day and hour are 0 */
-  case INTERVAL_HOUR_MICROSECOND:   /* day is anyway 0    */
-  case INTERVAL_DAY_MICROSECOND:
-    DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
-    expression= ((((interval_tmp.day*24) + interval_tmp.hour)*60+
-                  interval_tmp.minute)*60 +
-                 interval_tmp.second) * 1000000L + interval_tmp.second_part;
-    break;
   case INTERVAL_HOUR_MINUTE:
     expression= interval_tmp.hour * 60 + interval_tmp.minute;
     break;
   case INTERVAL_MINUTE_SECOND:
     expression= interval_tmp.minute * 60 + interval_tmp.second;
     break;
-  case INTERVAL_SECOND_MICROSECOND:
-    DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
-    expression= interval_tmp.second * 1000000L + interval_tmp.second_part;
-    break;
-  case INTERVAL_MICROSECOND:
-    DBUG_RETURN(EVEX_MICROSECOND_UNSUP);  
   case INTERVAL_LAST:
     DBUG_ASSERT(0);
+  default:
+    ;/* these are the microsec stuff */
   }
   if (interval_tmp.neg || expression > EVEX_MAX_INTERVAL_VALUE)
+  {
+    my_error(ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG, MYF(0));
     DBUG_RETURN(EVEX_BAD_PARAMS);
+  }
 
-  interval= new_interval;
   DBUG_RETURN(0);
+
+wrong_value:
+  report_bad_value("INTERVAL", item_execute_at);
+  DBUG_RETURN(ER_WRONG_VALUE);
 }
 
 
 /*
-  Set activation time.
+  Sets activation time.
 
   SYNOPSIS
     Event_parse_data::init_starts()
@@ -406,19 +428,21 @@ Event_parse_data::init_interval(THD *thd, Item *expr, interval_type new_interval
 */
 
 int
-Event_parse_data::init_starts(THD *thd, Item *new_starts)
+Event_parse_data::init_starts(THD *thd)
 {
   my_bool not_used;
   TIME ltime, time_tmp;
   my_time_t t;
 
   DBUG_ENTER("Event_parse_data::init_starts");
+  if (!item_starts)
+    DBUG_RETURN(0);
 
-  if (new_starts->fix_fields(thd, &new_starts))
-    DBUG_RETURN(EVEX_PARSE_ERROR);
+  if (item_starts->fix_fields(thd, &item_starts))
+    goto wrong_value;
 
-  if ((not_used= new_starts->get_date(&ltime, TIME_NO_ZERO_DATE)))
-    DBUG_RETURN(EVEX_BAD_PARAMS);
+  if ((not_used= item_starts->get_date(&ltime, TIME_NO_ZERO_DATE)))
+    goto wrong_value;
 
   /* Let's check whether time is in the past */
   thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp,
@@ -428,7 +452,7 @@ Event_parse_data::init_starts(THD *thd, Item *new_starts)
   DBUG_PRINT("info",("starts=%lld", TIME_to_ulonglong_datetime(&ltime)));
   if (TIME_to_ulonglong_datetime(&ltime) <
       TIME_to_ulonglong_datetime(&time_tmp))
-    DBUG_RETURN(EVEX_BAD_PARAMS);
+    goto wrong_value;
 
   /*
     This may result in a 1970-01-01 date if ltime is > 2037-xx-xx.
@@ -438,24 +462,25 @@ Event_parse_data::init_starts(THD *thd, Item *new_starts)
   */
   my_tz_UTC->gmt_sec_to_TIME(&ltime,t=TIME_to_timestamp(thd, &ltime, &not_used));
   if (!t)
-  {
-    DBUG_PRINT("error", ("STARTS after year 2037"));
-    DBUG_RETURN(EVEX_BAD_PARAMS);
-  }
+    goto wrong_value;
 
   starts= ltime;
   starts_null= FALSE;
   DBUG_RETURN(0);
+
+wrong_value:
+  report_bad_value("STARTS", item_starts);
+  DBUG_RETURN(ER_WRONG_VALUE);
 }
 
 
 /*
-  Set deactivation time.
+  Sets deactivation time.
 
   SYNOPSIS
     Event_parse_data::init_ends()
       thd       THD
-      new_ends  when?
+      new_ends  When?
 
   NOTES
     Note that activation time is not execution time.
@@ -467,26 +492,26 @@ Event_parse_data::init_starts(THD *thd, Item *new_starts)
 
   RETURN VALUE
     0                  OK
-    EVEX_PARSE_ERROR   fix_fields failed
-    ER_WRONG_VALUE     starts distant date (after year 2037)
-    EVEX_BAD_PARAMS    ENDS before STARTS
+    EVEX_BAD_PARAMS    Error (reported)
 */
 
 int
-Event_parse_data::init_ends(THD *thd, Item *new_ends)
+Event_parse_data::init_ends(THD *thd)
 {
   TIME ltime, ltime_now;
   my_bool not_used;
   my_time_t t;
 
   DBUG_ENTER("Event_parse_data::init_ends");
+  if (!item_ends)
+    DBUG_RETURN(0);
 
-  if (new_ends->fix_fields(thd, &new_ends))
-    DBUG_RETURN(EVEX_PARSE_ERROR);
+  if (item_ends->fix_fields(thd, &item_ends))
+    goto error_bad_params;
 
   DBUG_PRINT("info", ("convert to TIME"));
-  if ((not_used= new_ends->get_date(&ltime, TIME_NO_ZERO_DATE)))
-    DBUG_RETURN(EVEX_BAD_PARAMS);
+  if ((not_used= item_ends->get_date(&ltime, TIME_NO_ZERO_DATE)))
+    goto error_bad_params;
 
   /*
     This may result in a 1970-01-01 date if ltime is > 2037-xx-xx.
@@ -497,15 +522,12 @@ Event_parse_data::init_ends(THD *thd, Item *new_ends)
   DBUG_PRINT("info", ("get the UTC time"));
   my_tz_UTC->gmt_sec_to_TIME(&ltime,t=TIME_to_timestamp(thd, &ltime, &not_used));
   if (!t)
-  {
-    DBUG_PRINT("error", ("ENDS after year 2037"));
-    DBUG_RETURN(EVEX_BAD_PARAMS);
-  }
+    goto error_bad_params;
 
   /* Check whether ends is after starts */
   DBUG_PRINT("info", ("ENDS after STARTS?"));
   if (!starts_null && my_time_compare(&starts, &ltime) != -1)
-    DBUG_RETURN(EVEX_BAD_PARAMS);
+    goto error_bad_params;
 
   /*
     The parser forces starts to be provided but one day STARTS could be
@@ -515,11 +537,173 @@ Event_parse_data::init_ends(THD *thd, Item *new_ends)
   DBUG_PRINT("info", ("ENDS after NOW?"));
   my_tz_UTC->gmt_sec_to_TIME(&ltime_now, thd->query_start());
   if (my_time_compare(&ltime_now, &ltime) == 1)
-    DBUG_RETURN(EVEX_BAD_PARAMS);
+    goto error_bad_params;
 
   ends= ltime;
   ends_null= FALSE;
   DBUG_RETURN(0);
+
+error_bad_params:
+  my_error(ER_EVENT_ENDS_BEFORE_STARTS, MYF(0));
+  DBUG_RETURN(EVEX_BAD_PARAMS);
+}
+
+
+/*
+  Prints an error message about invalid value. Internally used
+  during input data verification
+
+  SYNOPSIS
+    Event_parse_data::report_bad_value()
+      item_name The name of the parameter
+      bad_item  The parameter
+*/
+
+void
+Event_parse_data::report_bad_value(const char *item_name, Item *bad_item)
+{
+  char buff[120];
+  String str(buff,(uint32) sizeof(buff), system_charset_info);
+  String *str2= bad_item->fixed? bad_item->val_str(&str):NULL;
+  my_error(ER_WRONG_VALUE, MYF(0), item_name, str2? str2->c_ptr_safe():"NULL");
+}
+
+
+/*
+  Performs checking of the data gathered during the parsing phase.
+
+  SYNOPSIS
+    Event_parse_data::check_parse_data()
+      thd  Thread
+
+  RETURN VALUE
+    FALSE  OK
+    TRUE   Error (reported)
+*/
+
+bool
+Event_parse_data::check_parse_data(THD *thd)
+{
+  bool ret;
+  DBUG_ENTER("Event_parse_data::check_parse_data");
+  DBUG_PRINT("info", ("execute_at=0x%lx expr=0x%lx starts=0x%lx ends=0x%lx",
+             item_execute_at, item_expression, item_starts, item_ends));
+
+  init_name(thd, identifier);
+
+  init_definer(thd);
+
+  ret= init_execute_at(thd) || init_interval(thd) || init_starts(thd) ||
+       init_ends(thd);
+  DBUG_RETURN(ret);
+}
+
+/*
+  Constructor
+
+  SYNOPSIS
+    Event_basic::Event_basic()
+*/
+
+Event_basic::Event_basic()
+{
+  DBUG_ENTER("Event_basic::Event_basic");
+  /* init memory root */
+  init_alloc_root(&mem_root, 256, 512);
+  dbname.str= name.str= NULL;
+  dbname.length= name.length= 0;
+  DBUG_VOID_RETURN;
+}
+  
+
+/*
+  Destructor
+
+  SYNOPSIS
+    Event_basic::Event_basic()
+*/
+
+Event_basic::~Event_basic()
+{
+  DBUG_ENTER("Event_basic::~Event_basic");
+  free_root(&mem_root, MYF(0));
+  DBUG_VOID_RETURN;
+}
+
+
+/*
+  Short function to load a char column into a LEX_STRING
+
+  SYNOPSIS
+    Event_basic::load_string_field()
+      field_name  The field( enum_events_table_field is not actually used
+                  because it's unknown in event_data_objects.h)
+      fields      The Field array
+      field_value The value
+*/
+
+bool
+Event_basic::load_string_fields(Field **fields, ...)
+{
+  bool ret= FALSE;
+  va_list args;
+  enum enum_events_table_field field_name;
+  LEX_STRING *field_value;
+
+  DBUG_ENTER("Event_basic::load_string_fields");
+  
+  va_start(args, fields);
+  field_name= (enum enum_events_table_field) va_arg(args, int);
+  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)
+    {
+      ret= TRUE;
+      break;
+    }
+    field_value->length= strlen(field_value->str);  
+
+    field_name= (enum enum_events_table_field) va_arg(args, int);
+  }
+  va_end(args);
+  
+  DBUG_RETURN(ret);
+}
+
+
+/*
+  Constructor
+
+  SYNOPSIS
+    Event_queue_element::Event_queue_element()
+*/
+
+Event_queue_element::Event_queue_element():
+  status_changed(FALSE), last_executed_changed(FALSE),
+  on_completion(ON_COMPLETION_DROP), status(ENABLED),
+  expression(0), dropped(FALSE), flags(0)
+{
+  DBUG_ENTER("Event_queue_element::Event_queue_element");
+
+  set_zero_time(&starts, MYSQL_TIMESTAMP_DATETIME);
+  set_zero_time(&ends, MYSQL_TIMESTAMP_DATETIME);
+  set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
+  set_zero_time(&last_executed, MYSQL_TIMESTAMP_DATETIME);
+  starts_null= ends_null= execute_at_null= TRUE;
+
+  DBUG_VOID_RETURN;
+}
+
+
+/*
+  Destructor
+
+  SYNOPSIS
+    Event_queue_element::Event_queue_element()
+*/
+Event_queue_element::~Event_queue_element()
+{
 }
 
 
@@ -530,15 +714,12 @@ Event_parse_data::init_ends(THD *thd, Item *new_ends)
     Event_timed::Event_timed()
 */
 
-Event_timed::Event_timed():status_changed(false),
-                           last_executed_changed(false), expression(0),
-                           created(0), modified(0),
-                           on_completion(Event_timed::ON_COMPLETION_DROP),
-                           status(Event_timed::ENABLED), sphead(0),
-                           sql_mode(0), dropped(false), flags(0)
-                
+Event_timed::Event_timed():
+  created(0), modified(0), sql_mode(0)
 {
+  DBUG_ENTER("Event_timed::Event_timed");
   init();
+  DBUG_VOID_RETURN;
 }
 
 
@@ -551,7 +732,31 @@ Event_timed::Event_timed():status_changed(false),
 
 Event_timed::~Event_timed()
 {    
-  free_root(&mem_root, MYF(0));
+}
+
+
+/*
+  Constructor
+
+  SYNOPSIS
+    Event_job_data::Event_job_data()
+*/
+
+Event_job_data::Event_job_data():
+  thd(NULL), sphead(0), sql_mode(0)
+{
+}
+
+
+/*
+  Destructor
+
+  SYNOPSIS
+    Event_timed::~Event_timed()
+*/
+
+Event_job_data::~Event_job_data()
+{    
   free_sp();
 }
 
@@ -568,31 +773,23 @@ Event_timed::init()
 {
   DBUG_ENTER("Event_timed::init");
 
-  dbname.str= name.str= body.str= comment.str= 0;
-  dbname.length= name.length= body.length= comment.length= 0;
-
-  set_zero_time(&starts, MYSQL_TIMESTAMP_DATETIME);
-  set_zero_time(&ends, MYSQL_TIMESTAMP_DATETIME);
-  set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
-  set_zero_time(&last_executed, MYSQL_TIMESTAMP_DATETIME);
-  starts_null= ends_null= execute_at_null= TRUE;
+  body.str= comment.str= NULL;
+  body.length= comment.length= 0;
 
   definer_user.str= definer_host.str= 0;
   definer_user.length= definer_host.length= 0;
 
   sql_mode= 0;
-  /* init memory root */
-  init_alloc_root(&mem_root, 256, 512);
 
   DBUG_VOID_RETURN;
 }
 
 
 /*
-  Loads an event from a row from mysql.event
+  Loads an event's body from a row from mysql.event
 
   SYNOPSIS
-    Event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table)
+    Event_job_data::load_from_row(MEM_ROOT *mem_root, TABLE *table)
 
   RETURN VALUE
     0                      OK
@@ -605,78 +802,127 @@ Event_timed::init()
 */
 
 int
-Event_timed::load_from_row(TABLE *table)
+Event_job_data::load_from_row(TABLE *table)
 {
   char *ptr;
-  Event_timed *et;
   uint len;
-  bool res1, res2;
-
-  DBUG_ENTER("Event_timed::load_from_row");
+  DBUG_ENTER("Event_job_data::load_from_row");
 
   if (!table)
     goto error;
 
-  et= this;
-
   if (table->s->fields != ET_FIELD_COUNT)
     goto error;
 
-  if ((et->dbname.str= get_field(&mem_root, table->field[ET_FIELD_DB])) == NULL)
-    goto error;
+  load_string_fields(table->field, ET_FIELD_DB, &dbname, ET_FIELD_NAME, &name,
+                     ET_FIELD_BODY, &body, ET_FIELD_DEFINER, &definer,
+                     ET_FIELD_COUNT);
 
-  et->dbname.length= strlen(et->dbname.str);
+/*  
+  if ((dbname.str= get_field(&mem_root, table->field[ET_FIELD_DB])) == NullS)
+    goto error;
+  dbname.length= strlen(dbname.str);
 
-  if ((et->name.str= get_field(&mem_root, table->field[ET_FIELD_NAME])) == NULL)
+  if ((name.str= get_field(&mem_root, table->field[ET_FIELD_NAME])) == NullS)
     goto error;
+  name.length= strlen(name.str);
 
-  et->name.length= strlen(et->name.str);
+  if ((body.str= get_field(&mem_root, table->field[ET_FIELD_BODY])) == NullS)
+    goto error;
+  body.length= strlen(body.str);
 
-  if ((et->body.str= get_field(&mem_root, table->field[ET_FIELD_BODY])) == NULL)
+  if ((definer.str= get_field(&mem_root,
+                              table->field[ET_FIELD_DEFINER])) == NullS)
     goto error;
 
-  et->body.length= strlen(et->body.str);
+  definer.length= strlen(definer.str);
+*/
+  ptr= strchr(definer.str, '@');
+
+  if (! ptr)
+    ptr= definer.str;
 
-  if ((et->definer.str= get_field(&mem_root,
-                                  table->field[ET_FIELD_DEFINER])) == NullS)
+  len= ptr - definer.str;
+  definer_user.str= strmake_root(&mem_root, definer.str, len);
+  definer_user.length= len;
+  len= definer.length - len - 1;
+  /* 1:because of @ */
+  definer_host.str= strmake_root(&mem_root, ptr + 1,  len);
+  definer_host.length= len;
+
+  sql_mode= (ulong) table->field[ET_FIELD_SQL_MODE]->val_int();
+
+  DBUG_RETURN(0);
+error:
+  DBUG_RETURN(EVEX_GET_FIELD_FAILED);
+}
+
+
+/*
+  Loads an event from a row from mysql.event
+
+  SYNOPSIS
+    Event_queue_element::load_from_row(MEM_ROOT *mem_root, TABLE *table)
+
+  RETURN VALUE
+    0                      OK
+    EVEX_GET_FIELD_FAILED  Error
+
+  NOTES
+    This method is silent on errors and should behave like that. Callers
+    should handle throwing of error messages. The reason is that the class
+    should not know about how to deal with communication.
+*/
+
+int
+Event_queue_element::load_from_row(TABLE *table)
+{
+  char *ptr;
+  bool res1, res2;
+
+  DBUG_ENTER("Event_queue_element::load_from_row");
+
+  if (!table)
     goto error;
-  et->definer.length= strlen(et->definer.str);
 
-  ptr= strchr(et->definer.str, '@');
+  if (table->s->fields != ET_FIELD_COUNT)
+    goto error;
 
-  if (! ptr)
-    ptr= et->definer.str;
+  load_string_fields(table->field, ET_FIELD_DB, &dbname, ET_FIELD_NAME, &name,
+                     ET_FIELD_DEFINER, &definer, ET_FIELD_COUNT);
+/*
+  if ((dbname.str= get_field(&mem_root, table->field[ET_FIELD_DB])) == NullS)
+    goto error;
+  dbname.length= strlen(dbname.str);
 
-  len= ptr - et->definer.str;
+  if ((name.str= get_field(&mem_root, table->field[ET_FIELD_NAME])) == NullS)
+    goto error;
+  name.length= strlen(name.str);
 
-  et->definer_user.str= strmake_root(&mem_root, et->definer.str, len);
-  et->definer_user.length= len;
-  len= et->definer.length - len - 1;            //1 is because of @
-  et->definer_host.str= strmake_root(&mem_root, ptr + 1, len);/* 1:because of @*/
-  et->definer_host.length= len;
-  
-  et->starts_null= table->field[ET_FIELD_STARTS]->is_null();
-  res1= table->field[ET_FIELD_STARTS]->
-                                    get_date(&et->starts,TIME_NO_ZERO_DATE);
+  if ((definer.str= get_field(&mem_root,
+                              table->field[ET_FIELD_DEFINER])) == NullS)
+    goto error;
+  definer.length= strlen(definer.str);
+*/
+  starts_null= table->field[ET_FIELD_STARTS]->is_null();
+  res1= table->field[ET_FIELD_STARTS]->get_date(&starts, TIME_NO_ZERO_DATE);
 
-  et->ends_null= table->field[ET_FIELD_ENDS]->is_null();
-  res2= table->field[ET_FIELD_ENDS]->get_date(&et->ends, TIME_NO_ZERO_DATE);
+  ends_null= table->field[ET_FIELD_ENDS]->is_null();
+  res2= table->field[ET_FIELD_ENDS]->get_date(&ends, TIME_NO_ZERO_DATE);
   
   if (!table->field[ET_FIELD_INTERVAL_EXPR]->is_null())
-    et->expression= table->field[ET_FIELD_INTERVAL_EXPR]->val_int();
+    expression= table->field[ET_FIELD_INTERVAL_EXPR]->val_int();
   else
-    et->expression= 0;
+    expression= 0;
   /*
-    If res1 and res2 are true then both fields are empty.
+    If res1 and res2 are TRUE then both fields are empty.
     Hence if ET_FIELD_EXECUTE_AT is empty there is an error.
   */
-  et->execute_at_null=
-            table->field[ET_FIELD_EXECUTE_AT]->is_null();
-  DBUG_ASSERT(!(et->starts_null && et->ends_null && !et->expression &&
-              et->execute_at_null));
-  if (!et->expression &&
-      table->field[ET_FIELD_EXECUTE_AT]-> get_date(&et->execute_at,
-                                                        TIME_NO_ZERO_DATE))
+  execute_at_null= table->field[ET_FIELD_EXECUTE_AT]->is_null();
+  DBUG_ASSERT(!(starts_null && ends_null && !expression && execute_at_null));
+  if (!expression &&
+      table->field[ET_FIELD_EXECUTE_AT]->get_date(&execute_at,
+                                                  TIME_NO_ZERO_DATE))
     goto error;
 
   /*
@@ -684,41 +930,94 @@ Event_timed::load_from_row(TABLE *table)
     from 0
   */
   if (!table->field[ET_FIELD_TRANSIENT_INTERVAL]->is_null())
-    et->interval= (interval_type) ((ulonglong)
+    interval= (interval_type) ((ulonglong)
           table->field[ET_FIELD_TRANSIENT_INTERVAL]->val_int() - 1);
   else
-    et->interval= (interval_type) 0;
+    interval= (interval_type) 0;
 
-  et->created= table->field[ET_FIELD_CREATED]->val_int();
-  et->modified= table->field[ET_FIELD_MODIFIED]->val_int();
+  table->field[ET_FIELD_LAST_EXECUTED]->get_date(&last_executed,
+                                                 TIME_NO_ZERO_DATE);
+  last_executed_changed= FALSE;
 
-  table->field[ET_FIELD_LAST_EXECUTED]->
-                     get_date(&et->last_executed, TIME_NO_ZERO_DATE);
 
-  last_executed_changed= false;
-
-  /* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */
   if ((ptr= get_field(&mem_root, table->field[ET_FIELD_STATUS])) == NullS)
     goto error;
 
-  DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", et->name.str, ptr));
-  et->status= (ptr[0]=='E'? Event_timed::ENABLED:Event_timed::DISABLED);
+  DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", name.str, ptr));
+  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,
-                  table->field[ET_FIELD_ON_COMPLETION])) == NullS)
+                      table->field[ET_FIELD_ON_COMPLETION])) == NullS)
+    goto error;
+
+  on_completion= (ptr[0]=='D'? Event_queue_element::ON_COMPLETION_DROP:
+                               Event_queue_element::ON_COMPLETION_PRESERVE);
+
+  DBUG_RETURN(0);
+error:
+  DBUG_RETURN(EVEX_GET_FIELD_FAILED);
+}
+
+
+/*
+  Loads an event from a row from mysql.event
+
+  SYNOPSIS
+    Event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table)
+
+  RETURN VALUE
+    0                      OK
+    EVEX_GET_FIELD_FAILED  Error
+
+  NOTES
+    This method is silent on errors and should behave like that. Callers
+    should handle throwing of error messages. The reason is that the class
+    should not know about how to deal with communication.
+*/
+
+int
+Event_timed::load_from_row(TABLE *table)
+{
+  char *ptr;
+  uint len;
+
+  DBUG_ENTER("Event_timed::load_from_row");
+
+  if (Event_queue_element::load_from_row(table))
     goto error;
 
-  et->on_completion= (ptr[0]=='D'? Event_timed::ON_COMPLETION_DROP:
-                                   Event_timed::ON_COMPLETION_PRESERVE);
+  load_string_fields(table->field, ET_FIELD_BODY, &body, ET_FIELD_COUNT);
+/*
+  if ((body.str= get_field(&mem_root, table->field[ET_FIELD_BODY])) == NullS)
+    goto error;
 
-  et->comment.str= get_field(&mem_root, table->field[ET_FIELD_COMMENT]);
-  if (et->comment.str != NullS)
-    et->comment.length= strlen(et->comment.str);
+  body.length= strlen(body.str);
+*/
+  ptr= strchr(definer.str, '@');
+
+  if (! ptr)
+    ptr= definer.str;
+
+  len= ptr - definer.str;
+  definer_user.str= strmake_root(&mem_root, definer.str, len);
+  definer_user.length= len;
+  len= definer.length - len - 1;
+  /* 1:because of @ */
+  definer_host.str= strmake_root(&mem_root, ptr + 1,  len);
+  definer_host.length= len;
+
+  created= table->field[ET_FIELD_CREATED]->val_int();
+  modified= table->field[ET_FIELD_MODIFIED]->val_int();
+
+  comment.str= get_field(&mem_root, table->field[ET_FIELD_COMMENT]);
+  if (comment.str != NullS)
+    comment.length= strlen(comment.str);
   else
-    et->comment.length= 0;
+    comment.length= 0;
 
-  et->sql_mode= (ulong) table->field[ET_FIELD_SQL_MODE]->val_int();
+  sql_mode= (ulong) table->field[ET_FIELD_SQL_MODE]->val_int();
 
   DBUG_RETURN(0);
 error:
@@ -872,7 +1171,7 @@ bool get_next_time(TIME *next, TIME *start, TIME *time_now, TIME *last_exec,
     tmp= *start;
     if ((ret= date_add_interval(&tmp, INTERVAL_MONTH, interval)))
       goto done;
-    
+
     /* If `tmp` is still before time_now just add one more time the interval */
     if (my_time_compare(&tmp, time_now) == -1)
     { 
@@ -896,7 +1195,7 @@ bool get_next_time(TIME *next, TIME *start, TIME *time_now, TIME *last_exec,
   Computes next execution time.
 
   SYNOPSIS
-    Event_timed::compute_next_execution_time()
+    Event_queue_element::compute_next_execution_time()
 
   RETURN VALUE
     FALSE  OK
@@ -908,18 +1207,18 @@ bool get_next_time(TIME *next, TIME *start, TIME *time_now, TIME *last_exec,
 */
 
 bool
-Event_timed::compute_next_execution_time()
+Event_queue_element::compute_next_execution_time()
 {
   TIME time_now;
   int tmp;
 
-  DBUG_ENTER("Event_timed::compute_next_execution_time");
-  DBUG_PRINT("enter", ("starts=%llu ends=%llu last_executed=%llu this=%p",
+  DBUG_ENTER("Event_queue_element::compute_next_execution_time");
+  DBUG_PRINT("enter", ("starts=%llu ends=%llu last_executed=%llu this=0x%lx",
                         TIME_to_ulonglong_datetime(&starts),
                         TIME_to_ulonglong_datetime(&ends),
                         TIME_to_ulonglong_datetime(&last_executed), this));
 
-  if (status == Event_timed::DISABLED)
+  if (status == Event_queue_element::DISABLED)
   {
     DBUG_PRINT("compute_next_execution_time",
                   ("Event %s is DISABLED", name.str));
@@ -933,11 +1232,11 @@ Event_timed::compute_next_execution_time()
     {
       DBUG_PRINT("info",("One-time event %s.%s of was already executed",
                          dbname.str, name.str, definer.str));
-      dropped= (on_completion == Event_timed::ON_COMPLETION_DROP);
+      dropped= (on_completion == Event_queue_element::ON_COMPLETION_DROP);
       DBUG_PRINT("info",("One-time event will be dropped=%d.", dropped));
 
-      status= Event_timed::DISABLED;
-      status_changed= true;
+      status= Event_queue_element::DISABLED;
+      status_changed= TRUE;
     }
     goto ret;
   }
@@ -953,11 +1252,11 @@ Event_timed::compute_next_execution_time()
     /* time_now is after ends. don't execute anymore */
     set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
     execute_at_null= TRUE;
-    if (on_completion == Event_timed::ON_COMPLETION_DROP)
-      dropped= true;
+    if (on_completion == Event_queue_element::ON_COMPLETION_DROP)
+      dropped= TRUE;
     DBUG_PRINT("info", ("Dropped=%d", dropped));
-    status= Event_timed::DISABLED;
-    status_changed= true;
+    status= Event_queue_element::DISABLED;
+    status_changed= TRUE;
 
     goto ret;
   }
@@ -1019,10 +1318,10 @@ Event_timed::compute_next_execution_time()
         /* Next execution after ends. No more executions */
         set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
         execute_at_null= TRUE;
-        if (on_completion == Event_timed::ON_COMPLETION_DROP)
-          dropped= true;
-        status= Event_timed::DISABLED;
-        status_changed= true;
+        if (on_completion == Event_queue_element::ON_COMPLETION_DROP)
+          dropped= TRUE;
+        status= Event_queue_element::DISABLED;
+        status_changed= TRUE;
       }
       else
       {
@@ -1112,10 +1411,10 @@ Event_timed::compute_next_execution_time()
           DBUG_PRINT("info", ("Next execution after ENDS. Stop executing."));
           set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
           execute_at_null= TRUE;
-          status= Event_timed::DISABLED;
-          status_changed= true;
-          if (on_completion == Event_timed::ON_COMPLETION_DROP)
-            dropped= true;
+          status= Event_queue_element::DISABLED;
+          status_changed= TRUE;
+          if (on_completion == Event_queue_element::ON_COMPLETION_DROP)
+            dropped= TRUE;
         }
         else
         {
@@ -1131,10 +1430,10 @@ Event_timed::compute_next_execution_time()
 ret:
   DBUG_PRINT("info", ("ret=0 execute_at=%llu",
              TIME_to_ulonglong_datetime(&execute_at)));
-  DBUG_RETURN(false);
+  DBUG_RETURN(FALSE);
 err:
   DBUG_PRINT("info", ("ret=1"));
-  DBUG_RETURN(true);
+  DBUG_RETURN(TRUE);
 }
 
 
@@ -1143,12 +1442,12 @@ Event_timed::compute_next_execution_time()
   time according to thd->query_start(), so the THD's clock.
 
   SYNOPSIS
-    Event_timed::drop()
+    Event_queue_element::mark_last_executed()
       thd   thread context
 */
 
 void
-Event_timed::mark_last_executed(THD *thd)
+Event_queue_element::mark_last_executed(THD *thd)
 {
   TIME time_now;
 
@@ -1156,16 +1455,15 @@ Event_timed::mark_last_executed(THD *thd)
   my_tz_UTC->gmt_sec_to_TIME(&time_now, (my_time_t) thd->query_start());
 
   last_executed= time_now; /* was execute_at */
-  last_executed_changed= true;
+  last_executed_changed= TRUE;
 }
 
 
-
 /*
   Drops the event
 
   SYNOPSIS
-    Event_timed::drop()
+    Event_queue_element::drop()
       thd   thread context
 
   RETURN VALUE
@@ -1178,13 +1476,13 @@ Event_timed::mark_last_executed(THD *thd)
 */
 
 int
-Event_timed::drop(THD *thd)
+Event_queue_element::drop(THD *thd)
 {
   uint tmp= 0;
-  DBUG_ENTER("Event_timed::drop");
+  DBUG_ENTER("Event_queue_element::drop");
 
-  DBUG_RETURN(Events::get_instance()->
-                db_repository->drop_event(thd, dbname, name, false, &tmp));
+  DBUG_RETURN(Events::get_instance()->drop_event(thd, dbname, name, FALSE,
+                                                 &tmp, TRUE));
 }
 
 
@@ -1192,12 +1490,12 @@ Event_timed::drop(THD *thd)
   Saves status and last_executed_at to the disk if changed.
 
   SYNOPSIS
-    Event_timed::update_fields()
+    Event_queue_element::update_timing_fields()
       thd - thread context
 
   RETURN VALUE
     0   OK
-    EVEX_OPEN_TABLE_FAILED    Error while opening mysql.event for writing
+    EVEX_OPEN_TABLE_FAILED  Error while opening mysql.event for writing
     EVEX_WRITE_ROW_FAILED   On error to write to disk
 
    others                   return code from SE in case deletion of the event
@@ -1205,13 +1503,13 @@ Event_timed::drop(THD *thd)
 */
 
 bool
-Event_timed::update_fields(THD *thd)
+Event_queue_element::update_timing_fields(THD *thd)
 {
   TABLE *table;
   Open_tables_state backup;
   int ret;
 
-  DBUG_ENTER("Event_timed::update_fields");
+  DBUG_ENTER("Event_queue_element::update_timing_fields");
 
   DBUG_PRINT("enter", ("name: %*s", name.length, name.str));
 
@@ -1227,8 +1525,8 @@ Event_timed::update_fields(THD *thd)
     goto done;
   }
 
-
-  if ((ret= evex_db_find_event_by_name(thd, dbname, name, table)))
+  if ((ret= Events::get_instance()->db_repository->
+                        find_event_by_name(thd, dbname, name, table)))
     goto done;
 
   store_record(table,record[1]);
@@ -1240,13 +1538,13 @@ Event_timed::update_fields(THD *thd)
     table->field[ET_FIELD_LAST_EXECUTED]->set_notnull();
     table->field[ET_FIELD_LAST_EXECUTED]->store_time(&last_executed,
                                                MYSQL_TIMESTAMP_DATETIME);
-    last_executed_changed= false;
+    last_executed_changed= FALSE;
   }
   if (status_changed)
   {
     table->field[ET_FIELD_STATUS]->set_notnull();
-    table->field[ET_FIELD_STATUS]->store((longlong)status, true);
-    status_changed= false;
+    table->field[ET_FIELD_STATUS]->store((longlong)status, TRUE);
+    status_changed= FALSE;
   }
 
   if ((table->file->ha_update_row(table->record[1],table->record[0])))
@@ -1279,8 +1577,8 @@ int
 Event_timed::get_create_event(THD *thd, String *buf)
 {
   int multipl= 0;
-  char tmp_buff[128];
-  String expr_buf(tmp_buff, sizeof(tmp_buff), system_charset_info);
+  char tmp_buf[2 * STRING_BUFFER_USUAL_SIZE];
+  String expr_buf(tmp_buf, sizeof(tmp_buf), system_charset_info);
   expr_buf.length(0);
 
   DBUG_ENTER("get_create_event");
@@ -1336,11 +1634,38 @@ Event_timed::get_create_event(THD *thd, String *buf)
 }
 
 
+/*
+  Get SHOW CREATE EVENT as string
+
+  SYNOPSIS
+    Event_job_data::get_create_event(THD *thd, String *buf)
+      thd    Thread
+      buf    String*, should be already allocated. CREATE EVENT goes inside.
+
+  RETURN VALUE
+    0                       OK
+    EVEX_MICROSECOND_UNSUP  Error (for now if mysql.event has been
+                            tampered and MICROSECONDS interval or
+                            derivative has been put there.
+*/
+
+int
+Event_job_data::get_fake_create_event(THD *thd, String *buf)
+{
+  DBUG_ENTER("Event_job_data::get_create_event");
+  buf->append(STRING_WITH_LEN("CREATE EVENT test.anonymous ON SCHEDULE "
+                              "EVERY 3337 HOUR DO "));
+  buf->append(body.str, body.length);
+
+  DBUG_RETURN(0);
+}
+
+
 /*
   Executes the event (the underlying sp_head object);
 
   SYNOPSIS
-    Event_timed::execute()
+    Event_job_data::execute()
       thd       THD
       mem_root  If != NULL use it to compile the event on it
 
@@ -1352,16 +1677,15 @@ Event_timed::get_create_event(THD *thd, String *buf)
 */
 
 int
-Event_timed::execute(THD *thd, MEM_ROOT *mem_root)
+Event_job_data::execute(THD *thd, MEM_ROOT *mem_root)
 {
   Security_context *save_ctx;
   /* this one is local and not needed after exec */
   Security_context security_ctx;
   int ret= 0;
 
-  DBUG_ENTER("Event_timed::execute");
-  DBUG_PRINT("info", ("    EVEX EXECUTING event %s.%s [EXPR:%d]",
-               dbname.str, name.str, (int) expression));
+  DBUG_ENTER("Event_job_data::execute");
+  DBUG_PRINT("info", ("EXECUTING %s.%s", dbname.str, name.str));
 
   thd->change_security_context(definer_user, definer_host, dbname,
                                &security_ctx, &save_ctx);
@@ -1406,8 +1730,7 @@ Event_timed::execute(THD *thd, MEM_ROOT *mem_root)
     delete sphead;
     sphead= 0;
   }
-  DBUG_PRINT("info", ("    EVEX EXECUTED event %s.%s  [EXPR:%d]. RetCode=%d",
-                      dbname.str, name.str, (int) expression, ret));
+  DBUG_PRINT("info", ("EXECUTED %s.%s ret=%d", dbname.str, name.str, ret));
 
   DBUG_RETURN(ret);
 }
@@ -1416,14 +1739,14 @@ Event_timed::execute(THD *thd, MEM_ROOT *mem_root)
 /*
   Frees the memory of the sp_head object we hold
   SYNOPSIS
-    Event_timed::free_sp()
+    Event_job_data::free_sp()
 */
 
 void
-Event_timed::free_sp()
+Event_job_data::free_sp()
 {
   delete sphead;
-  sphead= 0;
+  sphead= NULL;
 }
 
 
@@ -1432,7 +1755,7 @@ Event_timed::free_sp()
   sp_head object held by the event
 
   SYNOPSIS
-    Event_timed::compile()
+    Event_job_data::compile()
       thd        thread context, used for memory allocation mostly
       mem_root   if != NULL then this memory root is used for allocs
                  instead of thd->mem_root
@@ -1444,7 +1767,7 @@ Event_timed::free_sp()
 */
 
 int
-Event_timed::compile(THD *thd, MEM_ROOT *mem_root)
+Event_job_data::compile(THD *thd, MEM_ROOT *mem_root)
 {
   int ret= 0;
   MEM_ROOT *tmp_mem_root= 0;
@@ -1454,7 +1777,7 @@ Event_timed::compile(THD *thd, MEM_ROOT *mem_root)
   char *old_query;
   uint old_query_len;
   ulong old_sql_mode= thd->variables.sql_mode;
-  char create_buf[2048];
+  char create_buf[15 * STRING_BUFFER_USUAL_SIZE];
   String show_create(create_buf, sizeof(create_buf), system_charset_info);
   CHARSET_INFO *old_character_set_client,
                *old_collation_connection,
@@ -1463,11 +1786,11 @@ Event_timed::compile(THD *thd, MEM_ROOT *mem_root)
   /* this one is local and not needed after exec */
   Security_context security_ctx;
 
-  DBUG_ENTER("Event_timed::compile");
+  DBUG_ENTER("Event_job_data::compile");
 
   show_create.length(0);
 
-  switch (get_create_event(thd, &show_create)) {
+  switch (get_fake_create_event(thd, &show_create)) {
   case EVEX_MICROSECOND_UNSUP:
     sql_print_error("Scheduler");
     DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
@@ -1503,7 +1826,7 @@ Event_timed::compile(THD *thd, MEM_ROOT *mem_root)
   thd->db= dbname.str;
   thd->db_length= dbname.length;
 
-  thd->query= show_create.c_ptr();
+  thd->query= show_create.c_ptr_safe();
   thd->query_length= show_create.length();
   DBUG_PRINT("info", ("query:%s",thd->query));
 
@@ -1565,37 +1888,19 @@ Event_timed::compile(THD *thd, MEM_ROOT *mem_root)
 }
 
 
-/*
-  Checks whether two events have the same name
-
-  SYNOPSIS
-    event_timed_name_equal()
-
-  RETURN VALUE
-    TRUE  names are equal
-    FALSE names are not equal
-*/
-
-bool
-event_timed_name_equal(Event_timed *et, LEX_STRING *name)
-{
-  return !sortcmp_lex_string(et->name, *name, system_charset_info);
-}
-
-
 /*
   Checks whether two events are in the same schema
 
   SYNOPSIS
-    event_timed_db_equal()
+    event_basic_db_equal()
 
   RETURN VALUE
-    TRUE  schemas are equal
-    FALSE schemas are not equal
+    TRUE   Equal
+    FALSE  Not equal
 */
 
 bool
-event_timed_db_equal(Event_timed *et, LEX_STRING *db)
+event_basic_db_equal(LEX_STRING *db, Event_basic *et)
 {
   return !sortcmp_lex_string(et->dbname, *db, system_charset_info);
 }
@@ -1605,17 +1910,16 @@ event_timed_db_equal(Event_timed *et, LEX_STRING *db)
   Checks whether two events are equal by identifiers
 
   SYNOPSIS
-    event_timed_identifier_equal()
+    event_basic_identifier_equal()
 
   RETURN VALUE
-    TRUE   equal
-    FALSE  not equal
+    TRUE   Equal
+    FALSE  Not equal
 */
 
 bool
-event_timed_identifier_equal(LEX_STRING db, LEX_STRING name, Event_timed *b)
+event_basic_identifier_equal(LEX_STRING db, LEX_STRING name, Event_basic *b)
 {
   return !sortcmp_lex_string(name, b->name, system_charset_info) &&
          !sortcmp_lex_string(db, b->dbname, system_charset_info);
 }
-
diff --git a/sql/event_data_objects.h b/sql/event_data_objects.h
index a5aaf0e66fa..d405cafe42d 100644
--- a/sql/event_data_objects.h
+++ b/sql/event_data_objects.h
@@ -47,30 +47,46 @@
 
 class sp_head;
 class Sql_alloc;
-
-class Event_timed;
+class Event_basic;
 
 /* Compares only the schema part of the identifier */
 bool
-event_timed_db_equal(Event_timed *et, LEX_STRING *db);
+event_basic_db_equal( LEX_STRING *db, Event_basic *et);
 
 /* Compares the whole identifier*/
 bool
-event_timed_identifier_equal(LEX_STRING db, LEX_STRING name, Event_timed *b);
-
+event_basic_identifier_equal(LEX_STRING db, LEX_STRING name, Event_basic *b);
 
-class Event_timed
+class Event_basic
 {
-  Event_timed(const Event_timed &);	/* Prevent use of these */
-  void operator=(Event_timed &);
+protected:
+  MEM_ROOT mem_root;
 
+public:
+  LEX_STRING dbname;
+  LEX_STRING name;
+  LEX_STRING definer;// combination of user and host
+  
+  Event_basic();
+  virtual ~Event_basic();
+
+  virtual int
+  load_from_row(TABLE *table) = 0;
+
+protected:
+  bool
+  load_string_fields(Field **fields, ...);
+};
+
+
+
+class Event_queue_element : public Event_basic
+{
+protected:
   bool status_changed;
   bool last_executed_changed;
-  
-  MEM_ROOT mem_root;
 
 public:
-  THD *thd;
   enum enum_status
   {
     ENABLED = 1,
@@ -83,17 +99,10 @@ class Event_timed
     ON_COMPLETION_PRESERVE
   };
 
+  enum enum_on_completion on_completion;
+  enum enum_status status;
   TIME last_executed;
 
-  LEX_STRING dbname;
-  LEX_STRING name;
-  LEX_STRING body;
-
-  LEX_STRING definer_user;
-  LEX_STRING definer_host;
-  LEX_STRING definer;// combination of user and host
-
-  LEX_STRING comment;
   TIME starts;
   TIME ends;
   TIME execute_at;
@@ -104,20 +113,32 @@ class Event_timed
   longlong expression;
   interval_type interval;
 
-  ulonglong created;
-  ulonglong modified;
-  enum enum_on_completion on_completion;
-  enum enum_status status;
-  sp_head *sphead;
-  ulong sql_mode;
+  uint flags;//all kind of purposes
 
   bool dropped;
-  uint flags;//all kind of purposes
+
+  Event_queue_element();
+  virtual ~Event_queue_element();
+  
+  virtual int
+  load_from_row(TABLE *table);
+
+  bool
+  compute_next_execution_time();
+
+  int
+  drop(THD *thd);
+
+  void
+  mark_last_executed(THD *thd);
+
+  bool
+  update_timing_fields(THD *thd);
 
   static void *operator new(size_t size)
   {
     void *p;
-    DBUG_ENTER("Event_timed::new(size)");
+    DBUG_ENTER("Event_queue_element::new(size)");
     p= my_malloc(size, MYF(0));
     DBUG_PRINT("info", ("alloc_ptr=0x%lx", p));
     DBUG_RETURN(p);
@@ -125,54 +146,84 @@ class Event_timed
 
   static void operator delete(void *ptr, size_t size)
   {
-    DBUG_ENTER("Event_timed::delete(ptr,size)");
+    DBUG_ENTER("Event_queue_element::delete(ptr,size)");
     DBUG_PRINT("enter", ("free_ptr=0x%lx", ptr));
     TRASH(ptr, size);
     my_free((gptr) ptr, MYF(0));
     DBUG_VOID_RETURN;
   }
+};
 
-  Event_timed();
 
-  ~Event_timed();
+class Event_timed : public Event_queue_element
+{
+  Event_timed(const Event_timed &);	/* Prevent use of these */
+  void operator=(Event_timed &);
 
-  void
-  init();
+public:
+  LEX_STRING body;
 
-  int
-  load_from_row(TABLE *table);
+  LEX_STRING definer_user;
+  LEX_STRING definer_host;
 
-  bool
-  compute_next_execution_time();
+  LEX_STRING comment;
 
-  int
-  drop(THD *thd);
+  ulonglong created;
+  ulonglong modified;
+
+  ulong sql_mode;
+
+  Event_timed();
+  virtual ~Event_timed();
 
   void
-  mark_last_executed(THD *thd);
+  init();
 
-  bool
-  update_fields(THD *thd);
+  virtual int
+  load_from_row(TABLE *table);
 
   int
   get_create_event(THD *thd, String *buf);
+};
+
+
+class Event_job_data : public Event_basic
+{
+public:
+  THD *thd;
+  sp_head *sphead;
+
+  LEX_STRING body;
+  LEX_STRING definer_user;
+  LEX_STRING definer_host;
+
+  ulong sql_mode;
+
+  Event_job_data();
+  virtual ~Event_job_data();
+
+  virtual int
+  load_from_row(TABLE *table);
 
   int
   execute(THD *thd, MEM_ROOT *mem_root);
+private:
+  int
+  get_fake_create_event(THD *thd, String *buf);
 
   int
   compile(THD *thd, MEM_ROOT *mem_root);
-  
+
   void
   free_sp();
+
+  Event_job_data(const Event_job_data &);	/* Prevent use of these */
+  void operator=(Event_job_data &);
 };
 
 
 class Event_parse_data : public Sql_alloc
 {
-  Event_parse_data(const Event_parse_data &);	/* Prevent use of these */
-  void operator=(Event_parse_data &);
-
 public:
   enum enum_status
   {
@@ -185,7 +236,6 @@ class Event_parse_data : public Sql_alloc
     ON_COMPLETION_DROP = 1,
     ON_COMPLETION_PRESERVE
   };
-
   enum enum_on_completion on_completion;
   enum enum_status status;
 
@@ -193,8 +243,8 @@ class Event_parse_data : public Sql_alloc
 
   LEX_STRING dbname;
   LEX_STRING name;
-  LEX_STRING body;
   LEX_STRING definer;// combination of user and host
+  LEX_STRING body;
   LEX_STRING comment;
 
   Item* item_starts;
@@ -216,59 +266,41 @@ class Event_parse_data : public Sql_alloc
   static Event_parse_data *
   new_instance(THD *thd);
 
-  Event_parse_data();
-  ~Event_parse_data();
+  bool
+  check_parse_data(THD *);
 
-  int
-  init_definer(THD *thd);
+  void
+  init_body(THD *thd);
 
-  int
-  init_execute_at(THD *thd, Item *expr);
+private:
 
   int
-  init_interval(THD *thd, Item *expr, interval_type new_interval);
+  init_definer(THD *thd);
 
   void
   init_name(THD *thd, sp_name *spn);
 
   int
-  init_starts(THD *thd, Item *starts);
+  init_execute_at(THD *thd);
 
   int
-  init_ends(THD *thd, Item *ends);
-
-  void
-  init_body(THD *thd);
-};
-
-
-class Event_job_data
-{
-public:
-  LEX_STRING dbname;
-  LEX_STRING name;
-  sp_head *sphead;
-  LEX_STRING definer;
-  LEX_STRING body;
-  ulong sql_mode;
-
-  THD *thd;
-  
-  Event_job_data(){}
-  ~Event_job_data(){}
+  init_interval(THD *thd);
 
   int
-  execute();
+  init_starts(THD *thd);
 
-private:
-  int
-  load_from_disk();
-  
   int
-  compile();
+  init_ends(THD *thd);
+
+  Event_parse_data();
+  ~Event_parse_data();
 
+  void
+  report_bad_value(const char *item_name, Item *bad_item);
 
-  Event_job_data(const Event_job_data &);	/* Prevent use of these */
-  void operator=(Event_job_data &);
+  Event_parse_data(const Event_parse_data &);	/* Prevent use of these */
+  void operator=(Event_parse_data &);
 };
+
+
 #endif /* _EVENT_DATA_OBJECTS_H_ */
diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc
index a7daed113bb..22dcdd97a48 100644
--- a/sql/event_db_repository.cc
+++ b/sql/event_db_repository.cc
@@ -29,7 +29,8 @@
 time_t mysql_event_last_create_time= 0L;
 
 static
-TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] = {
+TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] =
+{
   {
     {(char *) STRING_WITH_LEN("db")},
     {(char *) STRING_WITH_LEN("char(64)")},
@@ -128,50 +129,49 @@ TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] = {
   Puts some data common to CREATE and ALTER EVENT into a row.
 
   SYNOPSIS
-    evex_fill_row()
+    mysql_event_fill_row()
       thd        THD
       table      The row to fill out
       et         Event's data
       is_update  CREATE EVENT or ALTER EVENT
 
   RETURN VALUE
-    0 - OK
-    EVEX_GENERAL_ERROR    - bad data
-    EVEX_GET_FIELD_FAILED - field count does not match. table corrupted?
+    0                       OK
+    EVEX_GENERAL_ERROR      Bad data
+    EVEX_GET_FIELD_FAILED   Field count does not match. table corrupted?
 
   DESCRIPTION 
     Used both when an event is created and when it is altered.
 */
 
 static int
-evex_fill_row(THD *thd, TABLE *table, Event_parse_data *et, my_bool is_update)
+mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et,
+                     my_bool is_update)
 {
   CHARSET_INFO *scs= system_charset_info;
-  enum enum_events_table_field field_num;
+  enum enum_events_table_field f_num;
+  Field **fields= table->field;
 
-  DBUG_ENTER("evex_fill_row");
+  DBUG_ENTER("mysql_event_fill_row");
 
   DBUG_PRINT("info", ("dbname=[%s]", et->dbname.str));
   DBUG_PRINT("info", ("name  =[%s]", et->name.str));
   DBUG_PRINT("info", ("body  =[%s]", et->body.str));
 
-  if (table->field[field_num= ET_FIELD_DEFINER]->
-                  store(et->definer.str, et->definer.length, scs))
+  if (fields[f_num= ET_FIELD_DEFINER]->
+                              store(et->definer.str, et->definer.length, scs))
     goto err_truncate;
 
-  if (table->field[field_num= ET_FIELD_DB]->
-                  store(et->dbname.str, et->dbname.length, scs))
+  if (fields[f_num= ET_FIELD_DB]->store(et->dbname.str, et->dbname.length, scs))
     goto err_truncate;
 
-  if (table->field[field_num= ET_FIELD_NAME]->
-                  store(et->name.str, et->name.length, scs))
+  if (fields[f_num= ET_FIELD_NAME]->store(et->name.str, et->name.length, scs))
     goto err_truncate;
 
   /* both ON_COMPLETION and STATUS are NOT NULL thus not calling set_notnull()*/
-  table->field[ET_FIELD_ON_COMPLETION]->
-                                       store((longlong)et->on_completion, true);
+  fields[ET_FIELD_ON_COMPLETION]->store((longlong)et->on_completion, TRUE);
 
-  table->field[ET_FIELD_STATUS]->store((longlong)et->status, true);
+  fields[ET_FIELD_STATUS]->store((longlong)et->status, TRUE);
 
   /*
     Change the SQL_MODE only if body was present in an ALTER EVENT and of course
@@ -179,52 +179,46 @@ evex_fill_row(THD *thd, TABLE *table, Event_parse_data *et, my_bool is_update)
   */ 
   if (et->body.str)
   {
-    table->field[ET_FIELD_SQL_MODE]->
-                               store((longlong)thd->variables.sql_mode, true);
-
-    if (table->field[field_num= ET_FIELD_BODY]->
-                     store(et->body.str, et->body.length, scs))
+    fields[ET_FIELD_SQL_MODE]->store((longlong)thd->variables.sql_mode, TRUE);
+    if (fields[f_num= ET_FIELD_BODY]->store(et->body.str, et->body.length, scs))
       goto err_truncate;
   }
 
   if (et->expression)
   {
-    table->field[ET_FIELD_INTERVAL_EXPR]->set_notnull();
-    table->field[ET_FIELD_INTERVAL_EXPR]->store((longlong)et->expression, true);
+    fields[ET_FIELD_INTERVAL_EXPR]->set_notnull();
+    fields[ET_FIELD_INTERVAL_EXPR]->store((longlong)et->expression, TRUE);
 
-    table->field[ET_FIELD_TRANSIENT_INTERVAL]->set_notnull();
+    fields[ET_FIELD_TRANSIENT_INTERVAL]->set_notnull();
     /*
-      In the enum (C) intervals start from 0 but in mysql enum valid values start
-      from 1. Thus +1 offset is needed!
+      In the enum (C) intervals start from 0 but in mysql enum valid values
+      start from 1. Thus +1 offset is needed!
     */
-    table->field[ET_FIELD_TRANSIENT_INTERVAL]->
-                                         store((longlong)et->interval+1, true);
+    fields[ET_FIELD_TRANSIENT_INTERVAL]->store((longlong)et->interval+1, TRUE);
 
-    table->field[ET_FIELD_EXECUTE_AT]->set_null();
+    fields[ET_FIELD_EXECUTE_AT]->set_null();
 
     if (!et->starts_null)
     {
-      table->field[ET_FIELD_STARTS]->set_notnull();
-      table->field[ET_FIELD_STARTS]->
-                            store_time(&et->starts, MYSQL_TIMESTAMP_DATETIME);
+      fields[ET_FIELD_STARTS]->set_notnull();
+      fields[ET_FIELD_STARTS]->store_time(&et->starts, MYSQL_TIMESTAMP_DATETIME);
     }
 
     if (!et->ends_null)
     {
-      table->field[ET_FIELD_ENDS]->set_notnull();
-      table->field[ET_FIELD_ENDS]->
-                            store_time(&et->ends, MYSQL_TIMESTAMP_DATETIME);
+      fields[ET_FIELD_ENDS]->set_notnull();
+      fields[ET_FIELD_ENDS]->store_time(&et->ends, MYSQL_TIMESTAMP_DATETIME);
     }
   }
   else if (et->execute_at.year)
   {
-    table->field[ET_FIELD_INTERVAL_EXPR]->set_null();
-    table->field[ET_FIELD_TRANSIENT_INTERVAL]->set_null();
-    table->field[ET_FIELD_STARTS]->set_null();
-    table->field[ET_FIELD_ENDS]->set_null();
+    fields[ET_FIELD_INTERVAL_EXPR]->set_null();
+    fields[ET_FIELD_TRANSIENT_INTERVAL]->set_null();
+    fields[ET_FIELD_STARTS]->set_null();
+    fields[ET_FIELD_ENDS]->set_null();
     
-    table->field[ET_FIELD_EXECUTE_AT]->set_notnull();
-    table->field[ET_FIELD_EXECUTE_AT]->
+    fields[ET_FIELD_EXECUTE_AT]->set_notnull();
+    fields[ET_FIELD_EXECUTE_AT]->
                         store_time(&et->execute_at, MYSQL_TIMESTAMP_DATETIME);
   }
   else
@@ -236,47 +230,23 @@ evex_fill_row(THD *thd, TABLE *table, Event_parse_data *et, my_bool is_update)
     */
   }
     
-  ((Field_timestamp *)table->field[ET_FIELD_MODIFIED])->set_time();
+  ((Field_timestamp *)fields[ET_FIELD_MODIFIED])->set_time();
 
   if (et->comment.str)
   {
-    if (table->field[field_num= ET_FIELD_COMMENT]->
-                 store(et->comment.str, et->comment.length, scs))
+    if (fields[f_num= ET_FIELD_COMMENT]->
+                          store(et->comment.str, et->comment.length, scs))
       goto err_truncate;
   }
 
   DBUG_RETURN(0);
+
 err_truncate:
-  my_error(ER_EVENT_DATA_TOO_LONG, MYF(0), table->field[field_num]->field_name);
+  my_error(ER_EVENT_DATA_TOO_LONG, MYF(0), fields[f_num]->field_name);
   DBUG_RETURN(EVEX_GENERAL_ERROR);
 }
 
 
-/*
-  Find row in open mysql.event table representing event
-
-  SYNOPSIS
-    evex_db_find_event_by_name()
-      thd    Thread context
-      dbname Name of event's database
-      rname  Name of the event inside the db  
-      table  TABLE object for open mysql.event table.
-
-  RETURN VALUE
-    0                  - Routine found
-    EVEX_KEY_NOT_FOUND - No routine with given name
-*/
-
-int
-evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
-                          const LEX_STRING ev_name,
-                          TABLE *table)
-{
-  return Events::get_instance()->db_repository->
-            find_event_by_name(thd, dbname, ev_name, table);
-}
-
-
 /*
   Performs an index scan of event_table (mysql.event) and fills schema_table.
 
@@ -313,7 +283,7 @@ Event_db_repository::index_read_for_db_for_i_s(THD *thd, TABLE *schema_table,
   if (!(key_buf= (byte *)alloc_root(thd->mem_root, key_len)))
   {
     ret= 1;
-    /* don't send error, it would be done by sql_alloc_error_handler() */
+    /* Don't send error, it would be done by sql_alloc_error_handler() */
   }
   else
   {
@@ -440,100 +410,14 @@ Event_db_repository::fill_schema_events(THD *thd, TABLE_LIST *tables, char *db)
 }
 
 
-/*
-  Looks for a named event in mysql.event and in case of success returns
-  an object will data loaded from the table.
-
-  SYNOPSIS
-    Event_db_repository::find_event()
-      thd      THD
-      name     the name of the event to find
-      ett      event's data if event is found
-      tbl      TABLE object to use when not NULL
-      root     On which root to load the event
-
-  NOTES
-    1) Use sp_name for look up, return in **ett if found
-    2) tbl is not closed at exit
-
-  RETURN VALUE
-    0  ok     In this case *ett is set to the event
-    #  error  *ett == 0
-*/
-
-int
-Event_db_repository::find_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
-                                Event_timed **ett, TABLE *tbl)
-{
-  TABLE *table;
-  int ret;
-  Event_timed *et= NULL;
-  DBUG_ENTER("Event_db_repository::find_event");
-  DBUG_PRINT("enter", ("name: %*s", name.length, name.str));
-
-  if (tbl)
-    table= tbl;
-  else if (open_event_table(thd, TL_READ, &table))
-  {
-    my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
-    ret= EVEX_GENERAL_ERROR;
-    goto done;
-  }
-
-  if ((ret= evex_db_find_event_by_name(thd, dbname, name, table)))
-  {
-    my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str);
-    goto done;
-  }
-  et= new Event_timed;
-
-  /*
-    1)The table should not be closed beforehand. ::load_from_row() only loads
-      and does not compile
-
-    2)::load_from_row() is silent on error therefore we emit error msg here
-  */
-  if ((ret= et->load_from_row(table)))
-  {
-    my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), "event");
-    goto done;
-  }
-
-done:
-  if (ret)
-  {
-    delete et;
-    et= NULL;
-  }
-  /* don't close the table if we haven't opened it ourselves */
-  if (!tbl && table)
-    close_thread_tables(thd);
-  *ett= et;
-  DBUG_RETURN(ret);
-}
-
-
-int
-Event_db_repository::init_repository()
-{
-  return 0;
-}
-
-
-void
-Event_db_repository::deinit_repository()
-{
-}
-
-
 /*
   Open mysql.event table for read
 
   SYNOPSIS
     Events::open_event_table()
-    thd         Thread context
-    lock_type   How to lock the table
-    table       We will store the open table here
+    thd         [in]  Thread context
+    lock_type   [in]  How to lock the table
+    table       [out] We will store the open table here
 
   RETURN VALUE
     1   Cannot lock table
@@ -574,33 +458,26 @@ Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type,
    Checks parameters which we got from the parsing phase.
 
    SYNOPSIS
-     evex_check_params()
+     check_parse_params()
        thd            THD
        et             event's data
   
    RETURNS
      0                OK
-     EVEX_BAD_PARAMS  Error
-  
-   REMARKS
-     Issues error messages
+     EVEX_BAD_PARAMS  Error (reported)
 */
 
-int
-evex_check_params(THD *thd, Event_parse_data *parse_data)
+static int
+check_parse_params(THD *thd, Event_parse_data *parse_data)
 {
   const char *pos= NULL;
   Item *bad_item;
+  int res;
 
-  DBUG_ENTER("evex_check_params");
-  DBUG_PRINT("info", ("execute_at=0x%d expr=0x%d starts=0x%d ends=0x%d",
-                      parse_data->item_execute_at,
-                      parse_data->item_expression,
-                      parse_data->item_starts,
-                      parse_data->item_ends));
+  DBUG_ENTER("check_parse_params");
 
-  parse_data->init_name(thd, parse_data->identifier);
-  parse_data->init_definer(thd);
+  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 &&
@@ -617,68 +494,7 @@ evex_check_params(THD *thd, Event_parse_data *parse_data)
                      is_schema_db(thd->lex->spname->m_db.str)))))
     DBUG_RETURN(EVEX_BAD_PARAMS);
 
-  if (parse_data->item_execute_at)
-  {
-    DBUG_PRINT("info", ("ONE TIME"));
-    if (parse_data->init_execute_at(thd, parse_data->item_execute_at))
-    {
-      pos= "AT";
-      bad_item= parse_data->item_execute_at;
-      goto wrong_value;
-    }
-  }
-  else
-  {
-    int res;
-    DBUG_PRINT("info", ("RECURRING"));
-
-    if (parse_data->item_expression &&
-        (res= parse_data->init_interval(thd, parse_data->item_expression,
-                                        parse_data->interval)))
-    {
-      switch (res) {
-      case EVEX_BAD_PARAMS:
-        my_error(ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG, MYF(0));
-        break;
-      case EVEX_MICROSECOND_UNSUP:
-        my_error(ER_NOT_SUPPORTED_YET, MYF(0), "MICROSECOND");
-        break;
-      default:
-        pos= "INTERVAL";
-        bad_item= parse_data->item_expression;
-        goto wrong_value;
-      }
-      DBUG_RETURN(EVEX_BAD_PARAMS);
-    }
-
-    if (parse_data->item_starts &&
-        parse_data->init_starts(thd, parse_data->item_starts))
-    {
-      pos= "STARTS";
-      bad_item= parse_data->item_starts;
-      goto wrong_value;
-    }
-
-    if (parse_data->item_ends &&
-        parse_data->init_ends(thd, parse_data->item_ends))
-    {
-      /*
-        despite the error name the value is
-        eng "ENDS is either invalid or before STARTS"
-      */
-      my_error(ER_EVENT_ENDS_BEFORE_STARTS, MYF(0));
-      DBUG_RETURN(EVEX_BAD_PARAMS);
-    }
-  }
   DBUG_RETURN(0);
-wrong_value:
-  {
-    char buff[120];
-    String str(buff,(uint32) sizeof(buff), system_charset_info);
-    String *str2= bad_item->fixed? bad_item->val_str(&str):NULL;
-    my_error(ER_WRONG_VALUE, MYF(0), pos, str2? str2->c_ptr():"NULL");
-    DBUG_RETURN(EVEX_BAD_PARAMS);
-  }
 }
 
 
@@ -687,18 +503,18 @@ evex_check_params(THD *thd, Event_parse_data *parse_data)
 
   SYNOPSIS
     Event_db_repository::create_event()
-      thd             THD
-      et              Event_timed object containing information for the event
-      create_if_not   If an warning should be generated in case event exists
-      rows_affected   How many rows were affected
+      thd             [in]  THD
+      et              [in]  Object containing info about the event
+      create_if_not   [in]  Whether to generate anwarning in case event exists
+      rows_affected   [out] How many rows were affected
 
   RETURN VALUE
                      0 - OK
     EVEX_GENERAL_ERROR - Failure
 
   DESCRIPTION 
-    Creates an event. Relies on evex_fill_row which is shared with
-    db_update_event. The name of the event is inside "et".
+    Creates an event. Relies on mysql_event_fill_row which is shared with
+    ::update_event. The name of the event is inside "et".
 */
 
 int
@@ -709,7 +525,7 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
   CHARSET_INFO *scs= system_charset_info;
   TABLE *table;
   char olddb[128];
-  bool dbchanged= false;
+  bool dbchanged= FALSE;
   DBUG_ENTER("Event_db_repository::create_event");
 
   *rows_affected= 0;
@@ -720,15 +536,14 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
     goto err;
   }
 
-  if (evex_check_params(thd, parse_data))
+  if (check_parse_params(thd, parse_data))
     goto err;
 
   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 (!evex_db_find_event_by_name(thd, parse_data->dbname,
-                                  parse_data->name, table))
+  if (!find_event_by_name(thd, parse_data->dbname, parse_data->name, table))
   {
     if (create_if_not)
     {
@@ -784,10 +599,10 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
   ((Field_timestamp *)table->field[ET_FIELD_CREATED])->set_time();
 
   /*
-    evex_fill_row() calls my_error() in case of error so no need to
+    mysql_event_fill_row() calls my_error() in case of error so no need to
     handle it here
   */
-  if ((ret= evex_fill_row(thd, table, parse_data, false)))
+  if ((ret= mysql_event_fill_row(thd, table, parse_data, FALSE)))
     goto err; 
 
   /* Close active transaction only if We are going to modify disk */
@@ -800,16 +615,6 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
     goto err;
   }
 
-#ifdef USE_THIS_CODE_AS_TEMPLATE_WHEN_EVENT_REPLICATION_IS_AGREED
-  if (mysql_bin_log.is_open())
-  {
-    thd->clear_error();
-    /* Such a statement can always go directly to binlog, no trans cache */
-    thd->binlog_query(THD::MYSQL_QUERY_TYPE, thd->query, thd->query_length,
-                      FALSE, FALSE);
-  }
-#endif
-
   *rows_affected= 1;
 ok:
   if (dbchanged)
@@ -838,7 +643,7 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
 
   RETURN VALUE
     0  OK
-    EVEX_GENERAL_ERROR  Error occured (my_error() called)
+    EVEX_GENERAL_ERROR  Error occured and reported
 
   NOTES
     sp_name is passed since this is the name of the event to
@@ -860,7 +665,7 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
     goto err;
   }
 
-  if (evex_check_params(thd, parse_data))
+  if (check_parse_params(thd, parse_data))
     goto err;
 
   DBUG_PRINT("info", ("dbname: %s", parse_data->dbname.str));
@@ -879,7 +684,7 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
       goto err;
     }
 
-    if (!evex_db_find_event_by_name(thd,new_name->m_db,new_name->m_name,table))
+    if (!find_event_by_name(thd, new_name->m_db, new_name->m_name, table))
     {
       my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), new_name->m_name.str);
       goto err;
@@ -904,10 +709,10 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
   table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
 
   /*
-    evex_fill_row() calls my_error() in case of error so no need to
+    mysql_event_fill_row() calls my_error() in case of error so no need to
     handle it here
   */
-  if ((ret= evex_fill_row(thd, table, parse_data, true)))
+  if ((ret= mysql_event_fill_row(thd, table, parse_data, TRUE)))
     goto err;
 
   if (new_name)
@@ -944,11 +749,12 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
 
   SYNOPSIS
     Event_db_repository::drop_event()
-      thd             THD
-      db              database name
-      name            event's name
-      drop_if_exists  if set and the event not existing => warning onto the stack
-      rows_affected   affected number of rows is returned heres
+      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
+      rows_affected   [out] Affected number of rows is returned heres
 
   RETURN VALUE
     0   OK
@@ -974,17 +780,16 @@ Event_db_repository::drop_event(THD *thd, LEX_STRING db, LEX_STRING name,
     goto done;
   }
 
-  if (!(ret= evex_db_find_event_by_name(thd, db, name, table)))
-  {
-    /* Close active transaction only if We are going to modify disk */
+  switch ((ret= find_event_by_name(thd, db, name, table))) {
+  case 0:
+    /* Close active transaction only if we are actually going to modify disk */
     if ((ret= end_active_trans(thd)))
-      goto done;
+      break;
 
     if ((ret= table->file->ha_delete_row(table->record[0])))
       my_error(ER_EVENT_CANNOT_DELETE, MYF(0));
-  }
-  else if (ret == EVEX_KEY_NOT_FOUND)
-  { 
+    break;
+  case EVEX_KEY_NOT_FOUND:
     if (drop_if_exists)
     {
       push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
@@ -993,19 +798,34 @@ Event_db_repository::drop_event(THD *thd, LEX_STRING db, LEX_STRING name,
       ret= 0;
     } else
       my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str);
+    break;
+  default:
+    ;
   }
 
 done:
-  /*
-    evex_drop_event() is used by Event_timed::drop therefore
-    we have to close our thread tables.
-  */
   close_thread_tables(thd);
   thd->restore_backup_open_tables_state(&backup);
   DBUG_RETURN(ret);
 }
 
 
+/*
+  Positions the internal pointer of `table` to the place where (db, name)
+  is stored.
+
+  SYNOPSIS
+    Event_db_repository::find_event_by_name()
+      thd    Thread
+      db     Schema
+      name   Event name
+      table  Opened mysql.event
+
+  RETURN VALUE
+    0                   OK
+    EVEX_KEY_NOT_FOUND  No such event
+*/
+
 int
 Event_db_repository::find_event_by_name(THD *thd, LEX_STRING db,
                                         LEX_STRING name, TABLE *table)
@@ -1043,25 +863,31 @@ Event_db_repository::find_event_by_name(THD *thd, LEX_STRING db,
 }
 
 
-int
-Event_db_repository::drop_schema_events(THD *thd, LEX_STRING schema)
-{
-  return drop_events_by_field(thd, ET_FIELD_DB, schema);
-}
+/*
+  Drops all events in the selected database, from mysql.event.
 
+  SYNOPSIS
+    Event_db_repository::drop_schema_events()
+      thd     Thread
+      schema  The database to clean from events
+
+  RETURN VALUE
+    0  OK
+   !0  Error (Reported)
+*/
 
 int
-Event_db_repository::drop_user_events(THD *thd, LEX_STRING definer)
+Event_db_repository::drop_schema_events(THD *thd, LEX_STRING schema)
 {
-  return drop_events_by_field(thd, ET_FIELD_DEFINER, definer);
+  return drop_events_by_field(thd, ET_FIELD_DB, schema);
 }
 
 
 /*
-  Drops all events in the selected database, from mysql.event.
+  Drops all events by field which has specific value of the field
 
   SYNOPSIS
-    drop_events_from_table_by_field()
+    Event_db_repository::drop_events_by_field()
       thd         Thread
       table       mysql.event TABLE
       field       Which field of the row to use for matching
@@ -1116,56 +942,63 @@ 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.
+  Looks for a named event in mysql.event and in case of success returns
+  an object will data loaded from the table.
 
   SYNOPSIS
-    Event_db_repository::load_named_event_timed()
-      thd      THD
-      etn      The name of the event to load and compile on scheduler's root
-      etn_new  The loaded event
+    Event_db_repository::find_event()
+      thd   [in]  THD
+      name  [in]  The name of the event to find
+      ett   [out] Event's data if event is found
+      tbl   [in]  TABLE object to use when not NULL
+
+  NOTES
+    1) Use sp_name for look up, return in **ett if found
+    2) tbl is not closed at exit
 
   RETURN VALUE
-    NULL       Error during compile or the event is non-enabled.
-    otherwise  Address
+    0  ok     In this case *ett is set to the event
+    #  error  *ett == 0
 */
 
 int
-Event_db_repository::load_named_event_timed(THD *thd, LEX_STRING dbname,
-                                            LEX_STRING name,
-                                            Event_timed **etn_new)
+Event_db_repository::find_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
+                                Event_basic *et)
 {
-  int ret= 0;
-  MEM_ROOT *tmp_mem_root;
-  Event_timed *et_loaded= NULL;
-  Open_tables_state backup;
+  TABLE *table;
+  int ret;
+  DBUG_ENTER("Event_db_repository::find_event");
+  DBUG_PRINT("enter", ("name: %*s", name.length, name.str));
 
-  DBUG_ENTER("Event_db_repository::load_named_event_timed");
-  DBUG_PRINT("enter",("thd=%p name:%*s",thd, name.length, name.str));
+  if (open_event_table(thd, TL_READ, &table))
+  {
+    my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
+    ret= EVEX_GENERAL_ERROR;
+    goto done;
+  }
 
-  thd->reset_n_backup_open_tables_state(&backup);
-  /* No need to use my_error() here because db_find_event() has done it */
-  ret= find_event(thd, dbname, name, &et_loaded, NULL);
-  thd->restore_backup_open_tables_state(&backup);
-  /* In this case no memory was allocated so we don't need to clean */
-  if (ret)
-    DBUG_RETURN(OP_LOAD_ERROR);
+  if ((ret= find_event_by_name(thd, dbname, name, table)))
+  {
+    my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str);
+    goto done;
+  }
+  /*
+    1)The table should not be closed beforehand. ::load_from_row() only loads
+      and does not compile
 
-  if (et_loaded->status != Event_timed::ENABLED)
+    2)::load_from_row() is silent on error therefore we emit error msg here
+  */
+  if ((ret= et->load_from_row(table)))
   {
-    /*
-      We don't load non-enabled events.
-      In db_find_event() `et_new` was allocated on the heap and not on
-      scheduler_root therefore we delete it here.
-    */
-    delete et_loaded;
-    DBUG_RETURN(OP_DISABLED_EVENT);
+    my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), "event");
+    goto done;
   }
 
-  et_loaded->compute_next_execution_time();
-  *etn_new= et_loaded;
+done:
+  if (table)
+    close_thread_tables(thd);
 
-  DBUG_RETURN(OP_OK);
+  DBUG_RETURN(ret);
 }
 
 
@@ -1174,50 +1007,34 @@ Event_db_repository::load_named_event_timed(THD *thd, LEX_STRING dbname,
   the table, compiles and inserts it into the cache.
 
   SYNOPSIS
-    Event_db_repository::load_named_event_job()
-      thd      THD
-      etn      The name of the event to load and compile on scheduler's root
-      etn_new  The loaded event
+    Event_db_repository::load_named_event()
+      thd      [in]  THD
+      dbname   [in]  Event's db name
+      name     [in]  Event's name
+      etn_new  [out] The loaded event
 
   RETURN VALUE
-    NULL       Error during compile or the event is non-enabled.
-    otherwise  Address
+    OP_OK          OK
+    OP_LOAD_ERROR  Error during loading from disk
 */
 
 int
-Event_db_repository::load_named_event_job(THD *thd, LEX_STRING dbname,
-                                          LEX_STRING name,
-                                          Event_job_data **etn_new)
+Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname,
+                                      LEX_STRING name, Event_basic *etn)
 {
   int ret= 0;
-  MEM_ROOT *tmp_mem_root;
-  Event_timed *et_loaded= NULL;
   Open_tables_state backup;
 
-  DBUG_ENTER("Event_db_repository::load_named_event_job");
-  DBUG_PRINT("enter",("thd=%p name:%*s",thd, name.length, name.str));
-#if 0
+  DBUG_ENTER("Event_db_repository::load_named_event");
+  DBUG_PRINT("enter",("thd=0x%lx name:%*s",thd, name.length, name.str));
+
   thd->reset_n_backup_open_tables_state(&backup);
-  /* No need to use my_error() here because db_find_event() has done it */
-  ret= find_event(thd, dbname, name, &et_loaded, NULL);
+  /* No need to use my_error() here because find_event() has done it */
+  ret= find_event(thd, dbname, name, etn);
   thd->restore_backup_open_tables_state(&backup);
   /* In this case no memory was allocated so we don't need to clean */
   if (ret)
     DBUG_RETURN(OP_LOAD_ERROR);
 
-  if (et_loaded->status != Event_timed::ENABLED)
-  {
-    /*
-      We don't load non-enabled events.
-      In db_find_event() `et_new` was allocated on the heap and not on
-      scheduler_root therefore we delete it here.
-    */
-    delete et_loaded;
-    DBUG_RETURN(OP_DISABLED_EVENT);
-  }
-
-  et_loaded->compute_next_execution_time();
-  *etn_new= et_loaded;
-#endif
   DBUG_RETURN(OP_OK);
 }
diff --git a/sql/event_db_repository.h b/sql/event_db_repository.h
index c000247cff2..d13538ce10b 100644
--- a/sql/event_db_repository.h
+++ b/sql/event_db_repository.h
@@ -38,11 +38,6 @@ enum enum_events_table_field
 };
 
 
-int
-evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
-                           const LEX_STRING ev_name,
-                           TABLE *table);
-
 int
 events_table_index_read_for_db(THD *thd, TABLE *schema_table,
                                TABLE *event_table);
@@ -53,22 +48,13 @@ events_table_scan_all(THD *thd, TABLE *schema_table, TABLE *event_table);
 int
 fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */);
 
-class Event_timed;
+class Event_basic;
 class Event_parse_data;
-class Event_queue_element;
-class Event_job_data;
 
 class Event_db_repository
 {
 public:
   Event_db_repository(){}
-  ~Event_db_repository(){}
-
-  int
-  init_repository();
-
-  void
-  deinit_repository();
 
   int
   create_event(THD *thd, Event_parse_data *parse_data, my_bool create_if_not,
@@ -85,19 +71,10 @@ class Event_db_repository
   drop_schema_events(THD *thd, LEX_STRING schema);
 
   int
-  drop_user_events(THD *thd, LEX_STRING definer);
-
-  int
-  find_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_timed **ett,
-             TABLE *tbl);
-
-  int
-  load_named_event_timed(THD *thd, LEX_STRING dbname, LEX_STRING name,
-                         Event_timed **etn_new);
+  find_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_basic *et);
 
   int
-  load_named_event_job(THD *thd, LEX_STRING dbname, LEX_STRING name,
-                       Event_job_data **etn_new);
+  load_named_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_basic *et);
 
   int
   find_event_by_name(THD *thd, LEX_STRING db, LEX_STRING name, TABLE *table);
diff --git a/sql/event_queue.cc b/sql/event_queue.cc
index b42372ba6bd..bd8809ba708 100644
--- a/sql/event_queue.cc
+++ b/sql/event_queue.cc
@@ -36,16 +36,16 @@
 
 
 /*
-  Compares the execute_at members of 2 Event_timed instances.
+  Compares the execute_at members of 2 Event_queue_element instances.
   Used as callback for the prioritized queue when shifting
   elements inside.
 
   SYNOPSIS
-    event_timed_compare_q()
+    event_queue_element_data_compare_q()
   
       vptr - not used (set it to NULL)
-      a    - first Event_timed object
-      b    - second Event_timed object
+      a    - first Event_queue_element object
+      b    - second Event_queue_element object
 
   RETURN VALUE
    -1   - a->execute_at < b->execute_at
@@ -57,14 +57,13 @@
 */
 
 static int 
-event_timed_compare_q(void *vptr, byte* a, byte *b)
+event_queue_element_compare_q(void *vptr, byte* a, byte *b)
 {
-  return my_time_compare(&((Event_timed *)a)->execute_at,
-                         &((Event_timed *)b)->execute_at);
+  return my_time_compare(&((Event_queue_element *)a)->execute_at,
+                         &((Event_queue_element *)b)->execute_at);
 }
 
 
-
 /*
   Constructor of class Event_queue.
 
@@ -79,6 +78,120 @@ Event_queue::Event_queue()
   mutex_queue_data_locked= FALSE;
 }
 
+
+/*
+  Inits mutexes.
+
+  SYNOPSIS
+    Event_queue::init_mutexes()
+*/
+
+void
+Event_queue::init_mutexes()
+{
+  pthread_mutex_init(&LOCK_event_queue, MY_MUTEX_INIT_FAST);
+}
+
+
+/*
+  Destroys mutexes.
+
+  SYNOPSIS
+    Event_queue::deinit_mutexes()
+*/
+
+void
+Event_queue::deinit_mutexes()
+{
+  pthread_mutex_destroy(&LOCK_event_queue);
+}
+
+
+/*
+  Signals the main scheduler thread that the queue has changed
+  its state.
+
+  SYNOPSIS
+    Event_queue::notify_observers()
+*/
+
+void
+Event_queue::notify_observers()
+{
+  DBUG_ENTER("Event_queue::notify_observers");
+  DBUG_PRINT("info", ("Signalling change of the queue"));
+  scheduler->queue_changed();
+  DBUG_VOID_RETURN;
+}
+
+
+/*
+  Inits the queue
+
+  SYNOPSIS
+    Event_queue::init()
+
+  RETURN VALUE
+    FALSE  OK
+    TRUE   Error
+*/
+
+bool
+Event_queue::init_queue(Event_db_repository *db_repo, Event_scheduler_ng *sched)
+{
+  int i= 0;
+  bool ret= FALSE;
+  DBUG_ENTER("Event_queue::init_queue");
+  DBUG_PRINT("enter", ("this=0x%lx", this));
+
+  LOCK_QUEUE_DATA();
+  db_repository= db_repo;
+  scheduler= sched;
+
+  if (init_queue_ex(&queue, 30 /*num_el*/, 0 /*offset*/, 0 /*smallest_on_top*/,
+                    event_queue_element_compare_q, NULL, 30 /*auto_extent*/))
+  {
+    sql_print_error("SCHEDULER: Can't initialize the execution queue");
+    ret= TRUE;
+    goto end;
+  }
+
+  if (sizeof(my_time_t) != sizeof(time_t))
+  {
+    sql_print_error("SCHEDULER: sizeof(my_time_t) != sizeof(time_t) ."
+                    "The scheduler may not work correctly. Stopping.");
+    DBUG_ASSERT(0);
+    ret= TRUE;
+    goto end;
+  }
+
+end:
+  UNLOCK_QUEUE_DATA();
+  DBUG_RETURN(ret);
+}
+
+
+/*
+  Deinits the queue
+
+  SYNOPSIS
+    Event_queue::deinit_queue()
+*/
+
+void
+Event_queue::deinit_queue()
+{
+  DBUG_ENTER("Event_queue::deinit_queue");
+
+  LOCK_QUEUE_DATA();
+  empty_queue();
+  delete_queue(&queue);
+  UNLOCK_QUEUE_DATA();
+
+  DBUG_VOID_RETURN;
+}
+
+
 /*
   Creates an event in the scheduler queue
 
@@ -90,28 +203,31 @@ Event_queue::Event_queue()
   RETURN VALUE
     OP_OK             OK or scheduler not working
     OP_LOAD_ERROR     Error during loading from disk
-    OP_ALREADY_EXISTS Event already in the queue    
 */
 
 int
-Event_queue::create_event(THD *thd, Event_parse_data *et)
+Event_queue::create_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
 {
   int res;
-  Event_timed *et_new;
+  Event_queue_element *element_new;
   DBUG_ENTER("Event_queue::create_event");
-  DBUG_PRINT("enter", ("thd=%p et=%p lock=%p",thd,et, &LOCK_event_queue));
+  DBUG_PRINT("enter", ("thd=0x%lx et=%s.%s",thd, dbname.str, name.str));
 
-  res= db_repository->load_named_event_timed(thd, et->dbname, et->name, &et_new);
-  LOCK_QUEUE_DATA();
-  if (!res)
+  element_new= new Event_queue_element();
+  res= db_repository->load_named_event(thd, dbname, name, element_new);
+  if (res || element_new->status == Event_queue_element::DISABLED)
+    delete element_new;
+  else
   {
-    DBUG_PRINT("info", ("new event in the queue %p", et_new));
-    queue_insert_safe(&queue, (byte *) et_new);
+    element_new->compute_next_execution_time();
+
+    LOCK_QUEUE_DATA();
+    DBUG_PRINT("info", ("new event in the queue 0x%lx", element_new));
+    queue_insert_safe(&queue, (byte *) element_new);
+    UNLOCK_QUEUE_DATA();
+
     notify_observers();
   }
-  else if (res == OP_DISABLED_EVENT)
-    res= OP_OK;
-  UNLOCK_QUEUE_DATA();
 
   DBUG_RETURN(res);
 }
@@ -123,9 +239,10 @@ Event_queue::create_event(THD *thd, Event_parse_data *et)
   SYNOPSIS
     Event_queue::update_event()
       thd        Thread
-      et         The event to replace(add) into the queue
-      new_schema New schema, in case of RENAME TO
-      new_name   New name, in case of RENAME TO
+      dbname     Schema of the event
+      name       Name of the event
+      new_schema New schema, in case of RENAME TO, otherwise NULL
+      new_name   New name, in case of RENAME TO, otherwise NULL
 
   RETURN VALUE
     OP_OK             OK or scheduler not working
@@ -133,43 +250,57 @@ Event_queue::create_event(THD *thd, Event_parse_data *et)
 */
 
 int
-Event_queue::update_event(THD *thd, Event_parse_data *et,
+Event_queue::update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
                           LEX_STRING *new_schema, LEX_STRING *new_name)
 {
   int res;
-  Event_timed *et_old= NULL, *et_new= NULL;
+  Event_queue_element *element_old= NULL,
+                      *element_new;
 
   DBUG_ENTER("Event_queue::update_event");
-  DBUG_PRINT("enter", ("thd=%p et=%p et=[%s.%s] lock=%p",
-             thd, et, et->dbname.str, et->name.str, &LOCK_event_queue));
+  DBUG_PRINT("enter", ("thd=0x%lx et=[%s.%s]", thd, dbname.str, name.str));
 
-  res= db_repository->
-            load_named_event_timed(thd, new_schema?*new_schema:et->dbname,
-                                   new_name? *new_name:et->name, &et_new);
+  element_new= new Event_queue_element();
 
-  if (res && res != OP_DISABLED_EVENT)
+  res= db_repository->load_named_event(thd, new_schema? *new_schema:dbname,
+                                       new_name? *new_name:name, element_new);
+  if (res)
+  {
+    delete element_new;
     goto end;
+  }
+  else if (element_new->status == Event_queue_element::DISABLED)
+  {
+    DBUG_PRINT("info", ("The event is disabled."));
+    /*
+      Destroy the object but don't skip to end: because we may have to remove
+      object from the cache.
+    */
+    delete element_new;
+    element_new= NULL;
+  }
+  else
+    element_new->compute_next_execution_time();
 
   LOCK_QUEUE_DATA();
-  if (!(et_old= find_event(et->dbname, et->name, TRUE)))
+  if (!(element_old= find_event(dbname, name, TRUE)))
   {
-    DBUG_PRINT("info", ("%s.%s not found cached, probably was DISABLED",
-                        et->dbname.str, et->name.str));
+    DBUG_PRINT("info", ("%s.%s not cached, probably was DISABLED",
+                        dbname.str, name.str));
   }
-
-  if (!res)
+  /* If not disabled event */
+  if (element_new)
   {
-    DBUG_PRINT("info", ("new event in the queue %p old %p", et_new, et_old));
-    queue_insert_safe(&queue, (byte *) et_new);
+    DBUG_PRINT("info", ("new event in the Q 0x%lx old 0x%lx",
+                        element_new, element_old));
+    queue_insert_safe(&queue, (byte *) element_new);
   }
-  else if (res == OP_DISABLED_EVENT)
-    res= OP_OK;
   UNLOCK_QUEUE_DATA();
 
   notify_observers();
 
-  if (et_old)
-    delete et_old;
+  if (element_old)
+    delete element_old;
 end:
   DBUG_PRINT("info", ("res=%d", res));
   DBUG_RETURN(res);
@@ -181,35 +312,34 @@ Event_queue::update_event(THD *thd, Event_parse_data *et,
 
   SYNOPSIS
     Event_queue::drop_event()
-      thd    Thread
-      name   The event to drop
-
-  RETURN VALUE
-    FALSE OK (replaced or scheduler not working)
-    TRUE  Failure
+      thd     Thread
+      dbname  Schema of the event to drop
+      name    Name of the event to drop
 */
 
-bool
-Event_queue::drop_event(THD *thd, sp_name *name)
+void
+Event_queue::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
 {
   int res;
-  Event_timed *et_old;
+  Event_queue_element *element;
   DBUG_ENTER("Event_queue::drop_event");
-  DBUG_PRINT("enter", ("thd=%p name=%p lock=%p", thd, name,
-             &LOCK_event_queue));
+  DBUG_PRINT("enter", ("thd=0x%lx name=0x%lx", thd, name));
 
   LOCK_QUEUE_DATA();
-  if (!(et_old= find_event(name->m_db, name->m_name, TRUE)))
-    DBUG_PRINT("info", ("No such event found, probably DISABLED"));
+  element= find_event(dbname, name, TRUE);
   UNLOCK_QUEUE_DATA();
-  if (et_old)
-    delete et_old;
+
+  if (element)
+    delete element;
+  else
+    DBUG_PRINT("info", ("No such event found, probably DISABLED"));
+  
   /*
     We don't signal here because the scheduler will catch the change
     next time it wakes up.
   */
 
-  DBUG_RETURN(FALSE);
+  DBUG_VOID_RETURN;
 }
 
 
@@ -232,7 +362,7 @@ Event_queue::drop_event(THD *thd, sp_name *name)
     (signalling COND_new_work for instance).
 */
 
-Event_timed *
+Event_queue_element *
 Event_queue::find_event(LEX_STRING db, LEX_STRING name, bool remove_from_q)
 {
   uint i;
@@ -240,10 +370,10 @@ Event_queue::find_event(LEX_STRING db, LEX_STRING name, bool remove_from_q)
 
   for (i= 0; i < queue.elements; ++i)
   {
-    Event_timed *et= (Event_timed *) queue_element(&queue, i);
+    Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i);
     DBUG_PRINT("info", ("[%s.%s]==[%s.%s]?", db.str, name.str,
                         et->dbname.str, et->name.str));
-    if (event_timed_identifier_equal(db, name, et))
+    if (event_basic_identifier_equal(db, name, et))
     {
       if (remove_from_q)
         queue_remove(&queue, i);
@@ -274,7 +404,7 @@ Event_queue::find_event(LEX_STRING db, LEX_STRING name, bool remove_from_q)
 
 void
 Event_queue::drop_matching_events(THD *thd, LEX_STRING pattern,
-                           bool (*comparator)(Event_timed *,LEX_STRING *))
+                           bool (*comparator)(LEX_STRING *, Event_basic *))
 {
   DBUG_ENTER("Event_queue::drop_matching_events");
   DBUG_PRINT("enter", ("pattern=%*s state=%d", pattern.length, pattern.str));
@@ -282,9 +412,9 @@ Event_queue::drop_matching_events(THD *thd, LEX_STRING pattern,
   uint i= 0;   
   while (i < queue.elements)
   {
-    Event_timed *et= (Event_timed *) queue_element(&queue, i);
+    Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i);
     DBUG_PRINT("info", ("[%s.%s]?", et->dbname.str, et->name.str));
-    if (comparator(et, &pattern))
+    if (comparator(&pattern, et))
     {
       /*
         The queue is ordered. If we remove an element, then all elements after
@@ -331,59 +461,12 @@ Event_queue::drop_schema_events(THD *thd, LEX_STRING schema)
 {
   DBUG_ENTER("Event_queue::drop_schema_events");
   LOCK_QUEUE_DATA();
-  drop_matching_events(thd, schema, event_timed_db_equal);
+  drop_matching_events(thd, schema, event_basic_db_equal);
   UNLOCK_QUEUE_DATA();
   DBUG_VOID_RETURN;
 }
 
 
-/*
-  Wrapper for pthread_mutex_lock
-
-  SYNOPSIS
-    Event_queue::lock_data()
-      mutex Mutex to lock
-      line  The line number on which the lock is done
-
-  RETURN VALUE
-    Error code of pthread_mutex_lock()
-*/
-
-void
-Event_queue::lock_data(const char *func, uint line)
-{
-  DBUG_ENTER("Event_queue::lock_mutex");
-  DBUG_PRINT("enter", ("func=%s line=%u", func, line));
-  pthread_mutex_lock(&LOCK_event_queue);
-  mutex_last_locked_in_func= func;
-  mutex_last_locked_at_line= line;
-  mutex_queue_data_locked= TRUE;
-  DBUG_VOID_RETURN;
-}
-
-
-/*
-  Wrapper for pthread_mutex_unlock
-
-  SYNOPSIS
-    Event_queue::unlock_data()
-      mutex Mutex to unlock
-      line  The line number on which the unlock is done
-*/
-
-void
-Event_queue::unlock_data(const char *func, uint line)
-{
-  DBUG_ENTER("Event_queue::unlock_mutex");
-  DBUG_PRINT("enter", ("func=%s line=%u", func, line));
-  mutex_last_unlocked_at_line= line;
-  mutex_queue_data_locked= FALSE;
-  mutex_last_unlocked_in_func= func;
-  pthread_mutex_unlock(&LOCK_event_queue);
-  DBUG_VOID_RETURN;
-}
-
-
 /*
   Returns the number of elements in the queue
 
@@ -391,7 +474,7 @@ Event_queue::unlock_data(const char *func, uint line)
     Event_queue::events_count()
 
   RETURN VALUE
-    0  Number of Event_timed objects in the queue
+    Number of Event_queue_element objects in the queue
 */
 
 uint
@@ -407,32 +490,10 @@ Event_queue::events_count()
 }
 
 
-/*
-  Returns the number of elements in the queue
-
-  SYNOPSIS
-    Event_queue::events_count_no_lock()
-
-  RETURN VALUE
-    0  Number of Event_timed objects in the queue
-*/
-
-uint
-Event_queue::events_count_no_lock()
-{
-  uint n;
-  DBUG_ENTER("Event_queue::events_count_no_lock");
-
-  n= queue.elements;
-
-  DBUG_RETURN(n);
-}
-
-
 /*
   Loads all ENABLED events from mysql.event into the prioritized
   queue. Called during scheduler main thread initialization. Compiles
-  the events. Creates Event_timed instances for every ENABLED event
+  the events. Creates Event_queue_element instances for every ENABLED event
   from mysql.event.
 
   SYNOPSIS
@@ -461,7 +522,7 @@ Event_queue::load_events_from_db(THD *thd)
   MEM_ROOT boot_root;
 
   DBUG_ENTER("Event_queue::load_events_from_db");
-  DBUG_PRINT("enter", ("thd=%p", thd));
+  DBUG_PRINT("enter", ("thd=0x%lx", thd));
 
   if ((ret= db_repository->open_event_table(thd, TL_READ, &table)))
   {
@@ -469,12 +530,11 @@ Event_queue::load_events_from_db(THD *thd)
     DBUG_RETURN(EVEX_OPEN_TABLE_FAILED);
   }
 
-  init_alloc_root(&boot_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
   init_read_record(&read_record_info, thd, table ,NULL,1,0);
   while (!(read_record_info.read_record(&read_record_info)))
   {
-    Event_timed *et;
-    if (!(et= new Event_timed))
+    Event_queue_element *et;
+    if (!(et= new Event_queue_element))
     {
       DBUG_PRINT("info", ("Out of memory"));
       clean_the_queue= TRUE;
@@ -489,13 +549,14 @@ Event_queue::load_events_from_db(THD *thd)
                       "Table probably corrupted");
       break;
     }
-    if (et->status != Event_timed::ENABLED)
+    if (et->status != Event_queue_element::ENABLED)
     {
       DBUG_PRINT("info",("%s is disabled",et->name.str));
       delete et;
       continue;
     }
-
+#if 0
+    init_alloc_root(&boot_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
     DBUG_PRINT("info", ("Event %s loaded from row. ", et->name.str));
 
     /* We load only on scheduler root just to check whether the body compiles */
@@ -514,6 +575,7 @@ Event_queue::load_events_from_db(THD *thd)
       et->free_sp();
       break;
     }
+    free_root(&boot_root, MYF(0));
 
     /* let's find when to be executed */
     if (et->compute_next_execution_time())
@@ -522,19 +584,17 @@ Event_queue::load_events_from_db(THD *thd)
                       " Skipping", et->dbname.str, et->name.str);
       continue;
     }
-
-    DBUG_PRINT("load_events_from_db", ("Adding %p to the exec list."));
+#endif
+    DBUG_PRINT("load_events_from_db", ("Adding 0x%lx to the exec list."));
     queue_insert_safe(&queue,  (byte *) et);
     count++;
   }
 end:
   end_read_record(&read_record_info);
-  free_root(&boot_root, MYF(0));
 
   if (clean_the_queue)
   {
-    for (count= 0; count < queue.elements; ++count)
-      queue_remove(&queue, 0);
+    empty_queue();
     ret= -1;
   }
   else
@@ -571,7 +631,7 @@ Event_queue::check_system_tables(THD *thd)
   bool ret;
 
   DBUG_ENTER("Event_queue::check_system_tables");
-  DBUG_PRINT("enter", ("thd=%p", thd));
+  DBUG_PRINT("enter", ("thd=0x%lx", thd));
 
   thd->reset_n_backup_open_tables_state(&backup);
 
@@ -618,123 +678,48 @@ Event_queue::check_system_tables(THD *thd)
 
 
 /*
-  Inits mutexes.
-
-  SYNOPSIS
-    Event_queue::init_mutexes()
-*/
-
-void
-Event_queue::init_mutexes()
-{
-  pthread_mutex_init(&LOCK_event_queue, MY_MUTEX_INIT_FAST);
-}
-
-
-/*
-  Destroys mutexes.
+  Recalculates activation times in the queue. There is one reason for
+  that. Because the values (execute_at) by which the queue is ordered are
+  changed by calls to compute_next_execution_time() on a request from the
+  scheduler thread, if it is not running then the values won't be updated.
+  Once the scheduler is started again the values has to be recalculated
+  so they are right for the current time.
 
   SYNOPSIS
-    Event_queue::deinit_mutexes()
+    Event_queue::recalculate_activation_times()
+      thd  Thread
 */
 
 void
-Event_queue::deinit_mutexes()
+Event_queue::recalculate_activation_times(THD *thd)
 {
-  pthread_mutex_destroy(&LOCK_event_queue);
-}
-
-
-/*
-  Signals the main scheduler thread that the queue has changed
-  its state.
-
-  SYNOPSIS
-    Event_queue::notify_observers()
-*/
-
-void
-Event_queue::notify_observers()
-{
-  DBUG_ENTER("Event_queue::notify_observers");
-  DBUG_PRINT("info", ("Signalling change of the queue"));
-  scheduler->queue_changed();
-  DBUG_VOID_RETURN;
-}
-
-
-/*
-  The implementation of full-fledged initialization.
-
-  SYNOPSIS
-    Event_queue::init()
-
-  RETURN VALUE
-    FALSE  OK
-    TRUE   Error
-*/
-
-bool
-Event_queue::init_queue(Event_db_repository *db_repo, Event_scheduler_ng *sched)
-{
-  int i= 0;
-  bool ret= FALSE;
-  DBUG_ENTER("Event_queue::init_queue");
-  DBUG_PRINT("enter", ("this=%p", this));
+  uint i;
+  DBUG_ENTER("Event_queue::recalculate_activation_times");
 
   LOCK_QUEUE_DATA();
-  db_repository= db_repo;
-  scheduler= sched;
-
-  if (init_queue_ex(&queue, 30 /*num_el*/, 0 /*offset*/, 0 /*smallest_on_top*/,
-                    event_timed_compare_q, NULL, 30 /*auto_extent*/))
-  {
-    sql_print_error("SCHEDULER: Can't initialize the execution queue");
-    ret= TRUE;
-    goto end;
-  }
-
-  if (sizeof(my_time_t) != sizeof(time_t))
+  DBUG_PRINT("info", ("%u loaded events to be recalculated", queue.elements));
+  for (i= 0; i < queue.elements; i++)
   {
-    sql_print_error("SCHEDULER: sizeof(my_time_t) != sizeof(time_t) ."
-                    "The scheduler may not work correctly. Stopping.");
-    DBUG_ASSERT(0);
-    ret= TRUE;
-    goto end;
+    ((Event_queue_element*)queue_element(&queue, i))->compute_next_execution_time();
+    ((Event_queue_element*)queue_element(&queue, i))->update_timing_fields(thd);
   }
-
-end:
-  UNLOCK_QUEUE_DATA();
-  DBUG_RETURN(ret);
-}
-
-
-void
-Event_queue::deinit_queue()
-{
-  DBUG_ENTER("Event_queue::deinit_queue");
-
-  LOCK_QUEUE_DATA();
-  empty_queue();
-  delete_queue(&queue);
+  queue_fix(&queue);
   UNLOCK_QUEUE_DATA();
 
   DBUG_VOID_RETURN;
 }
 
 
-void
-Event_queue::recalculate_queue(THD *thd)
-{
-  uint i;
-  for (i= 0; i < queue.elements; i++)
-  {
-    ((Event_timed*)queue_element(&queue, i))->compute_next_execution_time();
-    ((Event_timed*)queue_element(&queue, i))->update_fields(thd);
-  }
-  queue_fix(&queue);
-}
+/*
+  Empties the queue and destroys the Event_queue_element objects in the
+  queue.
 
+  SYNOPSIS
+    Event_queue::empty_queue()
+
+  NOTE
+    Should be called with LOCK_event_queue locked  
+*/
 
 void
 Event_queue::empty_queue()
@@ -743,9 +728,9 @@ Event_queue::empty_queue()
   DBUG_ENTER("Event_queue::empty_queue");
   DBUG_PRINT("enter", ("Purging the queue. %d element(s)", queue.elements));
   /* empty the queue */
-  for (i= 0; i < events_count_no_lock(); ++i)
+  for (i= 0; i < queue.elements; ++i)
   {
-    Event_timed *et= (Event_timed *) queue_element(&queue, i);
+    Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i);
     delete et;
   }
   resize_queue(&queue, 0);
@@ -753,38 +738,17 @@ Event_queue::empty_queue()
 }
 
 
-Event_timed*
-Event_queue::get_top()
-{
-  return (Event_timed *)queue_top(&queue); 
-}
-
-
-void
-Event_queue::remove_top()
-{
-  queue_remove(&queue, 0);// 0 is top, internally 1
-}
-
-
-void
-Event_queue::top_changed()
-{
-  queue_replaced(&queue);
-}
-
-
 inline void
 Event_queue::dbug_dump_queue(time_t now)
 {
 #ifndef DBUG_OFF
-  Event_timed *et;
+  Event_queue_element *et;
   uint i;
   DBUG_PRINT("info", ("Dumping queue . Elements=%u", queue.elements));
   for (i = 0; i < queue.elements; i++)
   {
-    et= ((Event_timed*)queue_element(&queue, i));
-    DBUG_PRINT("info",("et=%p db=%s name=%s",et, et->dbname.str, et->name.str));
+    et= ((Event_queue_element*)queue_element(&queue, i));
+    DBUG_PRINT("info",("et=0x%lx db=%s name=%s",et, et->dbname.str, et->name.str));
     DBUG_PRINT("info", ("exec_at=%llu starts=%llu ends=%llu "
                " expr=%lld et.exec_at=%d now=%d (et.exec_at - now)=%d if=%d",
                TIME_to_ulonglong_datetime(&et->execute_at),
@@ -797,14 +761,14 @@ Event_queue::dbug_dump_queue(time_t now)
 #endif
 }
 
-Event_timed *
+Event_job_data *
 Event_queue::get_top_for_execution_if_time(THD *thd, time_t now,
                                            struct timespec *abstime)
 {
   struct timespec top_time;
-  Event_timed *et_new= NULL;
+  Event_job_data *et_new= NULL;
   DBUG_ENTER("Event_queue::get_top_for_execution_if_time");
-  DBUG_PRINT("enter", ("thd=%p now=%d", thd, now));
+  DBUG_PRINT("enter", ("thd=0x%lx now=%d", thd, now));
   abstime->tv_nsec= 0;
   LOCK_QUEUE_DATA();
   do {
@@ -816,28 +780,31 @@ Event_queue::get_top_for_execution_if_time(THD *thd, time_t now,
     }
     dbug_dump_queue(now);
 
-    Event_timed *et= ((Event_timed*)queue_element(&queue, 0));
+    Event_queue_element *et= ((Event_queue_element*) queue_element(&queue, 0));
     top_time.tv_sec= sec_since_epoch_TIME(&et->execute_at);
 
     if (top_time.tv_sec <= now)
     {
       DBUG_PRINT("info", ("Ready for execution"));
       abstime->tv_sec= 0;
-      if ((res= db_repository->load_named_event_timed(thd, et->dbname, et->name,
-                                                      &et_new)))
+      et_new= new Event_job_data();
+      if ((res= db_repository->load_named_event(thd, et->dbname, et->name,
+                                                et_new)))
       {
+        delete et_new;
+        et_new= NULL;
         DBUG_ASSERT(0);
         break;
       }
 
       et->mark_last_executed(thd);
       if (et->compute_next_execution_time())
-        et->status= Event_timed::DISABLED;
+        et->status= Event_queue_element::DISABLED;
       DBUG_PRINT("info", ("event's status is %d", et->status));
 
-      et->update_fields(thd);
+      et->update_timing_fields(thd);
       if (((et->execute_at.year && !et->expression) || et->execute_at_null) ||
-          (et->status == Event_timed::DISABLED))
+          (et->status == Event_queue_element::DISABLED))
       {
         DBUG_PRINT("info", ("removing from the queue"));
         if (et->dropped)
@@ -857,12 +824,122 @@ Event_queue::get_top_for_execution_if_time(THD *thd, time_t now,
   } while (0);
   UNLOCK_QUEUE_DATA();
   
-  DBUG_PRINT("info", ("returning. et_new=%p abstime.tv_sec=%d ", et_new,
+  DBUG_PRINT("info", ("returning. et_new=0x%lx abstime.tv_sec=%d ", et_new,
              abstime->tv_sec));
   if (et_new)
-    DBUG_PRINT("info", ("db=%s  name=%s definer=%s "
-               "et_new.execute_at=%lld", et_new->dbname.str, et_new->name.str,
-               et_new->definer.str,
-               TIME_to_ulonglong_datetime(&et_new->execute_at)));
+    DBUG_PRINT("info", ("db=%s  name=%s definer=%s",
+               et_new->dbname.str, et_new->name.str, et_new->definer.str));
   DBUG_RETURN(et_new);
 }
+
+
+/*
+  Auxiliary function for locking LOCK_event_queue. Used by the
+  LOCK_QUEUE_DATA macro
+
+  SYNOPSIS
+    Event_queue::lock_data()
+      func  Which function is requesting mutex lock
+      line  On which line mutex lock is requested
+*/
+
+void
+Event_queue::lock_data(const char *func, uint line)
+{
+  DBUG_ENTER("Event_queue::lock_data");
+  DBUG_PRINT("enter", ("func=%s line=%u", func, line));
+  pthread_mutex_lock(&LOCK_event_queue);
+  mutex_last_locked_in_func= func;
+  mutex_last_locked_at_line= line;
+  mutex_queue_data_locked= TRUE;
+  DBUG_VOID_RETURN;
+}
+
+
+/*
+  Auxiliary function for unlocking LOCK_event_queue. Used by the
+  UNLOCK_QUEUE_DATA macro
+
+  SYNOPSIS
+    Event_queue::unlock_data()
+      func  Which function is requesting mutex unlock
+      line  On which line mutex unlock is requested
+*/
+
+void
+Event_queue::unlock_data(const char *func, uint line)
+{
+  DBUG_ENTER("Event_queue::unlock_data");
+  DBUG_PRINT("enter", ("func=%s line=%u", func, line));
+  mutex_last_unlocked_at_line= line;
+  mutex_queue_data_locked= FALSE;
+  mutex_last_unlocked_in_func= func;
+  pthread_mutex_unlock(&LOCK_event_queue);
+  DBUG_VOID_RETURN;
+}
+
+
+/*
+  Dumps the internal status of the queue
+
+  SYNOPSIS
+    Event_queue::dump_internal_status()
+      thd  Thread
+
+  RETURN VALUE
+    FALSE  OK
+    TRUE   Error
+*/
+
+bool
+Event_queue::dump_internal_status(THD *thd)
+{
+  DBUG_ENTER("Event_queue::dump_internal_status");
+#ifndef DBUG_OFF
+  CHARSET_INFO *scs= system_charset_info;
+  Protocol *protocol= thd->protocol;
+  List<Item> field_list;
+  int ret;
+  char tmp_buff[5*STRING_BUFFER_USUAL_SIZE];
+  char int_buff[STRING_BUFFER_USUAL_SIZE];
+  String tmp_string(tmp_buff, sizeof(tmp_buff), scs);
+  String int_string(int_buff, sizeof(int_buff), scs);
+  tmp_string.length(0);
+  int_string.length(0);
+
+  /* workers_count */
+  protocol->prepare_for_resend();
+  protocol->store(STRING_WITH_LEN("queue element count"), scs);
+  int_string.set((longlong) queue.elements, scs);
+  protocol->store(&int_string);
+  ret= protocol->write();
+
+  /* queue_data_locked */
+  protocol->prepare_for_resend();
+  protocol->store(STRING_WITH_LEN("queue data locked"), scs);
+  int_string.set((longlong) mutex_queue_data_locked, scs);
+  protocol->store(&int_string);
+  ret= protocol->write();
+
+  /* last locked at*/
+  protocol->prepare_for_resend();
+  protocol->store(STRING_WITH_LEN("queue last locked at"), scs);
+  tmp_string.length(scs->cset->snprintf(scs, (char*) tmp_string.ptr(),
+                                        tmp_string.alloced_length(), "%s::%d",
+                                        mutex_last_locked_in_func,
+                                        mutex_last_locked_at_line));
+  protocol->store(&tmp_string);
+  ret= protocol->write();
+
+  /* last unlocked at*/
+  protocol->prepare_for_resend();
+  protocol->store(STRING_WITH_LEN("queue last unlocked at"), scs);
+  tmp_string.length(scs->cset->snprintf(scs, (char*) tmp_string.ptr(),
+                                        tmp_string.alloced_length(), "%s::%d",
+                                        mutex_last_unlocked_in_func,
+                                        mutex_last_unlocked_at_line));
+  protocol->store(&tmp_string);
+  ret= protocol->write();
+#endif
+  DBUG_RETURN(FALSE);
+}
diff --git a/sql/event_queue.h b/sql/event_queue.h
index d253e3c7597..142a866e5ba 100644
--- a/sql/event_queue.h
+++ b/sql/event_queue.h
@@ -17,13 +17,12 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
 class sp_name;
-class Event_timed;
+class Event_basic;
 class Event_db_repository;
 class Event_job_data;
+class Event_queue_element;
 
 class THD;
-typedef bool * (*event_timed_identifier_comparator)(Event_timed*, Event_timed*);
-
 class Event_scheduler_ng;
 
 class Event_queue
@@ -46,14 +45,14 @@ class Event_queue
   /* Methods for queue management follow */
 
   int
-  create_event(THD *thd, Event_parse_data *et);
+  create_event(THD *thd, LEX_STRING dbname, LEX_STRING name);
 
   int
-  update_event(THD *thd, Event_parse_data *et, LEX_STRING *new_schema,
-               LEX_STRING *new_name);
+  update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
+               LEX_STRING *new_schema, LEX_STRING *new_name);
 
-  bool
-  drop_event(THD *thd, sp_name *name);
+  void
+  drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name);
 
   void
   drop_schema_events(THD *thd, LEX_STRING schema);
@@ -61,32 +60,20 @@ class Event_queue
   uint
   events_count();
 
-  uint
-  events_count_no_lock();
-
   static bool
   check_system_tables(THD *thd);
 
   void
-  recalculate_queue(THD *thd);
-  
-  void
-  empty_queue();
+  recalculate_activation_times(THD *thd);
 
-  Event_timed *
+  Event_job_data *
   get_top_for_execution_if_time(THD *thd, time_t now, struct timespec *abstime);
- 
-  Event_timed*
-  get_top();
-  
-  void
-  remove_top();
-  
-  void
-  top_changed();
+
+  bool
+  dump_internal_status(THD *thd);
 
 protected:
-  Event_timed *
+  Event_queue_element *
   find_event(LEX_STRING db, LEX_STRING name, bool remove_from_q);
 
   int
@@ -94,14 +81,16 @@ class Event_queue
 
   void
   drop_matching_events(THD *thd, LEX_STRING pattern,
-                       bool (*)(Event_timed *,LEX_STRING *));
+                       bool (*)(LEX_STRING *, Event_basic *));
+
+  void
+  empty_queue();
 
   /* LOCK_event_queue is the mutex which protects the access to the queue. */
   pthread_mutex_t LOCK_event_queue;
 
   Event_db_repository *db_repository;
 
-  
   uint mutex_last_locked_at_line;
   uint mutex_last_unlocked_at_line;
   const char* mutex_last_locked_in_func;
@@ -123,10 +112,8 @@ class Event_queue
 
   Event_scheduler_ng *scheduler;
 
-//public:
-  /* The sorted queue with the Event_timed objects */
+  /* The sorted queue with the Event_job_data objects */
   QUEUE queue;
-
 };
 
 #endif /* _EVENT_QUEUE_H_ */
diff --git a/sql/event_scheduler_ng.cc b/sql/event_scheduler_ng.cc
index b256ef8411f..4e2820b8f65 100644
--- a/sql/event_scheduler_ng.cc
+++ b/sql/event_scheduler_ng.cc
@@ -30,6 +30,7 @@
 
 #define LOCK_SCHEDULER_DATA()   lock_data(SCHED_FUNC, __LINE__)
 #define UNLOCK_SCHEDULER_DATA() unlock_data(SCHED_FUNC, __LINE__)
+#define COND_STATE_WAIT(timer)  cond_wait(timer, SCHED_FUNC, __LINE__)
 
 extern pthread_attr_t connection_attrib;
 
@@ -52,28 +53,6 @@ LEX_STRING scheduler_states_names[] =
 };
 
 
-class Worker_thread_param
-{
-public:
-  Event_timed *et;
-  pthread_mutex_t LOCK_started;
-  pthread_cond_t COND_started;
-  bool started;
-
-  Worker_thread_param(Event_timed *etn):et(etn), started(FALSE)
-  {
-    pthread_mutex_init(&LOCK_started, MY_MUTEX_INIT_FAST);
-    pthread_cond_init(&COND_started, NULL);  
-  }
-
-  ~Worker_thread_param()
-  {
-    pthread_mutex_destroy(&LOCK_started);
-    pthread_cond_destroy(&COND_started);
-  }
-};
-
-
 /*
   Prints the stack of infos, warnings, errors from thd to
   the console so it can be fetched by the logs-into-tables and
@@ -81,12 +60,12 @@ class Worker_thread_param
 
   SYNOPSIS
     evex_print_warnings
-      thd    - thread used during the execution of the event
-      et     - the event itself
+      thd  Thread used during the execution of the event
+      et   The event itself
 */
 
 static void
-evex_print_warnings(THD *thd, Event_timed *et)
+evex_print_warnings(THD *thd, Event_job_data *et)
 {
   MYSQL_ERROR *err;
   DBUG_ENTER("evex_print_warnings");
@@ -148,23 +127,22 @@ init_scheduler_thread(THD* thd)
   thd->security_ctx->db_access= 0;
   thd->security_ctx->host_or_ip= (char*)my_localhost;
   thd->security_ctx->set_user((char*)"event_scheduler");
-  my_net_init(&thd->net, 0);
+  my_net_init(&thd->net, NULL);
   thd->net.read_timeout= slave_net_timeout;
   thd->slave_thread= 0;
   thd->options|= OPTION_AUTO_IS_NULL;
   thd->client_capabilities|= CLIENT_MULTI_RESULTS;
-  VOID(pthread_mutex_lock(&LOCK_thread_count));
+  pthread_mutex_lock(&LOCK_thread_count);
   thd->thread_id= thread_id++;
   threads.append(thd);
   thread_count++;
   thread_running++;
-  VOID(pthread_mutex_unlock(&LOCK_thread_count));
+  pthread_mutex_unlock(&LOCK_thread_count);
 
   /*
     Guarantees that we will see the thread in SHOW PROCESSLIST though its
     vio is NULL.
   */
-  thd->system_thread= SYSTEM_THREAD_EVENT_SCHEDULER;
 
   thd->proc_info= "Initialized";
   thd->version= refresh_version;
@@ -174,6 +152,41 @@ init_scheduler_thread(THD* thd)
 }
 
 
+/*
+  Cleans up the THD and the threaded environment of the thread.
+
+  SYNOPSIS
+    deinit_event_thread()
+      thd  Thread
+*/
+
+static void
+deinit_event_thread(THD *thd)
+{
+  thd->proc_info= "Clearing";
+  DBUG_ASSERT(thd->net.buff != 0);
+  net_end(&thd->net);
+  DBUG_PRINT("exit", ("Scheduler thread finishing"));
+  pthread_mutex_lock(&LOCK_thread_count);
+  thread_count--;
+  thread_running--;
+  delete thd;
+  pthread_mutex_unlock(&LOCK_thread_count);
+
+  my_thread_end();
+}
+
+/*
+  Function that executes the scheduler,
+
+  SYNOPSIS
+    event_scheduler_ng_thread()
+      arg  Pointer to `struct scheduler_param`
+
+  RETURN VALUE
+    0  OK
+*/
+
 pthread_handler_t
 event_scheduler_ng_thread(void *arg)
 {
@@ -201,17 +214,8 @@ event_scheduler_ng_thread(void *arg)
   ((struct scheduler_param *) arg)->scheduler->run(thd);
 
 end:
-  thd->proc_info= "Clearing";
-  DBUG_ASSERT(thd->net.buff != 0);
-  net_end(&thd->net);
-  DBUG_PRINT("exit", ("Scheduler thread finishing"));
-  pthread_mutex_lock(&LOCK_thread_count);
-  thread_count--;
-  thread_running--;
-  delete thd;
-  pthread_mutex_unlock(&LOCK_thread_count);
+  deinit_event_thread(thd);
 
-  my_thread_end();
   DBUG_RETURN(0);                               // Against gcc warnings
 }
 
@@ -222,7 +226,7 @@ event_scheduler_ng_thread(void *arg)
 
   SYNOPSIS
     event_worker_ng_thread()
-      arg  The Event_timed object to be processed
+      arg  The Event_job_data object to be processed
 
   RETURN VALUE
     0  OK
@@ -233,14 +237,12 @@ event_worker_ng_thread(void *arg)
 {
   /* needs to be first for thread_stack */
   THD *thd; 
-  Event_timed *event= (Event_timed *)arg;
+  Event_job_data *event= (Event_job_data *)arg;
   int ret;
 
   thd= event->thd;
   thd->thread_stack= (char *) &thd;
 
-  DBUG_ENTER("event_worker_thread");
-  DBUG_PRINT("enter", ("event=[%s.%s]", event->dbname.str, event->name.str));
 
   my_thread_init();
   pthread_detach_this_thread();
@@ -251,62 +253,68 @@ event_worker_ng_thread(void *arg)
     goto end;
   }
 
+
 #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
   sigset_t set;
   VOID(sigemptyset(&set));			// Get mask in use
   VOID(pthread_sigmask(SIG_UNBLOCK, &set, &thd->block_signals));
 #endif
+  thd->init_for_queries();
+
+  DBUG_ENTER("event_worker_ng_thread");
+  DBUG_PRINT("info", ("Baikonur, time is %d, BURAN reporting and operational."
+             "THD=0x%lx", time(NULL), thd));
+
   sql_print_information("SCHEDULER: [%s.%s of %s] executing in thread %lu",
                         event->dbname.str, event->name.str,
                         event->definer.str, thd->thread_id);
 
-  thd->init_for_queries();
   thd->enable_slow_log= TRUE;
 
   ret= event->execute(thd, thd->mem_root);
 
   evex_print_warnings(thd, event);
 
-  sql_print_information("SCHEDULER: [%s.%s of %s] executed. RetCode=%d",
+  sql_print_information("SCHEDULER: [%s.%s of %s] executed "
+                        " in thread thread %lu. RetCode=%d",
                         event->dbname.str, event->name.str,
-                        event->definer.str, ret);
+                        event->definer.str, thd->thread_id, ret);
   if (ret == EVEX_COMPILE_ERROR)
     sql_print_information("SCHEDULER: COMPILE ERROR for event %s.%s of %s",
                           event->dbname.str, event->name.str,
                           event->definer.str);
   else if (ret == EVEX_MICROSECOND_UNSUP)
     sql_print_information("SCHEDULER: MICROSECOND is not supported");
-  
-  DBUG_PRINT("info", ("master_access=%d db_access=%d",
-             thd->security_ctx->master_access, thd->security_ctx->db_access));
 
 end:
-  thd->proc_info= "Clearing";
-  DBUG_ASSERT(thd->net.buff != 0);
-  /*
-    Free it here because net.vio is NULL for us => THD::~THD will check it
-    and won't call net_end(&net); See also replication code.
-  */
-  net_end(&thd->net);
-  DBUG_PRINT("info", ("Worker thread %lu exiting", thd->thread_id));
-  VOID(pthread_mutex_lock(&LOCK_thread_count));
-  thread_count--;
-  thread_running--;
-  delete thd;
-  VOID(pthread_mutex_unlock(&LOCK_thread_count));
+  DBUG_PRINT("info", ("BURAN %s.%s is landing!", event->dbname.str,
+             event->name.str));
   delete event;
 
-  my_thread_end();
+  deinit_event_thread(thd);
+
   DBUG_RETURN(0);                               // Against gcc warnings
 }
 
 
+/*
+  Performs initialization of the scheduler data, outside of the
+  threading primitives.
+
+  SYNOPSIS
+    Event_scheduler_ng::init_scheduler()
+*/
+
 bool
 Event_scheduler_ng::init_scheduler(Event_queue *q)
 {
+  LOCK_SCHEDULER_DATA();
   thread_id= 0;
   state= INITIALIZED;
   queue= q;
+  started_events= 0;
+  UNLOCK_SCHEDULER_DATA();
+
   return FALSE;
 }
 
@@ -315,6 +323,13 @@ void
 Event_scheduler_ng::deinit_scheduler() {}
 
 
+/*
+  Inits scheduler's threading primitives.
+
+  SYNOPSIS
+    Event_scheduler_ng::init_mutexes()
+*/
+
 void
 Event_scheduler_ng::init_mutexes()
 {
@@ -323,6 +338,13 @@ Event_scheduler_ng::init_mutexes()
 }
 
 
+/*
+  Deinits scheduler's threading primitives.
+
+  SYNOPSIS
+    Event_scheduler_ng::deinit_mutexes()
+*/
+
 void
 Event_scheduler_ng::deinit_mutexes()
 {
@@ -331,6 +353,21 @@ Event_scheduler_ng::deinit_mutexes()
 }
 
 
+/*
+  Starts the scheduler (again). Creates a new THD and passes it to
+  a forked thread. Does not wait for acknowledgement from the new
+  thread that it has started. Asynchronous starting. Most of the
+  needed initializations are done in the current thread to minimize
+  the chance of failure in the spawned thread.
+
+  SYNOPSIS
+    Event_scheduler_ng::start()
+
+  RETURN VALUE
+    FALSE  OK
+    TRUE   Error (not reported)
+*/
+
 bool
 Event_scheduler_ng::start()
 {
@@ -340,6 +377,7 @@ Event_scheduler_ng::start()
   DBUG_ENTER("Event_scheduler_ng::start");
 
   LOCK_SCHEDULER_DATA();
+  DBUG_PRINT("info", ("state before action %s", scheduler_states_names[state]));
   if (state > INITIALIZED)
     goto end;
 
@@ -349,10 +387,13 @@ Event_scheduler_ng::start()
     ret= TRUE;
     goto end;
   }
+  new_thd->system_thread= SYSTEM_THREAD_EVENT_SCHEDULER;
+  new_thd->command= COM_DAEMON;
 
   scheduler_param_value.thd= new_thd;
   scheduler_param_value.scheduler= this;
 
+  DBUG_PRINT("info", ("Forking new thread for scheduduler. THD=0x%lx", new_thd));
   if (pthread_create(&th, &connection_attrib, event_scheduler_ng_thread,
                     (void*)&scheduler_param_value))
   {
@@ -360,13 +401,14 @@ Event_scheduler_ng::start()
     state= INITIALIZED;
     ret= TRUE;
   }
-
+  DBUG_PRINT("info", ("Setting state go RUNNING"));
   state= RUNNING;
 end:
   UNLOCK_SCHEDULER_DATA();
 
   if (ret && new_thd)
   {
+    DBUG_PRINT("info", ("There was an error during THD creation. Clean up"));
     new_thd->proc_info= "Clearing";
     DBUG_ASSERT(new_thd->net.buff != 0);
     net_end(&new_thd->net);
@@ -380,14 +422,27 @@ Event_scheduler_ng::start()
 }
 
 
+/*
+  Stops the scheduler (again). Waits for acknowledgement from the
+  scheduler that it has stopped - synchronous stopping.
+
+  SYNOPSIS
+    Event_scheduler_ng::stop()
+
+  RETURN VALUE
+    FALSE  OK
+    TRUE   Error (not reported)
+*/
+
 bool
 Event_scheduler_ng::stop()
 {
   THD *thd= current_thd;
   DBUG_ENTER("Event_scheduler_ng::stop");
-  DBUG_PRINT("enter", ("thd=%p", current_thd));
+  DBUG_PRINT("enter", ("thd=0x%lx", current_thd));
 
   LOCK_SCHEDULER_DATA();
+  DBUG_PRINT("info", ("state before action %s", scheduler_states_names[state]));
   if (state != RUNNING)
     goto end;
 
@@ -406,48 +461,75 @@ Event_scheduler_ng::stop()
                         "workers count=%d", scheduler_states_names[state].str,
                         workers_count()));
     /* thd could be 0x0, when shutting down */
-    pthread_cond_wait(&COND_state, &LOCK_scheduler_state);
+    COND_STATE_WAIT(NULL);
   } while (state == STOPPING);
   DBUG_PRINT("info", ("Manager thread has cleaned up. Set state to INIT"));
+
+  thread_id= 0;
 end:
   UNLOCK_SCHEDULER_DATA();
   DBUG_RETURN(FALSE);
 }
 
 
+/*
+  The main loop of the scheduler.
+
+  SYNOPSIS
+    Event_scheduler_ng::run()
+      thd  Thread
+
+  RETURN VALUE
+    FALSE  OK
+    TRUE   Error (Serious error)
+*/
+
 bool
 Event_scheduler_ng::run(THD *thd)
 {
+  int res;
   struct timespec abstime;
-  Event_timed *job_data;
+  Event_job_data *job_data;
+  DBUG_ENTER("Event_scheduler_ng::run");
 
   LOCK_SCHEDULER_DATA();
 
   thread_id= thd->thread_id;
   sql_print_information("SCHEDULER: Manager thread started with id %lu",
                         thread_id);
+  /*
+    Recalculate the values in the queue because there could have been stops
+    in executions of the scheduler and some times could have passed by.
+  */
+  queue->recalculate_activation_times(thd);
   while (state == RUNNING)
   {
     thd->end_time();
     /* Gets a minimized version */
-    job_data= queue->get_top_for_execution_if_time(thd, thd->query_start(),
-                                                   &abstime);
-    DBUG_PRINT("info", ("get_top returned job_data=%p now=%d abs_time.tv_sec=%d",
-               job_data, thd->query_start(), abstime.tv_sec));
+    job_data= queue->
+            get_top_for_execution_if_time(thd, thd->query_start(), &abstime);
+
+    DBUG_PRINT("info", ("get_top returned job_data=0x%lx now=%d "
+                        "abs_time.tv_sec=%d",
+                        job_data, thd->query_start(), abstime.tv_sec));
     if (!job_data && !abstime.tv_sec)
     {
+      DBUG_PRINT("info", ("The queue is empty. Going to sleep"));
       thd->enter_cond(&COND_state, &LOCK_scheduler_state,
                       "Waiting on empty queue");
-      pthread_cond_wait(&COND_state, &LOCK_scheduler_state);
+      COND_STATE_WAIT(NULL);
       thd->exit_cond("");
       DBUG_PRINT("info", ("Woke up. Got COND_state"));
       LOCK_SCHEDULER_DATA();
     }
     else if (abstime.tv_sec)
     {
+      DBUG_PRINT("info", ("Have to sleep some time %u till",
+                 abstime.tv_sec - thd->query_start(), abstime.tv_sec));
+
       thd->enter_cond(&COND_state, &LOCK_scheduler_state,
                       "Waiting for next activation");
-      pthread_cond_timedwait(&COND_state, &LOCK_scheduler_state, &abstime);
+      COND_STATE_WAIT(&abstime);
       /*
         If we get signal we should recalculate the whether it's the right time
         because there could be :
@@ -461,12 +543,12 @@ Event_scheduler_ng::run(THD *thd)
     }
     else
     {
-      int res;
       UNLOCK_SCHEDULER_DATA();
       res= execute_top(thd, job_data);
       LOCK_SCHEDULER_DATA();
       if (res)
         break;
+      ++started_events;
     }
     DBUG_PRINT("info", ("state=%s", scheduler_states_names[state].str));
   }
@@ -477,29 +559,47 @@ Event_scheduler_ng::run(THD *thd)
   UNLOCK_SCHEDULER_DATA();
   sql_print_information("SCHEDULER: Stopped");
 
-  return FALSE;
+  DBUG_RETURN(res);
 }
 
 
+/*
+  Creates a new THD instance and then forks a new thread, while passing
+  the THD pointer and job_data to it.
+
+  SYNOPSIS
+    Event_scheduler_ng::execute_top()
+
+  RETURN VALUE
+    FALSE  OK
+    TRUE   Error (Serious error)
+*/
+
 bool
-Event_scheduler_ng::execute_top(THD *thd, Event_timed *job_data)
+Event_scheduler_ng::execute_top(THD *thd, Event_job_data *job_data)
 {
   THD *new_thd;
   pthread_t th;
+  int res= 0;
   DBUG_ENTER("Event_scheduler_ng::execute_top");
   if (!(new_thd= new THD) || init_scheduler_thread(new_thd))
     goto error;
 
-  /* Major failure */
+  new_thd->system_thread= SYSTEM_THREAD_EVENT_WORKER;
   job_data->thd= new_thd;
-  DBUG_PRINT("info", ("Starting new thread for %s@%s",
+  DBUG_PRINT("info", ("BURAN %s@%s ready for start t-3..2..1..0..ignition",
              job_data->dbname.str, job_data->name.str));
-  if (pthread_create(&th, &connection_attrib, event_worker_ng_thread, job_data))
+
+  /* Major failure */
+  if ((res= pthread_create(&th, &connection_attrib, event_worker_ng_thread,
+                           job_data)))
     goto error;
 
+  DBUG_PRINT("info", ("Launch succeeded. BURAN is in THD=0x%lx", new_thd));
   DBUG_RETURN(FALSE);
 
 error:
+  DBUG_PRINT("error", ("Baikonur, we have a problem! res=%d", res));
   if (new_thd)
   {
     new_thd->proc_info= "Clearing";
@@ -511,10 +611,21 @@ Event_scheduler_ng::execute_top(THD *thd, Event_timed *job_data)
     delete new_thd;
     pthread_mutex_unlock(&LOCK_thread_count);
   }
+  delete job_data;
   DBUG_RETURN(TRUE);
 }
 
 
+/*
+  Returns the current state of the scheduler
+
+  SYNOPSIS
+    Event_scheduler_ng::get_state()
+
+  RETURN VALUE
+    The state of the scheduler (INITIALIZED | RUNNING | STOPPING)
+*/
+
 enum Event_scheduler_ng::enum_state
 Event_scheduler_ng::get_state()
 {
@@ -526,13 +637,12 @@ Event_scheduler_ng::get_state()
 }
 
 
-int
-Event_scheduler_ng::dump_internal_status(THD *thd)
-{
-  return 1;
-
-}
+/*
+  Returns the number of living event worker threads.
 
+  SYNOPSIS
+    Event_scheduler_ng::workers_count()
+*/
 
 uint
 Event_scheduler_ng::workers_count()
@@ -541,7 +651,7 @@ Event_scheduler_ng::workers_count()
   uint count= 0;
   
   DBUG_ENTER("Event_scheduler_ng::workers_count");
-  VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
+  pthread_mutex_lock(&LOCK_thread_count);       // For unlink from list
   I_List_iterator<THD> it(threads);
   while ((tmp=it++))
   {
@@ -550,7 +660,7 @@ Event_scheduler_ng::workers_count()
     if (tmp->system_thread == SYSTEM_THREAD_EVENT_WORKER)
       ++count;
   }
-  VOID(pthread_mutex_unlock(&LOCK_thread_count));
+  pthread_mutex_unlock(&LOCK_thread_count);
   DBUG_PRINT("exit", ("%d", count));
   DBUG_RETURN(count);
 }
@@ -568,16 +678,27 @@ void
 Event_scheduler_ng::queue_changed()
 {
   DBUG_ENTER("Event_scheduler_ng::queue_changed");
-  DBUG_PRINT("info", ("Sending COND_state"));
+  DBUG_PRINT("info", ("Sending COND_state. state (read wo lock)=%s ",
+             scheduler_states_names[state].str));
   pthread_cond_signal(&COND_state);
   DBUG_VOID_RETURN;
 }
 
 
+/*
+  Auxiliary function for locking LOCK_scheduler_state. Used
+  by the LOCK_SCHEDULER_DATA macro.
+
+  SYNOPSIS
+    Event_scheduler_ng::lock_data()
+      func  Which function is requesting mutex lock
+      line  On which line mutex lock is requested
+*/
+
 void
 Event_scheduler_ng::lock_data(const char *func, uint line)
 {
-  DBUG_ENTER("Event_scheduler_ng::lock_mutex");
+  DBUG_ENTER("Event_scheduler_ng::lock_data");
   DBUG_PRINT("enter", ("func=%s line=%u", func, line));
   pthread_mutex_lock(&LOCK_scheduler_state);
   mutex_last_locked_in_func= func;
@@ -587,10 +708,20 @@ Event_scheduler_ng::lock_data(const char *func, uint line)
 }
 
 
+/*
+  Auxiliary function for unlocking LOCK_scheduler_state. Used
+  by the UNLOCK_SCHEDULER_DATA macro.
+
+  SYNOPSIS
+    Event_scheduler_ng::unlock_data()
+      func  Which function is requesting mutex unlock
+      line  On which line mutex unlock is requested
+*/
+
 void
 Event_scheduler_ng::unlock_data(const char *func, uint line)
 {
-  DBUG_ENTER("Event_scheduler_ng::unlock_mutex");
+  DBUG_ENTER("Event_scheduler_ng::unlock_data");
   DBUG_PRINT("enter", ("func=%s line=%u", func, line));
   mutex_last_unlocked_at_line= line;
   mutex_scheduler_data_locked= FALSE;
@@ -598,3 +729,147 @@ Event_scheduler_ng::unlock_data(const char *func, uint line)
   pthread_mutex_unlock(&LOCK_scheduler_state);
   DBUG_VOID_RETURN;
 }
+
+
+/*
+  Wrapper for pthread_cond_wait/timedwait
+
+  SYNOPSIS
+    Event_scheduler_ng::cond_wait()
+      cond   Conditional to wait for
+      mutex  Mutex of the conditional
+
+  RETURN VALUE
+    Error code of pthread_cond_wait()
+*/
+
+void
+Event_scheduler_ng::cond_wait(struct timespec *abstime,
+                              const char *func, uint line)
+{
+  DBUG_ENTER("Event_scheduler_ng::cond_wait");
+  waiting_on_cond= TRUE;
+  mutex_last_unlocked_at_line= line;
+  mutex_scheduler_data_locked= FALSE;
+  mutex_last_unlocked_in_func= func;
+
+  if (abstime)
+    pthread_cond_timedwait(&COND_state, &LOCK_scheduler_state, abstime);
+  else
+    pthread_cond_wait(&COND_state, &LOCK_scheduler_state);
+
+  mutex_last_locked_in_func= func;
+  mutex_last_locked_at_line= line;
+  mutex_scheduler_data_locked= TRUE;
+  waiting_on_cond= FALSE;
+
+  DBUG_VOID_RETURN;
+}
+
+
+/*
+  Dumps the internal status of the scheduler
+
+  SYNOPSIS
+    Event_scheduler_ng::dump_internal_status()
+      thd  Thread
+
+  RETURN VALUE
+    FALSE  OK
+    TRUE   Error
+*/
+
+bool
+Event_scheduler_ng::dump_internal_status(THD *thd)
+{
+  int ret= 0;
+  DBUG_ENTER("Event_scheduler_ng::dump_internal_status");
+
+#ifndef DBUG_OFF
+  CHARSET_INFO *scs= system_charset_info;
+  Protocol *protocol= thd->protocol;
+  char tmp_buff[5*STRING_BUFFER_USUAL_SIZE];
+  char int_buff[STRING_BUFFER_USUAL_SIZE];
+  String tmp_string(tmp_buff, sizeof(tmp_buff), scs);
+  String int_string(int_buff, sizeof(int_buff), scs);
+  tmp_string.length(0);
+  int_string.length(0);
+
+  protocol->prepare_for_resend();
+  protocol->store(STRING_WITH_LEN("scheduler state"), scs);
+  protocol->store(scheduler_states_names[state].str,
+                  scheduler_states_names[state].length, scs);
+
+  if ((ret= protocol->write()))
+    goto end;
+
+  /* thread_id */
+  protocol->prepare_for_resend();
+  protocol->store(STRING_WITH_LEN("thread_id"), scs);
+  if (thread_id)
+  {
+    int_string.set((longlong) thread_id, scs);
+    protocol->store(&int_string);
+  }
+  else
+    protocol->store_null();
+  if ((ret= protocol->write()))
+    goto end;
+
+  /* last locked at*/
+  protocol->prepare_for_resend();
+  protocol->store(STRING_WITH_LEN("scheduler last locked at"), scs);
+  tmp_string.length(scs->cset->snprintf(scs, (char*) tmp_string.ptr(),
+                                        tmp_string.alloced_length(), "%s::%d",
+                                        mutex_last_locked_in_func,
+                                        mutex_last_locked_at_line));
+  protocol->store(&tmp_string);
+  if ((ret= protocol->write()))
+    goto end;
+
+  /* last unlocked at*/
+  protocol->prepare_for_resend();
+  protocol->store(STRING_WITH_LEN("scheduler last unlocked at"), scs);
+  tmp_string.length(scs->cset->snprintf(scs, (char*) tmp_string.ptr(),
+                                        tmp_string.alloced_length(), "%s::%d",
+                                        mutex_last_unlocked_in_func,
+                                        mutex_last_unlocked_at_line));
+  protocol->store(&tmp_string);
+  if ((ret= protocol->write()))
+    goto end;
+
+  /* waiting on */
+  protocol->prepare_for_resend();
+  protocol->store(STRING_WITH_LEN("scheduler waiting on condition"), scs);
+  int_string.set((longlong) waiting_on_cond, scs);
+  protocol->store(&int_string);
+  if ((ret= protocol->write()))
+    goto end;
+
+  /* workers_count */
+  protocol->prepare_for_resend();
+  protocol->store(STRING_WITH_LEN("scheduler workers count"), scs);
+  int_string.set((longlong) workers_count(), scs);
+  protocol->store(&int_string);
+  if ((ret= protocol->write()))
+    goto end;
+
+  /* workers_count */
+  protocol->prepare_for_resend();
+  protocol->store(STRING_WITH_LEN("scheduler executed events"), scs);
+  int_string.set((longlong) started_events, scs);
+  protocol->store(&int_string);
+  if ((ret= protocol->write()))
+    goto end;
+
+  /* scheduler_data_locked */
+  protocol->prepare_for_resend();
+  protocol->store(STRING_WITH_LEN("scheduler data locked"), scs);
+  int_string.set((longlong) mutex_scheduler_data_locked, scs);
+  protocol->store(&int_string);
+  ret= protocol->write();
+end:
+#endif
+
+  DBUG_RETURN(ret);
+}
diff --git a/sql/event_scheduler_ng.h b/sql/event_scheduler_ng.h
index 41642161fc6..e4f3f0588f9 100644
--- a/sql/event_scheduler_ng.h
+++ b/sql/event_scheduler_ng.h
@@ -16,8 +16,8 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
-class Event_timed;
 class Event_queue;
+class Event_job_data;
 
 class Event_scheduler_ng
 {
@@ -67,7 +67,7 @@ class Event_scheduler_ng
   void
   queue_changed();
 
-  static int
+  bool
   dump_internal_status(THD *thd);
 
 private:
@@ -76,7 +76,7 @@ class Event_scheduler_ng
 
   /* helper functions */
   bool
-  execute_top(THD *thd, Event_timed *job_data);
+  execute_top(THD *thd, Event_job_data *job_data);
 
   /* helper functions for working with mutexes & conditionals */
   void
@@ -84,7 +84,10 @@ class Event_scheduler_ng
 
   void
   unlock_data(const char *func, uint line);
-  
+
+  void
+  cond_wait(struct timespec *abstime, const char *func, uint line);
+
   pthread_mutex_t LOCK_scheduler_state;
 
   /* This is the current status of the life-cycle of the scheduler. */
@@ -107,6 +110,9 @@ class Event_scheduler_ng
   const char* mutex_last_locked_in_func;
   const char* mutex_last_unlocked_in_func;
   bool mutex_scheduler_data_locked;
+  bool waiting_on_cond;
+  
+  ulonglong started_events;
 
 private:
   /* Prevent use of these */
diff --git a/sql/events.cc b/sql/events.cc
index d1bbb6be884..08e17a9578a 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -291,11 +291,11 @@ Events::open_event_table(THD *thd, enum thr_lock_type lock_type,
 
   RETURN VALUE
     0   OK
-    !0  Error
+    !0  Error (Reported)
 
   NOTES
-    - in case there is an event with the same name (db) and 
-      IF NOT EXISTS is specified, an warning is put into the W stack.
+    In case there is an event with the same name (db) and 
+    IF NOT EXISTS is specified, an warning is put into the stack.
 */
 
 int
@@ -304,13 +304,20 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, bool if_not_exists,
 {
   int ret;
   DBUG_ENTER("Events::create_event");
+
+  pthread_mutex_lock(&LOCK_event_metadata);
+  /* On error conditions my_error() is called so no need to handle here */
   if (!(ret= db_repository->create_event(thd, parse_data, if_not_exists,
                                          rows_affected)))
   {
-    if ((ret= event_queue->create_event(thd, parse_data)))
-      my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0), ret);
+    if ((ret= event_queue->create_event(thd, parse_data->dbname,
+                                        parse_data->name)))
+    {
+      DBUG_ASSERT(ret == OP_LOAD_ERROR);
+      my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0));
+    }
   }
-  /* No need to close the table, it will be closed in sql_parse::do_command */
+  pthread_mutex_unlock(&LOCK_event_metadata);
 
   DBUG_RETURN(ret);
 }
@@ -322,8 +329,8 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, bool if_not_exists,
   SYNOPSIS
     Events::update_event()
       thd        THD
-      et         event's data
-      new_name   set in case of RENAME TO.
+      et         Event's data from parsing stage
+      new_name   Set in case of RENAME TO.
 
   RETURN VALUE
     0   OK
@@ -341,18 +348,23 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, sp_name *new_name,
 {
   int ret;
   DBUG_ENTER("Events::update_event");
-  /*
-    db_update_event() opens & closes the table to prevent
-    crash later in the code when loading and compiling the new definition.
-    Also on error conditions my_error() is called so no need to handle here
-  */
+
+  pthread_mutex_lock(&LOCK_event_metadata);
+  /* On error conditions my_error() is called so no need to handle here */
   if (!(ret= db_repository->update_event(thd, parse_data, new_name)))
   {
-    if ((ret= event_queue->update_event(thd, parse_data,
+    if ((ret= event_queue->update_event(thd,
+                                        parse_data->dbname,
+                                        parse_data->name,
                                         new_name? &new_name->m_db: NULL,
                                         new_name? &new_name->m_name: NULL)))
-      my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0), ret);
+    {
+      DBUG_ASSERT(ret == OP_LOAD_ERROR);
+      my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0));
+    }
   }
+  pthread_mutex_unlock(&LOCK_event_metadata);
+
   DBUG_RETURN(ret);
 }
 
@@ -363,10 +375,15 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, sp_name *new_name,
   SYNOPSIS
     Events::drop_event()
       thd             THD
+      dbname          Event's schema
       name            Event's name
       if_exists       When set and the event does not exist => warning onto
                       the stack
       rows_affected   Affected number of rows is returned heres
+      only_from_disk  Whether to remove the event from the queue too. In case
+                      of Event_job_data::drop() it's needed to do only disk
+                      drop because Event_queue will handle removal from memory
+                      queue.
 
   RETURN VALUE
      0  OK
@@ -374,17 +391,52 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, sp_name *new_name,
 */
 
 int
-Events::drop_event(THD *thd, sp_name *name, bool if_exists, uint *rows_affected)
+Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists,
+                   uint *rows_affected, bool only_from_disk)
 {
   int ret;
   DBUG_ENTER("Events::drop_event");
 
-  if (!(ret= db_repository->drop_event(thd, name->m_db, name->m_name, if_exists,
+  pthread_mutex_lock(&LOCK_event_metadata);
+  /* On error conditions my_error() is called so no need to handle here */
+  if (!(ret= db_repository->drop_event(thd, dbname, name, if_exists,
                                        rows_affected)))
   {
-    if ((ret= event_queue->drop_event(thd, name)))
-      my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0), ret);
+    if (!only_from_disk)
+      event_queue->drop_event(thd, dbname, name);
   }
+  pthread_mutex_unlock(&LOCK_event_metadata);
+  DBUG_RETURN(ret);
+}
+
+
+/*
+  Drops all events from a schema
+
+  SYNOPSIS
+    Events::drop_schema_events()
+      thd  Thread
+      db   ASCIIZ schema name
+
+  RETURN VALUE
+    0   OK
+    !0  Error
+*/
+
+int
+Events::drop_schema_events(THD *thd, char *db)
+{
+  int ret= 0;
+  LEX_STRING db_lex= {db, strlen(db)};
+  
+  DBUG_ENTER("evex_drop_db_events");  
+  DBUG_PRINT("enter", ("dropping events from %s", db));
+
+  pthread_mutex_lock(&LOCK_event_metadata);
+  event_queue->drop_schema_events(thd, db_lex);
+  ret= db_repository->drop_schema_events(thd, db_lex);
+  pthread_mutex_unlock(&LOCK_event_metadata);
+
   DBUG_RETURN(ret);
 }
 
@@ -406,14 +458,14 @@ int
 Events::show_create_event(THD *thd, sp_name *spn)
 {
   int ret;
-  Event_timed *et= NULL;
+  Event_timed *et= new Event_timed();
   Open_tables_state backup;
 
   DBUG_ENTER("Events::show_create_event");
   DBUG_PRINT("enter", ("name: %*s", spn->m_name.length, spn->m_name.str));
 
   thd->reset_n_backup_open_tables_state(&backup);
-  ret= db_repository->find_event(thd, spn->m_db, spn->m_name, &et, NULL);
+  ret= db_repository->find_event(thd, spn->m_db, spn->m_name, et);
   thd->restore_backup_open_tables_state(&backup);
 
   if (!ret)
@@ -458,36 +510,43 @@ Events::show_create_event(THD *thd, sp_name *spn)
   DBUG_RETURN(ret);
 err:
   delete et;
-  DBUG_RETURN(1);  
+  DBUG_RETURN(1);
 }
 
 
 /*
-  Drops all events from a schema
+  Proxy for Event_db_repository::fill_schema_events.
+  Callback for I_S from sql_show.cc
 
   SYNOPSIS
-    Events::drop_schema_events()
-      thd  Thread
-      db   ASCIIZ schema name
+    Events::fill_schema_events()
+      thd     Thread
+      tables  The schema table
+      cond    Unused
 
   RETURN VALUE
-    0   OK
-    !0  Error
+    0  OK
+    !0 Error
 */
 
 int
-Events::drop_schema_events(THD *thd, char *db)
+Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
 {
-  int ret= 0;
-  LEX_STRING db_lex= {db, strlen(db)};
-  
-  DBUG_ENTER("evex_drop_db_events");  
-  DBUG_PRINT("enter", ("dropping events from %s", db));
-
-  event_queue->drop_schema_events(thd, db_lex);
-  ret= db_repository->drop_schema_events(thd, db_lex);
-
-  DBUG_RETURN(ret);
+  char *db= NULL;
+  DBUG_ENTER("Events::fill_schema_events");
+  /*
+    If it's SHOW EVENTS then thd->lex->select_lex.db is guaranteed not to
+    be NULL. Let's do an assert anyway.
+  */
+  if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS)
+  {
+    DBUG_ASSERT(thd->lex->select_lex.db);
+    if (check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0,
+                     is_schema_db(thd->lex->select_lex.db)))
+      DBUG_RETURN(1);
+    db= thd->lex->select_lex.db;
+  }
+  DBUG_RETURN(get_instance()->db_repository->fill_schema_events(thd, tables, db));
 }
 
 
@@ -511,7 +570,6 @@ Events::init()
   int ret= 0;
   Event_db_repository *db_repo;
   DBUG_ENTER("Events::init");
-  db_repository->init_repository();
   event_queue->init_queue(db_repository, scheduler_ng);
   scheduler_ng->init_scheduler(event_queue);
 
@@ -546,7 +604,6 @@ Events::deinit()
   scheduler_ng->deinit_scheduler();
 
   event_queue->deinit_queue();
-  db_repository->deinit_repository();
 
   DBUG_VOID_RETURN;
 }
@@ -563,6 +620,8 @@ Events::deinit()
 void
 Events::init_mutexes()
 {
+  pthread_mutex_init(&LOCK_event_metadata, MY_MUTEX_INIT_FAST);
+
   db_repository= new Event_db_repository;
 
   event_queue= new Event_queue;
@@ -585,9 +644,11 @@ Events::destroy_mutexes()
 {
   event_queue->deinit_mutexes();
   scheduler_ng->deinit_mutexes();
-  
+
   delete scheduler_ng;
   delete db_repository;
+
+  pthread_mutex_destroy(&LOCK_event_metadata);
 }
 
 
@@ -597,55 +658,45 @@ Events::destroy_mutexes()
   SYNOPSIS
     Events::dump_internal_status()
       thd  Thread
-  
+
   RETURN VALUE
-    0  OK
-    !0 Error
+    FALSE  OK
+    TRUE   Error
 */
 
-int
+bool
 Events::dump_internal_status(THD *thd)
 {
-  return Event_scheduler_ng::dump_internal_status(thd);
+  DBUG_ENTER("Events::dump_internal_status");
+  Protocol *protocol= thd->protocol;
+  List<Item> field_list;
+
+  field_list.push_back(new Item_empty_string("Name", 30));
+  field_list.push_back(new Item_empty_string("Value",20));
+  if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
+                                         Protocol::SEND_EOF))
+    DBUG_RETURN(TRUE);
+
+  if (scheduler_ng->dump_internal_status(thd) ||
+      event_queue->dump_internal_status(thd))
+    DBUG_RETURN(TRUE);
+
+  send_eof(thd);
+  DBUG_RETURN(FALSE);
 }
 
 
 /*
-  Proxy for Event_db_repository::fill_schema_events.
-  Callback for I_S from sql_show.cc
+  Starts execution of events by the scheduler
 
   SYNOPSIS
-    Events::fill_schema_events()
-      thd     Thread
-      tables  The schema table
-      cond    Unused
+    Events::start_execution_of_events()
 
   RETURN VALUE
-    0  OK
-    !0 Error
+    FALSE  OK
+    TRUE   Error
 */
 
-int
-Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
-{
-  char *db= NULL;
-  DBUG_ENTER("Events::fill_schema_events");
-  /*
-    If it's SHOW EVENTS then thd->lex->select_lex.db is guaranteed not to
-    be NULL. Let's do an assert anyway.
-  */
-  if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS)
-  {
-    DBUG_ASSERT(thd->lex->select_lex.db);
-    if (check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0,
-                     is_schema_db(thd->lex->select_lex.db)))
-      DBUG_RETURN(1);
-    db= thd->lex->select_lex.db;
-  }
-  DBUG_RETURN(get_instance()->db_repository->fill_schema_events(thd, tables, db));
-}
-
-
 bool
 Events::start_execution_of_events()
 {
@@ -654,6 +705,19 @@ Events::start_execution_of_events()
 }
 
 
+/*
+  Stops execution of events by the scheduler.
+  Already running events will not be stopped. If the user needs
+  them stopped manual intervention is needed.
+
+  SYNOPSIS
+    Events::stop_execution_of_events()
+
+  RETURN VALUE
+    FALSE  OK
+    TRUE   Error
+*/
+
 bool
 Events::stop_execution_of_events()
 {
@@ -661,6 +725,18 @@ Events::stop_execution_of_events()
   DBUG_RETURN(scheduler_ng->stop());
 }
 
+
+/*
+  Checks whether the scheduler is running or not.
+
+  SYNOPSIS
+    Events::is_started()
+
+  RETURN VALUE
+    TRUE  Yes
+    FALSE No
+*/
+
 bool
 Events::is_started()
 {
diff --git a/sql/events.h b/sql/events.h
index bb9fe7a8fc5..f825a75934f 100644
--- a/sql/events.h
+++ b/sql/events.h
@@ -20,6 +20,7 @@ class sp_name;
 class Event_parse_data;
 class Event_db_repository;
 class Event_queue;
+class Event_queue_element;
 class Event_scheduler_ng;
 
 /* Return codes */
@@ -41,6 +42,7 @@ sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
 class Events
 {
 public:
+  friend class Event_queue_element;
   /*
     Quite NOT the best practice and will be removed once
     Event_timed::drop() and Event_timed is fixed not do drop directly
@@ -83,7 +85,8 @@ class Events
                uint *rows_affected);
 
   int
-  drop_event(THD *thd, sp_name *name, bool if_exists, uint *rows_affected);
+  drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists,
+             uint *rows_affected, bool only_from_disk);
 
   int
   drop_schema_events(THD *thd, char *db);
@@ -102,13 +105,9 @@ class Events
   static int
   fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */);
   
-  int
+  bool
   dump_internal_status(THD *thd);
 
-  Event_queue         *event_queue;
-  Event_scheduler_ng  *scheduler_ng;
-  Event_db_repository *db_repository;
-
 private:
   /* Singleton DP is used */
   Events(){}
@@ -117,6 +116,12 @@ class Events
   /* Singleton instance */
   static Events singleton;
 
+  Event_queue         *event_queue;
+  Event_scheduler_ng  *scheduler_ng;
+  Event_db_repository *db_repository;
+
+  pthread_mutex_t LOCK_event_metadata;  
+
   /* Prevent use of these */
   Events(const Events &);
   void operator=(Events &);
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 40596d85f56..53006c8e094 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -5829,7 +5829,7 @@ ER_CANT_CHANGE_TX_ISOLATION 25001
 ER_DUP_ENTRY_AUTOINCREMENT_CASE
         eng "ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '%-.64s' for key '%-.64s'"
 ER_EVENT_MODIFY_QUEUE_ERROR
-        eng "Internal scheduler error %d"
+        eng "Error during loading event from disk. mysql.event damaged?"
 ER_EVENT_SET_VAR_ERROR
         eng "Error during starting/stopping of the scheduler."
 ER_PARTITION_MERGE_ERROR
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index a4987080b02..4276018d496 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3886,8 +3886,12 @@ mysql_execute_command(THD *thd)
     else
     {
       uint affected= 1;
-      if (!(res= Events::get_instance()->
-                  drop_event(thd, lex->spname, lex->drop_if_exists, &affected)))
+      if (!(res= Events::get_instance()->drop_event(thd,
+                                                    lex->spname->m_db,
+                                                    lex->spname->m_name,
+                                                    lex->drop_if_exists,
+                                                    &affected,
+                                                    FALSE)))
         send_ok(thd, affected);     
     }
     break;
-- 
2.30.9