Merge ahristov@bk-internal.mysql.com:/home/bk/mysql-5.1-wl3337

into  example.com:/work/mysql-5.1-runtime-wl3337


BitKeeper/etc/ignore:
  auto-union
client/mysqltest.c:
  Auto merged
libmysqld/Makefile.am:
  Auto merged
mysql-test/mysql-test-run.pl:
  Auto merged
mysql-test/r/sp_notembedded.result:
  Auto merged
sql/CMakeLists.txt:
  Auto merged
sql/Makefile.am:
  Auto merged
sql/mysqld.cc:
  Auto merged
sql/set_var.cc:
  Auto merged
sql/sp_head.cc:
  Auto merged
sql/sql_class.cc:
  Auto merged
sql/sql_class.h:
  Auto merged
sql/sql_db.cc:
  Auto merged
sql/sql_lex.cc:
  Auto merged
sql/sql_lex.h:
  Auto merged
sql/sql_parse.cc:
  Auto merged
sql/sql_show.cc:
  Auto merged
sql/share/errmsg.txt:
  C
mysql-test/r/events_bugs.result:
  update result
  manual merge
mysql-test/r/ps_1general.result:
  update result
  manual merge
sql/sql_yacc.yy:
  manual merge
This commit is contained in:
unknown 2006-08-14 15:26:59 +02:00
commit 66fb56f115
53 changed files with 5855 additions and 4824 deletions

1107
.bzrignore

File diff suppressed because it is too large Load Diff

View File

@ -155,6 +155,7 @@ static my_bool ps_protocol= 0, ps_protocol_enabled= 0;
static my_bool sp_protocol= 0, sp_protocol_enabled= 0;
static my_bool view_protocol= 0, view_protocol_enabled= 0;
static my_bool cursor_protocol= 0, cursor_protocol_enabled= 0;
static my_bool opt_valgrind_test= 0;
static int parsing_disabled= 0;
static char **default_argv;
@ -3286,6 +3287,8 @@ static struct my_option my_long_options[] =
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"user", 'u', "User for login.", (gptr*) &user, (gptr*) &user, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"valgrind", 'N', "Define VALGRIND_TEST to 1.", (gptr*) &opt_valgrind_test,
(gptr*) &opt_valgrind_test, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"verbose", 'v', "Write more.", (gptr*) &verbose, (gptr*) &verbose, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"version", 'V', "Output version information and exit.",
@ -5060,6 +5063,9 @@ static void init_var_hash(MYSQL *mysql)
die("Variable hash initialization failed");
my_hash_insert(&var_hash, (byte*) var_init(0,"BIG_TEST", 0,
(opt_big_test) ? "1" : "0", 0));
my_hash_insert(&var_hash, (byte*) var_init(0,"VALGRIND_TEST", 0,
(opt_valgrind_test) ? "1" : "0",
0));
v= var_init(0,"MAX_TABLES", 0, (sizeof(ulong) == 4) ? "31" : "62",0);
my_hash_insert(&var_hash, (byte*) v);
v= var_init(0,"SERVER_VERSION", 0, mysql_get_server_info(mysql), 0);

View File

@ -68,7 +68,8 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
spatial.cc gstream.cc sql_help.cc tztime.cc sql_cursor.cc \
sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \
parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
event_scheduler.cc events.cc event_timed.cc \
event_scheduler.cc events.cc event_data_objects.cc \
event_queue.cc event_db_repository.cc \
rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
sql_tablespace.cc \
rpl_injector.cc my_user.c partition_info.cc

View File

@ -0,0 +1,4 @@
--require r/not_valgrind.require
--disable_query_log
eval select $VALGRIND_TEST as using_valgrind;
--enable_query_log

View File

@ -3873,6 +3873,11 @@ sub run_mysqltest ($) {
mtr_add_arg($args, "--big-test");
}
if ( $opt_valgrind )
{
mtr_add_arg($args, "--valgrind");
}
if ( $opt_compress )
{
mtr_add_arg($args, "--compress");

View File

@ -85,13 +85,24 @@ SHOW EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
events_test event_starts_test root@localhost RECURRING NULL 20 SECOND # # ENABLED
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
begin
alter event e_43 on schedule every 5 minute;
insert into test_nested values(1);
end|
set global event_scheduler = 1;
select db, name, body, status, interval_field, interval_value from mysql.event;
db name body status interval_field interval_value
events_test e_43 set @a = 4 ENABLED SECOND 1
events_test e_43 begin
alter event e_43 on schedule every 5 minute;
insert into test_nested values(1);
end ENABLED MINUTE 5
drop event e_43;
drop table test_nested;
"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);
@ -100,7 +111,15 @@ a
800219
drop event non_qualif_ev;
drop table non_qualif;
alter event non_existant rename to non_existant_too;
ERROR HY000: Unknown event 'non_existant'
set global event_scheduler = 2;
create event existant on schedule at now() + interval 1 year do select 12;
alter event non_existant rename to existant;
ERROR HY000: Event 'existant' already exists
alter event existant rename to events_test.existant;
ERROR HY000: Same old and new event name
drop event existant;
create table t_event3 (a int, b float);
drop event if exists event3;
Warnings:
@ -195,6 +214,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;
@ -285,9 +308,9 @@ select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_comp
db name body definer convert_tz(execute_at, 'UTC', 'SYSTEM') on_completion
events_test e_26 set @a = 5 root@localhost 2017-01-01 00:00:00 DROP
drop event e_26;
create event e_26 on schedule at NULL disabled do set @a = 5;
create event e_26 on schedule at NULL disable do set @a = 5;
ERROR HY000: Incorrect AT value: 'NULL'
create event e_26 on schedule at 'definitely not a datetime' disabled do set @a = 5;
create event e_26 on schedule at 'definitely not a datetime' disable do set @a = 5;
ERROR HY000: Incorrect AT value: 'definitely not a datetime'
set names utf8;
create event задачка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1;
@ -311,7 +334,6 @@ root@localhost закачка events_test
"Should be only 1 process"
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 Suspended NULL
select release_lock("test_lock1");
release_lock("test_lock1")
1
@ -331,7 +353,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 Sleeping 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."
@ -347,18 +369,17 @@ 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 Sleeping 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:"
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 Suspended NULL
root localhost events_test Connect User lock select get_lock("test_lock2_1", 20)
drop event закачка21;
create table t_16 (s1 int);
create trigger t_16_bi before insert on t_16 for each row create event e_16 on schedule every 1 second do set @a=5;
ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
ERROR HY000: Recursivity of EVENT DDL statements is forbidden when body is present
drop table t_16;
create event white_space
on schedule every 10 hour

View File

@ -5,10 +5,10 @@ CREATE EVENT Lower_case ON SCHEDULE EVERY 2 MINUTE DO SELECT 2;
ERROR HY000: Event 'Lower_case' already exists
DROP EVENT Lower_case;
SET NAMES cp1251;
CREATE EVENT äîëåí_ðåãèñòúð_1251 ON SCHEDULE EVERY 1 YEAR DO SELECT 100;
CREATE EVENT ÄîËåÍ_ðåãèñòúð_1251 ON SCHEDULE EVERY 2 YEAR DO SELECT 200;
CREATE EVENT äîëåí_ðåãèñòúð_1251 ON SCHEDULE EVERY 1 YEAR DO SELECT 100;
CREATE EVENT ÄîËåÍ_ðåãèñòúð_1251 ON SCHEDULE EVERY 2 YEAR DO SELECT 200;
ERROR HY000: Event 'ДоЛеН_регистър_1251' already exists
DROP EVENT ÄîËåÍ_ðåãèñòúð_1251;
DROP EVENT ÄîËåÍ_ðåãèñòúð_1251;
SET NAMES utf8;
CREATE EVENT долен_регистър_утф8 ON SCHEDULE EVERY 3 YEAR DO SELECT 300;
CREATE EVENT ДОЛЕН_регистър_утф8 ON SCHEDULE EVERY 4 YEAR DO SELECT 400;
@ -17,26 +17,26 @@ DROP EVENT ДОЛЕН_регистър_утф8;
SET NAMES latin1;
set @a=3;
CREATE PROCEDURE p_16 () CREATE EVENT e_16 ON SCHEDULE EVERY @a SECOND DO SET @a=5;
call p_16();
"Here we used to crash!"
call p_16();
ERROR HY000: Event 'e_16' already exists
call p_16();
ERROR HY000: Event 'e_16' already exists
DROP EVENT e_16;
CALL p_16();
CALL p_16();
ERROR HY000: Event 'e_16' already exists
DROP PROCEDURE p_16;
DROP EVENT e_16;
ERROR HY000: Recursivity of EVENT DDL statements is forbidden when body is present
create event e_55 on schedule at 99990101000000 do drop table t;
ERROR HY000: Incorrect AT value: '99990101000000'
create event e_55 on schedule every 10 hour starts 99990101000000 do drop table t;
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;
@ -50,10 +50,10 @@ select get_lock('test_bug16407', 60);
drop table "hashed_num";
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 Sleeping NULL
root localhost events_test Connect User lock select get_lock('test_bug16407', 60)
select /*1*/ user, host, db, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
user host db info
event_scheduler localhost NULL NULL
root localhost events_test select get_lock('test_bug16407', 60)
select release_lock('test_bug16407');
release_lock('test_bug16407')
1
@ -68,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;
@ -75,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')|
@ -83,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|
@ -91,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;
@ -98,23 +106,18 @@ 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 Sleeping NULL
root localhost events_test Connect User lock select get_lock('ee_16407_2', 60)
root localhost events_test Connect User lock select get_lock('ee_16407_2', 60)
root localhost events_test Connect User lock select get_lock('ee_16407_2', 60)
select /*2*/ user, host, db, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
user host db info
event_scheduler localhost NULL NULL
root localhost events_test select get_lock('ee_16407_2', 60) /*ee_16407_2*/
root localhost events_test select get_lock('ee_16407_2', 60) /*ee_16407_3*/
root localhost events_test select get_lock('ee_16407_2', 60) /*ee_16407_4*/
select release_lock('ee_16407_2');
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 Sleeping NULL
select /*3*/ user, host, db, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
user host db info
event_scheduler localhost NULL NULL
set global event_scheduler= 2;
select * from events_smode_test order by ev_name, a;
ev_name a
@ -132,37 +135,39 @@ 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 Sleeping NULL
root localhost events_test Connect User lock select get_lock('ee_16407_5', 60)
root localhost events_test Connect User lock select get_lock('ee_16407_5', 60)
select /*4*/ user, host, db, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
user host db info
event_scheduler localhost NULL NULL
root localhost events_test select get_lock('ee_16407_5', 60) /*ee_16407_5*/
root localhost events_test select get_lock('ee_16407_5', 60) /*ee_16407_6*/
select release_lock('ee_16407_5');
release_lock('ee_16407_5')
1
"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 Sleeping NULL
select /*5*/ user, host, db, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
user host db info
event_scheduler localhost NULL NULL
select * from events_smode_test order by ev_name, a;
ev_name a
ee_16407_6 2004-02-29
@ -201,4 +206,12 @@ events_test mysqltest_user1 mysqltest_user1@localhost RECURRING ENABLED
drop event events_test.mysqltest_user1;
drop user mysqltest_user1@localhost;
drop database mysqltest_db1;
create event e_53 on schedule at (select s1 from ttx) 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 'select s1 from ttx) do drop table t' at line 1
create event e_53 on schedule every (select s1 from ttx) second 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 'select s1 from ttx) second do drop table t' at line 1
create event e_53 on schedule every 5 second starts (select s1 from ttx) 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 'select s1 from ttx) do drop table t' at line 1
create event e_53 on schedule every 5 second ends (select s1 from ttx) 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 'select s1 from ttx) do drop table t' at line 1
drop database events_test;

View File

@ -1,5 +1,5 @@
create database if not exists events_test;
use events_test;
CREATE DATABASE IF NOT EXISTS events_test;
USE events_test;
"We use procedure here because its statements won't be logged into the general log"
"If we had used normal select that are logged in different ways depending on whether"
"the test suite is run in normal mode or with --ps-protocol"
@ -8,18 +8,21 @@ BEGIN
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;
TRUNCATE mysql.general_log;
"1 row, the current statement!"
call select_general_log();
CALL select_general_log();
user_host argument
USER_HOST CREATE procedure select_general_log()
BEGIN
SELECT user_host, argument FROM mysql.general_log WHERE argument LIKE '%alabala%';
END
SET GLOBAL event_scheduler=1;
TRUNCATE mysql.general_log;
CREATE EVENT log_general ON SCHEDULE EVERY 1 MINUTE DO SELECT 'alabala', SLEEP(1) FROM DUAL;
"Wait the scheduler to start"
"Should see 3 rows - the 'SELect' is in the middle. The other two are selects from general_log"
call select_general_log();
"Should see 2 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 CREATE EVENT log_general ON SCHEDULE EVERY 1 MINUTE DO SELECT 'alabala', SLEEP(1) FROM DUAL
USER_HOST SELECT 'alabala', SLEEP(1) FROM DUAL
DROP PROCEDURE select_general_log;
DROP EVENT log_general;
SET GLOBAL event_scheduler=2;
@ -52,10 +55,11 @@ TRUNCATE mysql.slow_log;
CREATE TABLE slow_event_test (slo_val tinyint, val tinyint);
SET SESSION long_query_time=1;
"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 +68,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"
@ -89,4 +93,4 @@ TRUNCATE mysql.slow_log;
DROP TABLE slow_event_test;
SET GLOBAL long_query_time =@old_global_long_query_time;
SET SESSION long_query_time =@old_session_long_query_time;
drop database events_test;
DROP DATABASE events_test;

View File

@ -0,0 +1,10 @@
create database if not exists mysqltest_events_test;
use mysqltest_events_test;
set global event_scheduler=2;
create table execution_log(name char(10));
create event abc1 on schedule every 1 second do insert into execution_log value('abc1');
create event abc2 on schedule every 1 second do insert into execution_log value('abc2');
create event abc3 on schedule every 1 second do insert into execution_log value('abc3');
insert into mysql.event values ('db1','bad','select 42','root@localhost',NULL,1000,'MICROSECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment1');
insert into mysql.event values ('db1','bad2','sect','root@localhost',NULL,1000,'SECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment2');
"Now we restart the server"

View File

@ -0,0 +1,6 @@
use mysqltest_events_test;
"Should get 0 rows because the queue aborted run
select distinct name from execution_log order by name;
name
delete from mysql.event where name like 'bad%';
"Now restart the server again"

View File

@ -0,0 +1,9 @@
use mysqltest_events_test;
"Should get 3 rows : abc1, abc2, abc3
select distinct name from execution_log order by name;
name
drop event abc1;
drop event abc2;
drop event abc3;
drop table execution_log;
drop database mysqltest_events_test;

View File

@ -6,7 +6,6 @@ CREATE TABLE table_3(a int);
CREATE TABLE table_4(a int);
CREATE TABLE T19170(s1 TIMESTAMP);
SET GLOBAL event_scheduler=1;
CREATE EVENT E19170 ON SCHEDULE EVERY 2 SECOND DO INSERT INTO T19170 VALUES(CURRENT_TIMESTAMP);
CREATE EVENT two_sec ON SCHEDULE EVERY 2 SECOND DO INSERT INTO table_1 VALUES(1);
CREATE EVENT start_n_end
ON SCHEDULE EVERY 1 SECOND
@ -39,17 +38,12 @@ 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
DROP EVENT two_time;
DROP TABLE table_1;
DROP TABLE table_2;
DROP TABLE table_3;
DROP TABLE table_4;
"Checking for multiple executions in one second, should not happen -> 0 as result"
SELECT COUNT(*) FROM (SELECT s1, COUNT(*) AS cnt FROM T19170 GROUP BY s1) AS tmp WHERE tmp.cnt > 1;
COUNT(*)
0
DROP DATABASE events_test;

View File

@ -1,6 +1,5 @@
prepare stmt1 from ' show full processlist ';
execute stmt1;
Id User Host db Command Time State Info
number event_scheduler localhost NULL Connect time Suspended NULL
number root localhost test Query time NULL show full processlist
deallocate prepare stmt1;

View File

@ -0,0 +1,2 @@
using_valgrind
0

View File

@ -10,6 +10,5 @@ user()
#
show processlist;
Id User Host db Command Time State Info
<id> event_scheduler <host> NULL <command> <time> <state> <info>
<id> root <host> test <command> <time> <state> <info>
<id> root <host> test <command> <time> <state> <info>

View File

@ -34,7 +34,6 @@ lock tables t2 write;
call bug9486();
show processlist;
Id User Host db Command Time State Info
# event_scheduler localhost NULL Connect # Suspended NULL
# root localhost test Sleep # NULL
# root localhost test Query # Locked update t1, t2 set val= 1 where id1=id2
# root localhost test Query # NULL show processlist

View File

@ -18,11 +18,9 @@ show processlist;
end|
call bug4902_2()|
Id User Host db Command Time State Info
# event_scheduler localhost NULL Connect # Suspended NULL
# root localhost test Query # NULL show processlist
call bug4902_2()|
Id User Host db Command Time State Info
# event_scheduler localhost NULL Connect # Suspended NULL
# root localhost test Query # NULL show processlist
drop procedure bug4902_2|
drop table if exists t1|

View File

@ -52,22 +52,22 @@ drop table t1;
FLUSH STATUS;
SHOW STATUS LIKE 'max_used_connections';
Variable_name Value
Max_used_connections 2
Max_used_connections 1
SET @save_thread_cache_size=@@thread_cache_size;
SET GLOBAL thread_cache_size=3;
SHOW STATUS LIKE 'max_used_connections';
Variable_name Value
Max_used_connections 4
Max_used_connections 3
FLUSH STATUS;
SHOW STATUS LIKE 'max_used_connections';
Variable_name Value
Max_used_connections 2
SHOW STATUS LIKE 'max_used_connections';
Variable_name Value
Max_used_connections 3
SHOW STATUS LIKE 'max_used_connections';
Variable_name Value
Max_used_connections 4
SHOW STATUS LIKE 'max_used_connections';
Variable_name Value
Max_used_connections 5
SET GLOBAL thread_cache_size=@save_thread_cache_size;
show status like 'com_show_status';
Variable_name Value

View File

@ -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 1.2
SHOW DATABASES LIKE 'db_x';
SHOW TABLES FROM db_x;
SET GLOBAL event_scheduler=2;
@ -81,23 +81,42 @@ SHOW EVENTS;
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;
--sleep 2
--error 1562
alter event e_43 do alter event e_43 do set @a = 4;
--sleep 2
delimiter |;
alter event e_43 do
begin
alter event e_43 on schedule every 5 minute;
insert into test_nested values(1);
end|
delimiter ;|
set global event_scheduler = 1;
--sleep 3
select db, name, body, status, interval_field, interval_value from mysql.event;
drop event e_43;
--sleep 1
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 1.1
select * from non_qualif;
drop event non_qualif_ev;
drop table non_qualif;
--error ER_EVENT_DOES_NOT_EXIST
alter event non_existant rename to non_existant_too;
set global event_scheduler = 2;
create event existant on schedule at now() + interval 1 year do select 12;
--error ER_EVENT_ALREADY_EXISTS
alter event non_existant rename to existant;
--error ER_EVENT_SAME_NAME
alter event existant rename to events_test.existant;
drop event existant;
create table t_event3 (a int, b float);
drop event if exists event3;
@ -156,6 +175,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;
@ -201,34 +224,34 @@ SHOW EVENTS;
CREATE TABLE event_like LIKE mysql.event;
INSERT INTO event_like SELECT * FROM mysql.event;
#sleep a bit or we won't catch the change of time
--sleep 1
--sleep 1.1
ALTER TABLE mysql.event MODIFY db char(64) character set cp1251 default '';
--error ER_CANNOT_LOAD_FROM_TABLE
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
ALTER TABLE mysql.event MODIFY db char(20) character set utf8 collate utf8_bin default '';
#wait a bit or we won't see the difference because of seconds resolution
--sleep 1
--sleep 1.1
SHOW CREATE TABLE mysql.event;
--error ER_CANNOT_LOAD_FROM_TABLE
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
--sleep 1
--sleep 1.1
ALTER TABLE mysql.event MODIFY db char(64) character set utf8 collate utf8_bin default '';
--sleep 1
--sleep 1.1
--echo "This should work"
--replace_column 8 # 9 #
SHOW EVENTS;
--sleep 1
--sleep 1.1
ALTER TABLE mysql.event MODIFY db char(64) character set cp1251 default '';
--error ER_CANNOT_LOAD_FROM_TABLE
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
--sleep 1
--sleep 1.1
ALTER TABLE mysql.event MODIFY db varchar(64) character set utf8 collate utf8_bin default '';
--sleep 1
--sleep 1.1
--error ER_CANNOT_LOAD_FROM_TABLE
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
--sleep 1
--sleep 1.1
ALTER TABLE mysql.event DROP comment, DROP starts;
--sleep 1
--sleep 1.1
--error ER_COL_COUNT_DOESNT_MATCH_CORRUPTED
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
DROP TABLE mysql.event;
@ -246,9 +269,9 @@ create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5;
select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event;
drop event e_26;
--error ER_WRONG_VALUE
create event e_26 on schedule at NULL disabled do set @a = 5;
create event e_26 on schedule at NULL disable do set @a = 5;
--error ER_WRONG_VALUE
create event e_26 on schedule at 'definitely not a datetime' disabled do set @a = 5;
create event e_26 on schedule at 'definitely not a datetime' disable do set @a = 5;
set names utf8;
create event задачка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1;
@ -307,6 +330,7 @@ create event закачка21 on schedule every 10 hour do select get_lock("test
--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.8
--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;
@ -315,7 +339,7 @@ drop event закачка21;
# Bug #16410 Events: CREATE EVENT is legal in a CREATE TRIGGER statement
#
create table t_16 (s1 int);
--error 1422
--error 1562
create trigger t_16_bi before insert on t_16 for each row create event e_16 on schedule every 1 second do set @a=5;
drop table t_16;
#

View File

@ -30,19 +30,8 @@ SET NAMES latin1;
# START - BUG#16408: Events: crash for an event in a procedure
#
set @a=3;
--error 1562
CREATE PROCEDURE p_16 () CREATE EVENT e_16 ON SCHEDULE EVERY @a SECOND DO SET @a=5;
call p_16();
--echo "Here we used to crash!"
--error ER_EVENT_ALREADY_EXISTS
call p_16();
--error ER_EVENT_ALREADY_EXISTS
call p_16();
DROP EVENT e_16;
CALL p_16();
--error ER_EVENT_ALREADY_EXISTS
CALL p_16();
DROP PROCEDURE p_16;
DROP EVENT e_16;
#
# END - BUG#16408: Events: crash for an event in a procedure
#
@ -56,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
#
@ -64,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;
@ -78,11 +78,13 @@ begin
drop table "hashed_num";
end|
delimiter ;|
--sleep 1
--sleep 0.8
--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 /*1*/ user, host, db, 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';
@ -90,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;
@ -98,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
@ -106,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|
@ -114,18 +122,16 @@ 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
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 /*2*/ user, host, db, 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
select /*3*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
--sleep 1.2
select /*3*/ user, host, db, 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;
--echo "OK, last check before we drop them"
@ -137,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|
@ -144,24 +155,23 @@ 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
--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 /*4*/ user, host, db, 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 1.3
--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 /*5*/ user, host, db, 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;
--echo "And here we check one more time before we drop the events"
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
@ -209,4 +219,19 @@ drop database mysqltest_db1;
# END - 18897: Events: unauthorized action possible with alter event rename
#
#
# START - BUG#16394: Events: Crash if schedule contains SELECT
#
--error ER_PARSE_ERROR
create event e_53 on schedule at (select s1 from ttx) do drop table t;
--error ER_PARSE_ERROR
create event e_53 on schedule every (select s1 from ttx) second do drop table t;
--error ER_PARSE_ERROR
create event e_53 on schedule every 5 second starts (select s1 from ttx) do drop table t;
--error ER_PARSE_ERROR
create event e_53 on schedule every 5 second ends (select s1 from ttx) do drop table t;
#
# END - BUG#16394: Events: Crash if schedule contains SELECT
#
drop database events_test;

View File

@ -1,8 +1,8 @@
# Can't test with embedded server that doesn't support grants
-- source include/not_embedded.inc
create database if not exists events_test;
use events_test;
CREATE DATABASE IF NOT EXISTS events_test;
USE events_test;
--echo "We use procedure here because its statements won't be logged into the general log"
--echo "If we had used normal select that are logged in different ways depending on whether"
--echo "the test suite is run in normal mode or with --ps-protocol"
@ -13,22 +13,19 @@ BEGIN
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;
TRUNCATE mysql.general_log;
--echo "1 row, the current statement!"
--replace_column 1 USER_HOST
call select_general_log();
CALL select_general_log();
SET GLOBAL event_scheduler=1;
TRUNCATE mysql.general_log;
CREATE EVENT log_general ON SCHEDULE EVERY 1 MINUTE DO SELECT 'alabala', SLEEP(1) FROM DUAL;
--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 1.5
--echo "Should see 2 rows - the 'SELECT' is in the middle. The other two are selects from general_log"
--replace_column 1 USER_HOST
call select_general_log();
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
@ -72,15 +69,16 @@ TRUNCATE mysql.slow_log;
CREATE TABLE slow_event_test (slo_val tinyint, val tinyint);
SET SESSION long_query_time=1;
--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 +86,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"
@ -102,4 +100,4 @@ DROP TABLE slow_event_test;
SET GLOBAL long_query_time =@old_global_long_query_time;
SET SESSION long_query_time =@old_session_long_query_time;
drop database events_test;
DROP DATABASE events_test;

View File

@ -0,0 +1,17 @@
# Can't test with embedded server that doesn't support grants
-- source include/not_embedded.inc
--disable_warnings
create database if not exists mysqltest_events_test;
--enable_warnings
use mysqltest_events_test;
set global event_scheduler=2;
create table execution_log(name char(10));
create event abc1 on schedule every 1 second do insert into execution_log value('abc1');
create event abc2 on schedule every 1 second do insert into execution_log value('abc2');
create event abc3 on schedule every 1 second do insert into execution_log value('abc3');
insert into mysql.event values ('db1','bad','select 42','root@localhost',NULL,1000,'MICROSECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment1');
insert into mysql.event values ('db1','bad2','sect','root@localhost',NULL,1000,'SECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment2');
--echo "Now we restart the server"

View File

@ -0,0 +1 @@
--event-scheduler=1

View File

@ -0,0 +1,9 @@
# Can't test with embedded server that doesn't support grants
-- source include/not_embedded.inc
use mysqltest_events_test;
--sleep 1.5
--echo "Should get 0 rows because the queue aborted run
select distinct name from execution_log order by name;
delete from mysql.event where name like 'bad%';
--echo "Now restart the server again"

View File

@ -0,0 +1 @@
--event-scheduler=1

View File

@ -0,0 +1,14 @@
# Can't test with embedded server that doesn't support grants
-- source include/not_embedded.inc
use mysqltest_events_test;
--sleep 2
--echo "Should get 3 rows : abc1, abc2, abc3
select distinct name from execution_log order by name;
drop event abc1;
drop event abc2;
drop event abc3;
drop table execution_log;
drop database mysqltest_events_test;

View File

@ -1,5 +1,6 @@
# Can't test with embedded server that doesn't support grants
-- source include/not_embedded.inc
-- source include/not_valgrind.inc
CREATE DATABASE IF NOT EXISTS events_test;
USE events_test;
@ -11,7 +12,6 @@ CREATE TABLE T19170(s1 TIMESTAMP);
SET GLOBAL event_scheduler=1;
# We need to have 2 to make it safe with valgrind. This is probably because
# of when we calculate the timestamp value
CREATE EVENT E19170 ON SCHEDULE EVERY 2 SECOND DO INSERT INTO T19170 VALUES(CURRENT_TIMESTAMP);
CREATE EVENT two_sec ON SCHEDULE EVERY 2 SECOND DO INSERT INTO table_1 VALUES(1);
CREATE EVENT start_n_end
ON SCHEDULE EVERY 1 SECOND
@ -34,12 +34,10 @@ 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;
DROP TABLE table_3;
DROP TABLE table_4;
--echo "Checking for multiple executions in one second, should not happen -> 0 as result"
SELECT COUNT(*) FROM (SELECT s1, COUNT(*) AS cnt FROM T19170 GROUP BY s1) AS tmp WHERE tmp.cnt > 1;
DROP DATABASE events_test;

View File

@ -62,7 +62,7 @@ while ($1)
--enable_query_log
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
SET GLOBAL event_scheduler=1;
--sleep 6
--sleep 2.5
DROP DATABASE events_conn1_test2;
SET GLOBAL event_scheduler=2;
@ -101,7 +101,7 @@ while ($1)
}
--enable_query_log
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
--sleep 6
--sleep 2.5
connection conn2;
--send
DROP DATABASE events_conn2_db;

View File

@ -51,7 +51,8 @@ ADD_EXECUTABLE(mysqld ../sql-common/client.c derror.cc des_key_file.cc
sql_table.cc sql_test.cc sql_trigger.cc sql_udf.cc sql_union.cc
sql_update.cc sql_view.cc strfunc.cc table.cc thr_malloc.cc
time.cc tztime.cc uniques.cc unireg.cc item_xmlfunc.cc
rpl_tblmap.cc sql_binlog.cc event_scheduler.cc event_timed.cc
rpl_tblmap.cc sql_binlog.cc event_scheduler.cc event_data_objects.cc
event_queue.cc event_db_repository.cc
sql_tablespace.cc events.cc ../sql-common/my_user.c
partition_info.cc rpl_injector.cc sql_locale.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc

View File

@ -64,8 +64,9 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
tztime.h my_decimal.h\
sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \
parse_file.h sql_view.h sql_trigger.h \
sql_array.h sql_cursor.h events.h events_priv.h \
sql_plugin.h authors.h sql_partition.h event_timed.h \
sql_array.h sql_cursor.h events.h \
event_db_repository.h event_queue.h \
sql_plugin.h authors.h sql_partition.h event_data_objects.h \
partition_info.h partition_element.h event_scheduler.h \
contributors.h
mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
@ -104,7 +105,8 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
tztime.cc my_time.c my_user.c my_decimal.cc\
sp_head.cc sp_pcontext.cc sp_rcontext.cc sp.cc \
sp_cache.cc parse_file.cc sql_trigger.cc \
event_scheduler.cc events.cc event_timed.cc \
event_scheduler.cc events.cc event_data_objects.cc \
event_queue.cc event_db_repository.cc \
sql_plugin.cc sql_binlog.cc \
sql_builtin.cc sql_tablespace.cc partition_info.cc

File diff suppressed because it is too large Load Diff

285
sql/event_data_objects.h Normal file
View File

@ -0,0 +1,285 @@
#ifndef _EVENT_DATA_OBJECTS_H_
#define _EVENT_DATA_OBJECTS_H_
/* Copyright (C) 2004-2006 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define EVEX_GET_FIELD_FAILED -2
#define EVEX_COMPILE_ERROR -3
#define EVEX_GENERAL_ERROR -4
#define EVEX_BAD_PARAMS -5
#define EVEX_MICROSECOND_UNSUP -6
class sp_head;
class Sql_alloc;
class Event_basic
{
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;
public:
enum enum_status
{
ENABLED = 1,
DISABLED
};
enum enum_on_completion
{
ON_COMPLETION_DROP = 1,
ON_COMPLETION_PRESERVE
};
enum enum_on_completion on_completion;
enum enum_status status;
TIME last_executed;
TIME execute_at;
TIME starts;
TIME ends;
my_bool starts_null;
my_bool ends_null;
my_bool execute_at_null;
longlong expression;
interval_type interval;
bool dropped;
uint execution_count;
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_queue_element::new(size)");
p= my_malloc(size, MYF(0));
DBUG_PRINT("info", ("alloc_ptr=0x%lx", p));
DBUG_RETURN(p);
}
static void operator delete(void *ptr, size_t 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;
}
};
class Event_timed : public Event_queue_element
{
Event_timed(const Event_timed &); /* Prevent use of these */
void operator=(Event_timed &);
public:
LEX_STRING body;
LEX_STRING definer_user;
LEX_STRING definer_host;
LEX_STRING comment;
ulonglong created;
ulonglong modified;
ulong sql_mode;
Event_timed();
virtual ~Event_timed();
void
init();
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;
uint execution_count;
Event_job_data();
virtual ~Event_job_data();
virtual int
load_from_row(TABLE *table);
int
execute(THD *thd);
int
compile(THD *thd, MEM_ROOT *mem_root);
private:
int
get_fake_create_event(THD *thd, String *buf);
Event_job_data(const Event_job_data &); /* Prevent use of these */
void operator=(Event_job_data &);
};
class Event_parse_data : public Sql_alloc
{
public:
enum enum_status
{
ENABLED = 1,
DISABLED
};
enum enum_on_completion
{
ON_COMPLETION_DROP = 1,
ON_COMPLETION_PRESERVE
};
enum enum_on_completion on_completion;
enum enum_status status;
const uchar *body_begin;
LEX_STRING dbname;
LEX_STRING name;
LEX_STRING definer;// combination of user and host
LEX_STRING body;
LEX_STRING comment;
Item* item_starts;
Item* item_ends;
Item* item_execute_at;
TIME starts;
TIME ends;
TIME execute_at;
my_bool starts_null;
my_bool ends_null;
my_bool execute_at_null;
sp_name *identifier;
Item* item_expression;
longlong expression;
interval_type interval;
static Event_parse_data *
new_instance(THD *thd);
bool
check_parse_data(THD *);
void
init_body(THD *thd);
private:
void
init_definer(THD *thd);
void
init_name(THD *thd, sp_name *spn);
int
init_execute_at(THD *thd);
int
init_interval(THD *thd);
int
init_starts(THD *thd);
int
init_ends(THD *thd);
Event_parse_data();
~Event_parse_data();
void
report_bad_value(const char *item_name, Item *bad_item);
Event_parse_data(const Event_parse_data &); /* Prevent use of these */
void operator=(Event_parse_data &);
};
/* Compares only the schema part of the identifier */
bool
event_basic_db_equal(LEX_STRING db, Event_basic *et);
/* Compares the whole identifier*/
bool
event_basic_identifier_equal(LEX_STRING db, LEX_STRING name, Event_basic *b);
#endif /* _EVENT_DATA_OBJECTS_H_ */

1004
sql/event_db_repository.cc Normal file

File diff suppressed because it is too large Load Diff

108
sql/event_db_repository.h Normal file
View File

@ -0,0 +1,108 @@
#ifndef _EVENT_DB_REPOSITORY_H_
#define _EVENT_DB_REPOSITORY_H_
/* Copyright (C) 2004-2006 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define EVEX_OPEN_TABLE_FAILED -1
enum enum_events_table_field
{
ET_FIELD_DB = 0,
ET_FIELD_NAME,
ET_FIELD_BODY,
ET_FIELD_DEFINER,
ET_FIELD_EXECUTE_AT,
ET_FIELD_INTERVAL_EXPR,
ET_FIELD_TRANSIENT_INTERVAL,
ET_FIELD_CREATED,
ET_FIELD_MODIFIED,
ET_FIELD_LAST_EXECUTED,
ET_FIELD_STARTS,
ET_FIELD_ENDS,
ET_FIELD_STATUS,
ET_FIELD_ON_COMPLETION,
ET_FIELD_SQL_MODE,
ET_FIELD_COMMENT,
ET_FIELD_COUNT /* a cool trick to count the number of fields :) */
};
int
events_table_index_read_for_db(THD *thd, TABLE *schema_table,
TABLE *event_table);
int
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_basic;
class Event_parse_data;
class Event_db_repository
{
public:
Event_db_repository(){}
int
create_event(THD *thd, Event_parse_data *parse_data, my_bool create_if_not,
uint *rows_affected);
bool
update_event(THD *thd, Event_parse_data *parse_data, LEX_STRING *new_dbname,
LEX_STRING *new_name);
bool
drop_event(THD *thd, LEX_STRING db, LEX_STRING name, bool drop_if_exists,
uint *rows_affected);
int
drop_schema_events(THD *thd, LEX_STRING schema);
bool
find_named_event(THD *thd, LEX_STRING db, LEX_STRING name, TABLE *table);
bool
load_named_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_basic *et);
int
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
int
fill_schema_events(THD *thd, TABLE_LIST *tables, char *db);
private:
int
drop_events_by_field(THD *thd, enum enum_events_table_field field,
LEX_STRING field_value);
int
index_read_for_db_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table,
char *db);
int
table_scan_all_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table);
static bool
check_system_tables(THD *thd);
/* Prevent use of these */
Event_db_repository(const Event_db_repository &);
void operator=(Event_db_repository &);
};
#endif /* _EVENT_DB_REPOSITORY_H_ */

1084
sql/event_queue.cc Normal file

File diff suppressed because it is too large Load Diff

119
sql/event_queue.h Normal file
View File

@ -0,0 +1,119 @@
#ifndef _EVENT_QUEUE_H_
#define _EVENT_QUEUE_H_
/* Copyright (C) 2004-2006 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
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_basic;
class Event_db_repository;
class Event_job_data;
class Event_queue_element;
class THD;
class Event_scheduler;
class Event_queue
{
public:
Event_queue();
void
init_mutexes();
void
deinit_mutexes();
bool
init_queue(Event_db_repository *db_repo, Event_scheduler *sched);
void
deinit_queue();
/* Methods for queue management follow */
int
create_event(THD *thd, LEX_STRING dbname, LEX_STRING name);
int
update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
LEX_STRING *new_schema, LEX_STRING *new_name);
void
drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name);
void
drop_schema_events(THD *thd, LEX_STRING schema);
void
check_system_tables(THD *thd);
void
recalculate_activation_times(THD *thd);
bool
get_top_for_execution_if_time(THD *thd, time_t now, Event_job_data **job_data,
struct timespec *abstime);
bool
dump_internal_status(THD *thd);
int
load_events_from_db(THD *thd);
protected:
Event_queue_element *
find_n_remove_event(LEX_STRING db, LEX_STRING name);
void
drop_matching_events(THD *thd, LEX_STRING pattern,
bool (*)(LEX_STRING, Event_basic *));
void
empty_queue();
void
notify_observers();
void
dbug_dump_queue(time_t now);
/* LOCK_event_queue is the mutex which protects the access to the queue. */
pthread_mutex_t LOCK_event_queue;
Event_db_repository *db_repository;
Event_scheduler *scheduler;
/* The sorted queue with the Event_job_data objects */
QUEUE queue;
uint mutex_last_locked_at_line;
uint mutex_last_unlocked_at_line;
uint mutex_last_attempted_lock_at_line;
const char* mutex_last_locked_in_func;
const char* mutex_last_unlocked_in_func;
const char* mutex_last_attempted_lock_in_func;
bool mutex_queue_data_locked;
bool mutex_queue_data_attempting_lock;
/* helper functions for working with mutexes & conditionals */
void
lock_data(const char *func, uint line);
void
unlock_data(const char *func, uint line);
};
#endif /* _EVENT_QUEUE_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -16,225 +16,76 @@
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 THD;
typedef bool * (*event_timed_identifier_comparator)(Event_timed*, Event_timed*);
int
events_init();
class Event_queue;
class Event_job_data;
void
events_shutdown();
pre_init_event_thread(THD* thd);
bool
post_init_event_thread(THD* thd);
void
deinit_event_thread(THD *thd);
class Event_scheduler
{
public:
/* Return codes */
enum enum_error_code
{
OP_OK= 0,
OP_NOT_RUNNING,
OP_CANT_KILL,
OP_CANT_INIT,
OP_DISABLED_EVENT,
OP_LOAD_ERROR,
OP_ALREADY_EXISTS
};
Event_scheduler(){}
~Event_scheduler(){}
enum enum_state
{
UNINITIALIZED= 0,
INITIALIZED,
COMMENCING,
CANTSTART,
INITIALIZED = 0,
RUNNING,
SUSPENDED,
IN_SHUTDOWN
STOPPING
};
enum enum_suspend_or_resume
{
SUSPEND= 1,
RESUME= 2
};
/* Singleton access */
static Event_scheduler*
get_instance();
/* Methods for queue management follow */
enum enum_error_code
create_event(THD *thd, Event_timed *et, bool check_existence);
enum enum_error_code
update_event(THD *thd, Event_timed *et, LEX_STRING *new_schema,
LEX_STRING *new_name);
bool
drop_event(THD *thd, Event_timed *et);
int
drop_schema_events(THD *thd, LEX_STRING *schema);
int
drop_user_events(THD *thd, LEX_STRING *definer, uint *dropped_num)
{ DBUG_ASSERT(0); return 0;}
uint
events_count();
/* State changing methods follow */
bool
start();
enum enum_error_code
bool
stop();
bool
start_suspended();
/*
Need to be public because has to be called from the function
passed to pthread_create.
*/
bool
run(THD *thd);
enum enum_error_code
suspend_or_resume(enum enum_suspend_or_resume action);
bool
init();
void
init_scheduler(Event_queue *queue);
void
destroy();
deinit_scheduler();
static void
void
init_mutexes();
static void
destroy_mutexes();
void
report_error_during_start();
deinit_mutexes();
/* Information retrieving methods follow */
enum enum_state
get_state();
bool
initialized();
void
queue_changed();
static int
bool
dump_internal_status(THD *thd);
static bool
check_system_tables(THD *thd);
private:
Event_timed *
find_event(Event_timed *etn, bool remove_from_q);
uint
workers_count();
bool
is_running_or_suspended();
/* helper functions */
bool
execute_top(THD *thd);
void
clean_queue(THD *thd);
void
stop_all_running_events(THD *thd);
enum enum_error_code
load_named_event(THD *thd, Event_timed *etn, Event_timed **etn_new);
int
load_events_from_db(THD *thd);
void
drop_matching_events(THD *thd, LEX_STRING *pattern,
bool (*)(Event_timed *,LEX_STRING *));
bool
check_n_suspend_if_needed(THD *thd);
bool
check_n_wait_for_non_empty_queue(THD *thd);
/* Singleton DP is used */
Event_scheduler();
enum enum_cond_vars
{
COND_NONE= -1,
/*
COND_new_work is a conditional used to signal that there is a change
of the queue that should inform the executor thread that new event should
be executed sooner than previously expected, because of add/replace event.
*/
COND_new_work= 0,
/*
COND_started is a conditional used to synchronize the thread in which
::start() was called and the spawned thread. ::start() spawns a new thread
and then waits on COND_started but also checks when awaken that `state` is
either RUNNING or CANTSTART. Then it returns back.
*/
COND_started_or_stopped,
/*
Conditional used for signalling from the scheduler thread back to the
thread that calls ::suspend() or ::resume. Synchronizing the calls.
*/
COND_suspend_or_resume,
/* Must be always last */
COND_LAST
};
/* Singleton instance */
static Event_scheduler singleton;
/* This is the current status of the life-cycle of the manager. */
enum enum_state state;
/* Set to start the scheduler in suspended state */
bool start_scheduler_suspended;
/*
LOCK_scheduler_data is the mutex which protects the access to the
manager's queue as well as used when signalling COND_new_work,
COND_started and COND_shutdown.
*/
pthread_mutex_t LOCK_scheduler_data;
/*
Holds the thread id of the executor thread or 0 if the executor is not
running. It is used by ::shutdown() to know which thread to kill with
kill_one_thread(). The latter wake ups a thread if it is waiting on a
conditional variable and sets thd->killed to non-zero.
*/
ulong thread_id;
pthread_cond_t cond_vars[COND_LAST];
static const char * const cond_vars_names[COND_LAST];
/* The MEM_ROOT of the object */
MEM_ROOT scheduler_root;
/* The sorted queue with the Event_timed objects */
QUEUE queue;
uint mutex_last_locked_at_line;
uint mutex_last_unlocked_at_line;
const char* mutex_last_locked_in_func;
const char* mutex_last_unlocked_in_func;
enum enum_cond_vars cond_waiting_on;
bool mutex_scheduler_data_locked;
execute_top(THD *thd, Event_job_data *job_data);
/* helper functions for working with mutexes & conditionals */
void
@ -243,8 +94,35 @@ private:
void
unlock_data(const char *func, uint line);
int
cond_wait(enum enum_cond_vars, pthread_mutex_t *mutex);
void
cond_wait(THD *thd, struct timespec *abstime, const char* msg,
const char *func, uint line);
pthread_mutex_t LOCK_scheduler_state;
/* This is the current status of the life-cycle of the scheduler. */
enum enum_state state;
/*
Holds the thread id of the executor thread or 0 if the scheduler is not
running. It is used by ::shutdown() to know which thread to kill with
kill_one_thread(). The latter wake ups a thread if it is waiting on a
conditional variable and sets thd->killed to non-zero.
*/
ulong thread_id;
pthread_cond_t COND_state;
Event_queue *queue;
uint mutex_last_locked_at_line;
uint mutex_last_unlocked_at_line;
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 */

View File

@ -1,217 +0,0 @@
#ifndef _EVENT_TIMED_H_
#define _EVENT_TIMED_H_
/* Copyright (C) 2004-2006 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define EVEX_OK 0
#define EVEX_KEY_NOT_FOUND -1
#define EVEX_OPEN_TABLE_FAILED -2
#define EVEX_WRITE_ROW_FAILED -3
#define EVEX_DELETE_ROW_FAILED -4
#define EVEX_GET_FIELD_FAILED -5
#define EVEX_PARSE_ERROR -6
#define EVEX_INTERNAL_ERROR -7
#define EVEX_NO_DB_ERROR -8
#define EVEX_COMPILE_ERROR -19
#define EVEX_GENERAL_ERROR -20
#define EVEX_BAD_IDENTIFIER -21
#define EVEX_BODY_TOO_LONG -22
#define EVEX_BAD_PARAMS -23
#define EVEX_NOT_RUNNING -24
#define EVEX_MICROSECOND_UNSUP -25
#define EVEX_CANT_KILL -26
#define EVENT_EXEC_NO_MORE (1L << 0)
#define EVENT_NOT_USED (1L << 1)
#define EVENT_FREE_WHEN_FINISHED (1L << 2)
class sp_head;
class Event_timed
{
Event_timed(const Event_timed &); /* Prevent use of these */
void operator=(Event_timed &);
my_bool in_spawned_thread;
ulong locked_by_thread_id;
my_bool running;
ulong thread_id;
pthread_mutex_t LOCK_running;
pthread_cond_t COND_finished;
bool status_changed;
bool last_executed_changed;
public:
enum enum_status
{
ENABLED = 1,
DISABLED
};
enum enum_on_completion
{
ON_COMPLETION_DROP = 1,
ON_COMPLETION_PRESERVE
};
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;
my_bool starts_null;
my_bool ends_null;
my_bool execute_at_null;
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;
const uchar *body_begin;
bool dropped;
bool free_sphead_on_delete;
uint flags;//all kind of purposes
static void *operator new(size_t size)
{
void *p;
DBUG_ENTER("Event_timed::new(size)");
p= my_malloc(size, MYF(0));
DBUG_PRINT("info", ("alloc_ptr=0x%lx", p));
DBUG_RETURN(p);
}
static void *operator new(size_t size, MEM_ROOT *mem_root)
{ return (void*) alloc_root(mem_root, (uint) size); }
static void operator delete(void *ptr, size_t size)
{
DBUG_ENTER("Event_timed::delete(ptr,size)");
DBUG_PRINT("enter", ("free_ptr=0x%lx", ptr));
TRASH(ptr, size);
my_free((gptr) ptr, MYF(0));
DBUG_VOID_RETURN;
}
static void operator delete(void *ptr, MEM_ROOT *mem_root)
{
/*
Don't free the memory it will be done by the mem_root but
we need to call the destructor because we free other resources
which are not allocated on the root but on the heap, or we
deinit mutexes.
*/
DBUG_ASSERT(0);
}
Event_timed();
~Event_timed();
void
init();
void
deinit_mutexes();
int
init_definer(THD *thd);
int
init_execute_at(THD *thd, Item *expr);
int
init_interval(THD *thd, Item *expr, interval_type new_interval);
void
init_name(THD *thd, sp_name *spn);
int
init_starts(THD *thd, Item *starts);
int
init_ends(THD *thd, Item *ends);
void
init_body(THD *thd);
void
init_comment(THD *thd, LEX_STRING *set_comment);
int
load_from_row(MEM_ROOT *mem_root, TABLE *table);
bool
compute_next_execution_time();
int
drop(THD *thd);
void
mark_last_executed(THD *thd);
bool
update_fields(THD *thd);
int
get_create_event(THD *thd, String *buf);
int
execute(THD *thd, MEM_ROOT *mem_root);
int
compile(THD *thd, MEM_ROOT *mem_root);
bool
is_running();
int
spawn_now(void * (*thread_func)(void*), void *arg);
bool
spawn_thread_finish(THD *thd);
void
free_sp();
bool
has_equal_db(Event_timed *etn);
int
kill_thread(THD *thd);
void
set_thread_id(ulong tid) { thread_id= tid; }
};
#endif /* _EVENT_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -16,78 +16,112 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
class sp_name;
class Event_parse_data;
class Event_db_repository;
class Event_queue;
class Event_queue_element;
class Event_scheduler;
/* Return codes */
enum enum_events_error_code
{
OP_OK= 0,
OP_NOT_RUNNING,
OP_CANT_KILL,
OP_CANT_INIT,
OP_DISABLED_EVENT,
OP_LOAD_ERROR,
OP_ALREADY_EXISTS
};
int
sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
class Event_timed;
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
or other scheme will be found.
*/
static ulong opt_event_scheduler;
static TYPELIB opt_typelib;
enum enum_table_field
{
FIELD_DB = 0,
FIELD_NAME,
FIELD_BODY,
FIELD_DEFINER,
FIELD_EXECUTE_AT,
FIELD_INTERVAL_EXPR,
FIELD_TRANSIENT_INTERVAL,
FIELD_CREATED,
FIELD_MODIFIED,
FIELD_LAST_EXECUTED,
FIELD_STARTS,
FIELD_ENDS,
FIELD_STATUS,
FIELD_ON_COMPLETION,
FIELD_SQL_MODE,
FIELD_COMMENT,
FIELD_COUNT /* a cool trick to count the number of fields :) */
};
bool
init();
void
deinit();
static int
create_event(THD *thd, Event_timed *et, uint create_options,
void
init_mutexes();
void
destroy_mutexes();
bool
start_execution_of_events();
bool
stop_execution_of_events();
bool
is_started();
static Events*
get_instance();
int
create_event(THD *thd, Event_parse_data *parse_data, bool if_exists,
uint *rows_affected);
static int
update_event(THD *thd, Event_timed *et, sp_name *new_name,
int
update_event(THD *thd, Event_parse_data *parse_data, sp_name *rename_to,
uint *rows_affected);
static int
drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
uint *rows_affected);
int
drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists,
uint *rows_affected, bool only_from_disk);
static int
int
drop_schema_events(THD *thd, char *db);
int
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
static int
show_create_event(THD *thd, sp_name *spn);
int
show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name);
/* Needed for both SHOW CREATE EVENT and INFORMATION_SCHEMA */
static int
reconstruct_interval_expression(String *buf, interval_type interval,
longlong expression);
static int
drop_schema_events(THD *thd, char *db);
fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */);
static int
bool
dump_internal_status(THD *thd);
static int
init();
static void
shutdown();
static void
init_mutexes();
static void
destroy_mutexes();
private:
/* Singleton DP is used */
Events(){}
~Events(){}
/* Singleton instance */
static Events singleton;
Event_queue *event_queue;
Event_scheduler *scheduler;
Event_db_repository *db_repository;
pthread_mutex_t LOCK_event_metadata;
/* Prevent use of these */
Events(const Events &);
void operator=(Events &);

View File

@ -1,79 +0,0 @@
#ifndef _EVENT_PRIV_H_
#define _EVENT_PRIV_H_
/* Copyright (C) 2004-2006 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define EVENT_EXEC_STARTED 0
#define EVENT_EXEC_ALREADY_EXEC 1
#define EVENT_EXEC_CANT_FORK 2
#define EVEX_DB_FIELD_LEN 64
#define EVEX_NAME_FIELD_LEN 64
#define EVEX_MAX_INTERVAL_VALUE 2147483647L
class Event_timed;
int
evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
const LEX_STRING ev_name,
TABLE *table);
int
db_drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
uint *rows_affected);
int
db_find_event(THD *thd, sp_name *name, Event_timed **ett, TABLE *tbl,
MEM_ROOT *root);
int
db_create_event(THD *thd, Event_timed *et, my_bool create_if_not,
uint *rows_affected);
int
db_drop_events_from_table(THD *thd, LEX_STRING *db);
int
sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
/* Compares only the name part of the identifier */
bool
event_timed_name_equal(Event_timed *et, LEX_STRING *name);
/* Compares only the schema part of the identifier */
bool
event_timed_db_equal(Event_timed *et, LEX_STRING *db);
/*
Compares only the definer part of the identifier. Use during DROP USER
to drop user's events. (Still not implemented)
*/
bool
event_timed_definer_equal(Event_timed *et, LEX_STRING *definer);
/* Compares the whole identifier*/
bool
event_timed_identifier_equal(Event_timed *a, Event_timed *b);
bool
change_security_context(THD *thd, LEX_STRING user, LEX_STRING host,
LEX_STRING db, Security_context *s_ctx,
Security_context **backup);
void
restore_security_context(THD *thd, Security_context *backup);
#endif /* _EVENT_PRIV_H_ */

View File

@ -867,7 +867,7 @@ static void close_connections(void)
DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
tmp->thread_id));
/* We skip slave threads & scheduler on this first loop through. */
if (tmp->slave_thread || tmp->system_thread == SYSTEM_THREAD_EVENT_SCHEDULER)
if (tmp->slave_thread)
continue;
tmp->killed= THD::KILL_CONNECTION;
@ -886,7 +886,7 @@ static void close_connections(void)
}
(void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
Events::shutdown();
Events::get_instance()->deinit();
end_slave();
if (thread_count)
@ -1324,7 +1324,7 @@ static void clean_up_mutexes()
(void) pthread_mutex_destroy(&LOCK_bytes_sent);
(void) pthread_mutex_destroy(&LOCK_bytes_received);
(void) pthread_mutex_destroy(&LOCK_user_conn);
Events::destroy_mutexes();
Events::get_instance()->destroy_mutexes();
#ifdef HAVE_OPENSSL
(void) pthread_mutex_destroy(&LOCK_des_key_file);
#ifndef HAVE_YASSL
@ -2905,7 +2905,7 @@ static int init_thread_environment()
(void) pthread_mutex_init(&LOCK_server_started, MY_MUTEX_INIT_FAST);
(void) pthread_cond_init(&COND_server_started,NULL);
sp_cache_init();
Events::init_mutexes();
Events::get_instance()->init_mutexes();
/* Parameter for threads created for connections */
(void) pthread_attr_init(&connection_attrib);
(void) pthread_attr_setdetachstate(&connection_attrib,
@ -3696,7 +3696,8 @@ we force server id to 2, but this MySQL server will not act as a slave.");
if (!opt_noacl)
{
Events::init();
if (Events::get_instance()->init())
unireg_abort(1);
}
#if defined(__NT__) || defined(HAVE_SMEM)
handle_connections_methods();

View File

@ -57,7 +57,7 @@
#include <myisam.h>
#include <my_dir.h>
#include "event_scheduler.h"
#include "events.h"
/* WITH_BERKELEY_STORAGE_ENGINE */
extern bool berkeley_shared_data;
@ -3943,30 +3943,32 @@ byte *sys_var_thd_dbug::value_ptr(THD *thd, enum_var_type type, LEX_STRING *b)
bool
sys_var_event_scheduler::update(THD *thd, set_var *var)
{
enum Event_scheduler::enum_error_code res;
Event_scheduler *scheduler= Event_scheduler::get_instance();
int res;
/* here start the thread if not running. */
DBUG_ENTER("sys_var_event_scheduler::update");
DBUG_PRINT("new_value", ("%lu", (bool)var->save_result.ulong_value));
if (!scheduler->initialized())
if (Events::opt_event_scheduler == 0)
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--event-scheduler=0");
DBUG_RETURN(true);
DBUG_RETURN(TRUE);
}
DBUG_PRINT("new_value", ("%lu", (bool)var->save_result.ulong_value));
if (var->save_result.ulonglong_value < 1 ||
var->save_result.ulonglong_value > 2)
{
char buf[64];
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "event_scheduler",
llstr(var->save_result.ulonglong_value, buf));
DBUG_RETURN(true);
DBUG_RETURN(TRUE);
}
if ((res= scheduler->suspend_or_resume(var->save_result.ulonglong_value == 1?
Event_scheduler::RESUME :
Event_scheduler::SUSPEND)))
my_error(ER_EVENT_SET_VAR_ERROR, MYF(0), (uint) res);
if (var->save_result.ulonglong_value == 1)
res= Events::get_instance()->start_execution_of_events();
else
res= Events::get_instance()->stop_execution_of_events();
if (res)
my_error(ER_EVENT_SET_VAR_ERROR, MYF(0));
DBUG_RETURN((bool) res);
}
@ -3974,11 +3976,9 @@ sys_var_event_scheduler::update(THD *thd, set_var *var)
byte *sys_var_event_scheduler::value_ptr(THD *thd, enum_var_type type,
LEX_STRING *base)
{
Event_scheduler *scheduler= Event_scheduler::get_instance();
if (!scheduler->initialized())
if (Events::opt_event_scheduler == 0)
thd->sys_var_tmp.long_value= 0;
else if (scheduler->get_state() == Event_scheduler::RUNNING)
else if (Events::get_instance()->is_started())
thd->sys_var_tmp.long_value= 1;
else
thd->sys_var_tmp.long_value= 2;

View File

@ -647,10 +647,12 @@ sp_head::create(THD *thd)
sp_head::~sp_head()
{
DBUG_ENTER("sp_head::~sp_head");
destroy();
delete m_next_cached_sp;
if (m_thd)
restore_thd_mem_root(m_thd);
DBUG_VOID_RETURN;
}
void

View File

@ -2084,6 +2084,7 @@ bool Security_context::set_user(char *user_arg)
return user == 0;
}
/****************************************************************************
Handling of open and locked tables states.

View File

@ -949,7 +949,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
exit:
(void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */
error= Events::drop_schema_events(thd, db);
error= Events::get_instance()->drop_schema_events(thd, db);
/*
If this database was the client's selected database, we silently
change the client's selected database to nothing (to have an empty

View File

@ -169,14 +169,15 @@ void lex_start(THD *thd, const uchar *buf, uint length)
lex->sql_command= SQLCOM_END;
lex->duplicates= DUP_ERROR;
lex->ignore= 0;
lex->spname= NULL;
lex->sphead= NULL;
lex->spcont= NULL;
lex->proc_list.first= 0;
lex->escape_used= lex->et_compile_phase= FALSE;
lex->escape_used= FALSE;
lex->reset_query_tables_list(FALSE);
lex->name= 0;
lex->et= NULL;
lex->event_parse_data= NULL;
lex->nest_level=0 ;
lex->allow_sum_func= 0;

View File

@ -27,7 +27,7 @@ class sp_instr;
class sp_pcontext;
class st_alter_tablespace;
class partition_info;
class Event_timed;
class Event_parse_data;
#ifdef MYSQL_SERVER
/*
@ -1035,8 +1035,7 @@ typedef struct st_lex : public Query_tables_list
st_sp_chistics sp_chistics;
Event_timed *et;
bool et_compile_phase;
Event_parse_data *event_parse_data;
bool only_view; /* used for SHOW CREATE TABLE/VIEW */
/*

View File

@ -27,7 +27,7 @@
#include "sp.h"
#include "sp_cache.h"
#include "events.h"
#include "event_timed.h"
#include "event_data_objects.h"
#ifdef HAVE_OPENSSL
/*
@ -3896,73 +3896,44 @@ end_with_restore_list:
}
case SQLCOM_CREATE_EVENT:
case SQLCOM_ALTER_EVENT:
case SQLCOM_DROP_EVENT:
{
uint rows_affected= 1;
DBUG_ASSERT(lex->et);
do {
if (! lex->et->dbname.str ||
(lex->sql_command == SQLCOM_ALTER_EVENT && lex->spname &&
!lex->spname->m_db.str))
{
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
res= true;
break;
}
uint affected= 1;
DBUG_ASSERT(lex->event_parse_data);
switch (lex->sql_command) {
case SQLCOM_CREATE_EVENT:
res= Events::get_instance()->
create_event(thd, lex->event_parse_data,
lex->create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS,
&affected);
break;
case SQLCOM_ALTER_EVENT:
res= Events::get_instance()->
update_event(thd, lex->event_parse_data, lex->spname, &affected);
break;
default:;
}
DBUG_PRINT("info",("DDL error code=%d affected=%d", res, affected));
if (!res)
send_ok(thd, affected);
if (check_access(thd, EVENT_ACL, lex->et->dbname.str, 0, 0, 0,
is_schema_db(lex->et->dbname.str)) ||
(lex->sql_command == SQLCOM_ALTER_EVENT && lex->spname &&
(check_access(thd, EVENT_ACL, lex->spname->m_db.str, 0, 0, 0,
is_schema_db(lex->spname->m_db.str)))))
break;
if (end_active_trans(thd))
{
res= -1;
break;
}
switch (lex->sql_command) {
case SQLCOM_CREATE_EVENT:
res= Events::create_event(thd, lex->et,
(uint) lex->create_info.options,
&rows_affected);
break;
case SQLCOM_ALTER_EVENT:
res= Events::update_event(thd, lex->et, lex->spname,
&rows_affected);
break;
case SQLCOM_DROP_EVENT:
res= Events::drop_event(thd, lex->et, lex->drop_if_exists,
&rows_affected);
default:;
}
DBUG_PRINT("info", ("CREATE/ALTER/DROP returned error code=%d af_rows=%d",
res, rows_affected));
if (!res)
send_ok(thd, rows_affected);
/* lex->unit.cleanup() is called outside, no need to call it here */
} while (0);
/* Don't do it, if we are inside a SP */
if (!thd->spcont)
{
lex->et->free_sphead_on_delete= true;
lex->et->free_sp();
lex->et->deinit_mutexes();
delete lex->sphead;
lex->sphead= NULL;
}
/* lex->unit.cleanup() is called outside, no need to call it here */
break;
}
case SQLCOM_DROP_EVENT:
case SQLCOM_SHOW_CREATE_EVENT:
{
DBUG_ASSERT(lex->spname);
DBUG_ASSERT(lex->et);
if (! lex->spname->m_db.str)
{
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
res= true;
break;
goto error;
}
if (check_access(thd, EVENT_ACL, lex->spname->m_db.str, 0, 0, 0,
is_schema_db(lex->spname->m_db.str)))
@ -3971,15 +3942,30 @@ end_with_restore_list:
if (lex->spname->m_name.length > NAME_LEN)
{
my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
/* this jumps to the end of the function and skips own messaging */
goto error;
}
res= Events::show_create_event(thd, lex->spname);
if (lex->sql_command == SQLCOM_SHOW_CREATE_EVENT)
res= Events::get_instance()->show_create_event(thd, lex->spname->m_db,
lex->spname->m_name);
else
{
uint affected= 1;
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;
}
#ifndef DBUG_OFF
case SQLCOM_SHOW_SCHEDULER_STATUS:
{
res= Events::dump_internal_status(thd);
res= Events::get_instance()->dump_internal_status(thd);
break;
}
#endif
@ -6059,14 +6045,6 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
{
delete lex->sphead;
lex->sphead= NULL;
if (lex->et)
{
lex->et->free_sphead_on_delete= true;
/* alloced on thd->mem_root so no real memory free but dtor call */
lex->et->free_sp();
lex->et->deinit_mutexes();
lex->et= NULL;
}
}
else
{
@ -6103,13 +6081,6 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
delete lex->sphead;
lex->sphead= NULL;
}
if (lex->et)
{
lex->et->free_sphead_on_delete= true;
lex->et->free_sp();
lex->et->deinit_mutexes();
lex->et= NULL;
}
}
thd->proc_info="freeing items";
thd->end_statement();

View File

@ -27,7 +27,7 @@
#include "authors.h"
#include "contributors.h"
#include "events.h"
#include "event_timed.h"
#include "event_data_objects.h"
#include <my_dir.h>
#ifdef WITH_PARTITION_STORAGE_ENGINE
@ -4232,7 +4232,7 @@ extern LEX_STRING interval_type_to_name[];
1 Error
*/
static int
int
copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
{
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
@ -4243,7 +4243,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
restore_record(sch_table, s->default_values);
if (et.load_from_row(thd->mem_root, event_table))
if (et.load_from_row(event_table))
{
my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0));
DBUG_RETURN(1);
@ -4367,183 +4367,6 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
}
/*
Performs an index scan of event_table (mysql.event) and fills schema_table.
Synopsis
events_table_index_read_for_db()
thd Thread
schema_table The I_S.EVENTS table
event_table The event table to use for loading (mysql.event)
Returns
0 OK
1 Error
*/
static
int events_table_index_read_for_db(THD *thd, TABLE *schema_table,
TABLE *event_table)
{
int ret=0;
CHARSET_INFO *scs= system_charset_info;
KEY *key_info;
uint key_len;
byte *key_buf= NULL;
LINT_INIT(key_buf);
DBUG_ENTER("schema_events_do_index_scan");
DBUG_PRINT("info", ("Using prefix scanning on PK"));
event_table->file->ha_index_init(0, 1);
event_table->field[Events::FIELD_DB]->
store(thd->lex->select_lex.db, strlen(thd->lex->select_lex.db), scs);
key_info= event_table->key_info;
key_len= key_info->key_part[0].store_length;
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() */
}
else
{
key_copy(key_buf, event_table->record[0], key_info, key_len);
if (!(ret= event_table->file->index_read(event_table->record[0], key_buf,
key_len, HA_READ_PREFIX)))
{
DBUG_PRINT("info",("Found rows. Let's retrieve them. ret=%d", ret));
do
{
ret= copy_event_to_schema_table(thd, schema_table, event_table);
if (ret == 0)
ret= event_table->file->index_next_same(event_table->record[0],
key_buf, key_len);
} while (ret == 0);
}
DBUG_PRINT("info", ("Scan finished. ret=%d", ret));
}
event_table->file->ha_index_end();
/* ret is guaranteed to be != 0 */
if (ret == HA_ERR_END_OF_FILE || ret == HA_ERR_KEY_NOT_FOUND)
DBUG_RETURN(0);
DBUG_RETURN(1);
}
/*
Performs a table scan of event_table (mysql.event) and fills schema_table.
Synopsis
events_table_scan_all()
thd Thread
schema_table The I_S.EVENTS in memory table
event_table The event table to use for loading.
Returns
0 OK
1 Error
*/
static
int events_table_scan_all(THD *thd, TABLE *schema_table,
TABLE *event_table)
{
int ret;
READ_RECORD read_record_info;
DBUG_ENTER("schema_events_do_table_scan");
init_read_record(&read_record_info, thd, event_table, NULL, 1, 0);
/*
rr_sequential, in read_record(), returns 137==HA_ERR_END_OF_FILE,
but rr_handle_error returns -1 for that reason. Thus, read_record()
returns -1 eventually.
*/
do
{
ret= read_record_info.read_record(&read_record_info);
if (ret == 0)
ret= copy_event_to_schema_table(thd, schema_table, event_table);
}
while (ret == 0);
DBUG_PRINT("info", ("Scan finished. ret=%d", ret));
end_read_record(&read_record_info);
/* ret is guaranteed to be != 0 */
DBUG_RETURN(ret == -1? 0:1);
}
/*
Fills I_S.EVENTS with data loaded from mysql.event. Also used by
SHOW EVENTS
Synopsis
fill_schema_events()
thd Thread
tables The schema table
cond Unused
Returns
0 OK
1 Error
*/
int fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
{
TABLE *schema_table= tables->table;
TABLE *event_table= NULL;
Open_tables_state backup;
int ret= 0;
DBUG_ENTER("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);
}
DBUG_PRINT("info",("db=%s", thd->lex->select_lex.db?
thd->lex->select_lex.db:"(null)"));
thd->reset_n_backup_open_tables_state(&backup);
if (Events::open_event_table(thd, TL_READ, &event_table))
{
sql_print_error("Table mysql.event is damaged.");
thd->restore_backup_open_tables_state(&backup);
DBUG_RETURN(1);
}
/*
1. SELECT I_S => use table scan. I_S.EVENTS does not guarantee order
thus we won't order it. OTOH, SHOW EVENTS will be
ordered.
2. SHOW EVENTS => PRIMARY KEY with prefix scanning on (db)
Reasoning: Events are per schema, therefore a scan over an index
will save use from doing a table scan and comparing
every single row's `db` with the schema which we show.
*/
if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS)
ret= events_table_index_read_for_db(thd, schema_table, event_table);
else
ret= events_table_scan_all(thd, schema_table, event_table);
close_thread_tables(thd);
thd->restore_backup_open_tables_state(&backup);
DBUG_PRINT("info", ("Return code=%d", ret));
DBUG_RETURN(ret);
}
int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond)
{
DBUG_ENTER("fill_open_tables");
@ -5646,7 +5469,7 @@ ST_SCHEMA_TABLE schema_tables[]=
{"ENGINES", engines_fields_info, create_schema_table,
fill_schema_engines, make_old_format, 0, -1, -1, 0},
{"EVENTS", events_fields_info, create_schema_table,
fill_schema_events, make_old_format, 0, -1, -1, 0},
Events::fill_schema_events, make_old_format, 0, -1, -1, 0},
{"FILES", files_fields_info, create_schema_table,
fill_schema_files, 0, 0, -1, -1, 0},
{"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,

View File

@ -14,4 +14,6 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
HA_CREATE_INFO *create_info_arg);
int view_store_create_info(THD *thd, TABLE_LIST *table, String *buff);
int copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table);
#endif /* SQL_SHOW_H */

View File

@ -38,7 +38,7 @@
#include "sp_pcontext.h"
#include "sp_rcontext.h"
#include "sp.h"
#include "event_timed.h"
#include "event_data_objects.h"
#include <myisam.h>
#include <myisammrg.h>
@ -880,7 +880,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
load_data opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
definer view_replace_or_algorithm view_replace view_algorithm_opt
view_algorithm view_or_trigger_or_sp view_or_trigger_or_sp_tail
view_algorithm view_or_trigger_or_sp_or_event
view_or_trigger_or_sp_or_event_tail
view_suid view_tail view_list_opt view_list view_select
view_check_option trigger_tail sp_tail
install uninstall partition_entry binlog_base64_event
@ -1257,29 +1258,41 @@ create:
lex->name=$4.str;
lex->create_info.options=$3;
}
| CREATE EVENT_SYM opt_if_not_exists sp_name
| CREATE
{
Lex->create_view_mode= VIEW_CREATE_NEW;
Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED;
Lex->create_view_suid= TRUE;
}
view_or_trigger_or_sp_or_event
{}
| CREATE USER clear_privileges grant_list
{
Lex->sql_command = SQLCOM_CREATE_USER;
}
| CREATE LOGFILE_SYM GROUP logfile_group_info
{
Lex->alter_tablespace_info->ts_cmd_type= CREATE_LOGFILE_GROUP;
}
| CREATE TABLESPACE tablespace_info
{
Lex->alter_tablespace_info->ts_cmd_type= CREATE_TABLESPACE;
}
;
event_tail:
EVENT_SYM opt_if_not_exists sp_name
/*
BE CAREFUL when you add a new rule to update the block where
YYTHD->client_capabilities is set back to original value
*/
{
LEX *lex=Lex;
Lex->create_info.options= $2;
if (lex->et)
{
/*
Recursive events are not possible because recursive SPs
are not also possible. lex->sp_head is not stacked.
*/
// ToDo Andrey : Change the error message
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "EVENT");
YYABORT;
}
lex->create_info.options= $3;
if (!(lex->et= new(YYTHD->mem_root) Event_timed())) // implicitly calls Event_timed::init()
if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD)))
YYABORT;
Lex->event_parse_data->identifier= $3;
/*
We have to turn of CLIENT_MULTI_QUERIES while parsing a
@ -1289,11 +1302,8 @@ create:
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES);
if (!lex->et_compile_phase)
{
lex->et->init_name(YYTHD, $4);
lex->et->init_definer(YYTHD);
}
/* We need that for disallowing subqueries */
Lex->sql_command= SQLCOM_CREATE_EVENT;
}
ON SCHEDULE_SYM ev_schedule_time
opt_ev_on_completion
@ -1303,13 +1313,12 @@ create:
{
/*
Restore flag if it was cleared above
$1 - CREATE
$2 - EVENT_SYM
$3 - opt_if_not_exists
$4 - sp_name
$5 - the block above
$1 - EVENT_SYM
$2 - opt_if_not_exists
$3 - sp_name
$4 - the block above
*/
YYTHD->client_capabilities |= $<ulong_num>5;
YYTHD->client_capabilities |= $<ulong_num>4;
/*
sql_command is set here because some rules in ev_sql_stmt
@ -1317,146 +1326,48 @@ create:
*/
Lex->sql_command= SQLCOM_CREATE_EVENT;
}
| CREATE
{
Lex->create_view_mode= VIEW_CREATE_NEW;
Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED;
Lex->create_view_suid= TRUE;
}
view_or_trigger_or_sp
{}
| CREATE USER clear_privileges grant_list
{
Lex->sql_command = SQLCOM_CREATE_USER;
}
| CREATE LOGFILE_SYM GROUP logfile_group_info
{
LEX *lex= Lex;
lex->alter_tablespace_info->ts_cmd_type= CREATE_LOGFILE_GROUP;
}
| CREATE TABLESPACE tablespace_info
{
LEX *lex= Lex;
lex->alter_tablespace_info->ts_cmd_type= CREATE_TABLESPACE;
}
;
ev_schedule_time: EVERY_SYM expr interval
{
LEX *lex=Lex;
if (!lex->et_compile_phase)
{
switch (lex->et->init_interval(YYTHD , $2, $3)) {
case EVEX_PARSE_ERROR:
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
break;
case EVEX_BAD_PARAMS:
my_error(ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG, MYF(0));
case EVEX_MICROSECOND_UNSUP:
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "MICROSECOND");
YYABORT;
break;
}
}
Lex->event_parse_data->item_expression= $2;
Lex->event_parse_data->interval= $3;
}
ev_starts
ev_ends
| AT_SYM expr
{
LEX *lex=Lex;
if (!lex->et_compile_phase)
{
switch (lex->et->init_execute_at(YYTHD, $2)) {
case EVEX_PARSE_ERROR:
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
break;
case ER_WRONG_VALUE:
{
char buff[120];
String str(buff,(uint32) sizeof(buff), system_charset_info);
String *str2= $2->val_str(&str);
my_error(ER_WRONG_VALUE, MYF(0), "AT",
str2? str2->c_ptr_safe():"NULL");
YYABORT;
break;
}
case EVEX_BAD_PARAMS:
my_error(ER_EVENT_EXEC_TIME_IN_THE_PAST, MYF(0));
YYABORT;
break;
}
}
Lex->event_parse_data->item_execute_at= $2;
}
;
opt_ev_status: /* empty */ { $$= 0; }
| ENABLE_SYM
{
LEX *lex=Lex;
if (!lex->et_compile_phase)
lex->et->status= Event_timed::ENABLED;
Lex->event_parse_data->status= Event_parse_data::ENABLED;
$$= 1;
}
| DISABLE_SYM
{
LEX *lex=Lex;
if (!lex->et_compile_phase)
lex->et->status= Event_timed::DISABLED;
Lex->event_parse_data->status= Event_parse_data::DISABLED;
$$= 1;
}
;
ev_starts: /* empty */
{
Lex->et->init_starts(YYTHD, new Item_func_now_local());
Lex->event_parse_data->item_starts= new Item_func_now_local();
}
| STARTS_SYM expr
{
LEX *lex= Lex;
if (!lex->et_compile_phase)
{
switch (lex->et->init_starts(YYTHD, $2)) {
case EVEX_PARSE_ERROR:
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
break;
case EVEX_BAD_PARAMS:
{
char buff[20];
String str(buff,(uint32) sizeof(buff), system_charset_info);
String *str2= $2->val_str(&str);
my_error(ER_WRONG_VALUE, MYF(0), "STARTS",
str2 ? str2->c_ptr_safe() : NULL);
YYABORT;
break;
}
}
}
Lex->event_parse_data->item_starts= $2;
}
;
ev_ends: /* empty */
| ENDS_SYM expr
{
LEX *lex= Lex;
if (!lex->et_compile_phase)
{
switch (lex->et->init_ends(YYTHD, $2)) {
case EVEX_PARSE_ERROR:
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
break;
case EVEX_BAD_PARAMS:
my_error(ER_EVENT_ENDS_BEFORE_STARTS, MYF(0));
YYABORT;
break;
}
}
Lex->event_parse_data->item_ends= $2;
}
;
@ -1467,16 +1378,14 @@ opt_ev_on_completion: /* empty */ { $$= 0; }
ev_on_completion:
ON COMPLETION_SYM PRESERVE_SYM
{
LEX *lex=Lex;
if (!lex->et_compile_phase)
lex->et->on_completion= Event_timed::ON_COMPLETION_PRESERVE;
Lex->event_parse_data->on_completion=
Event_parse_data::ON_COMPLETION_PRESERVE;
$$= 1;
}
| ON COMPLETION_SYM NOT_SYM PRESERVE_SYM
{
LEX *lex=Lex;
if (!lex->et_compile_phase)
lex->et->on_completion= Event_timed::ON_COMPLETION_DROP;
Lex->event_parse_data->on_completion=
Event_parse_data::ON_COMPLETION_DROP;
$$= 1;
}
;
@ -1484,64 +1393,65 @@ ev_on_completion:
opt_ev_comment: /* empty */ { $$= 0; }
| COMMENT_SYM TEXT_STRING_sys
{
LEX *lex= Lex;
if (!lex->et_compile_phase)
{
lex->comment= $2;
lex->et->init_comment(YYTHD, &$2);
}
$$= 1;
Lex->comment= Lex->event_parse_data->comment= $2;
}
;
ev_sql_stmt:
{
LEX *lex= Lex;
sp_head *sp;
$<sphead>$= lex->sphead;
if (!lex->sphead)
/*
This stops the following :
- CREATE EVENT ... DO CREATE EVENT ...;
- ALTER EVENT ... DO CREATE EVENT ...;
- CREATE EVENT ... DO ALTER EVENT DO ....;
- CREATE PROCEDURE ... BEGIN CREATE EVENT ... END|
This allows:
- CREATE EVENT ... DO DROP EVENT yyy;
- CREATE EVENT ... DO ALTER EVENT yyy;
(the nested ALTER EVENT can have anything but DO clause)
- ALTER EVENT ... DO ALTER EVENT yyy;
(the nested ALTER EVENT can have anything but DO clause)
- ALTER EVENT ... DO DROP EVENT yyy;
- CREATE PROCEDURE ... BEGIN ALTER EVENT ... END|
(the nested ALTER EVENT can have anything but DO clause)
- CREATE PROCEDURE ... BEGIN DROP EVENT ... END|
*/
if (lex->sphead)
{
if (!(sp= new sp_head()))
YYABORT;
sp->reset_thd_mem_root(YYTHD);
sp->init(lex);
sp->m_type= TYPE_ENUM_PROCEDURE;
lex->sphead= sp;
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
lex->sphead->m_chistics= &lex->sp_chistics;
lex->sphead->m_body_begin= lex->ptr;
my_error(ER_EVENT_RECURSIVITY_FORBIDDEN, MYF(0));
YYABORT;
}
if (!(lex->sphead= new sp_head()))
YYABORT;
lex->sphead->reset_thd_mem_root(YYTHD);
lex->sphead->init(lex);
lex->sphead->m_type= TYPE_ENUM_PROCEDURE;
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
lex->sphead->m_chistics= &lex->sp_chistics;
lex->sphead->m_body_begin= lex->ptr;
Lex->event_parse_data->body_begin= lex->ptr;
if (!lex->et_compile_phase)
lex->et->body_begin= lex->ptr;
}
ev_sql_stmt_inner
{
LEX *lex=Lex;
if (!$<sphead>1)
{
sp_head *sp= lex->sphead;
// return back to the original memory root ASAP
sp->init_strings(YYTHD, lex);
sp->restore_thd_mem_root(YYTHD);
// return back to the original memory root ASAP
lex->sphead->init_strings(YYTHD, lex,
Lex->event_parse_data->identifier);
lex->sphead->restore_thd_mem_root(YYTHD);
lex->sp_chistics.suid= SP_IS_SUID;//always the definer!
lex->sp_chistics.suid= SP_IS_SUID;//always the definer!
lex->et->sphead= lex->sphead;
lex->sphead= NULL;
}
if (!lex->et_compile_phase)
{
lex->et->init_body(YYTHD);
}
Lex->event_parse_data->init_body(YYTHD);
}
;
@ -1613,17 +1523,6 @@ create_function_tail:
RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys
{
LEX *lex=Lex;
if (lex->definer != NULL)
{
/*
DEFINER is a concept meaningful when interpreting SQL code.
UDF functions are compiled.
Using DEFINER with UDF has therefore no semantic,
and is considered a parsing error.
*/
my_error(ER_WRONG_USAGE, MYF(0), "SONAME", "DEFINER");
YYABORT;
}
lex->sql_command = SQLCOM_CREATE_FUNCTION;
lex->udf.name = lex->spname->m_name;
lex->udf.returns=(Item_result) $2;
@ -4767,37 +4666,29 @@ alter:
YYTHD->client_capabilities is set back to original value
*/
{
LEX *lex=Lex;
Event_timed *et;
/*
It is safe to use Lex->spname because
ALTER EVENT xxx RENATE TO yyy DO ALTER EVENT RENAME TO
is not allowed. Lex->spname is used in the case of RENAME TO
If it had to be supported spname had to be added to
Event_parse_data.
*/
Lex->spname= NULL;
if (lex->et)
{
/*
Recursive events are not possible because recursive SPs
are not also possible. lex->sp_head is not stacked.
*/
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "EVENT");
if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD)))
YYABORT;
}
lex->spname= 0;//defensive programming
if (!(et= new (YYTHD->mem_root) Event_timed()))// implicitly calls Event_timed::init()
YYABORT;
lex->et = et;
if (!lex->et_compile_phase)
{
et->init_definer(YYTHD);
et->init_name(YYTHD, $3);
}
Lex->event_parse_data->identifier= $3;
/*
We have to turn of CLIENT_MULTI_QUERIES while parsing a
stored procedure, otherwise yylex will chop it into pieces
at each ';'.
We have to turn of CLIENT_MULTI_QUERIES while parsing a
stored procedure, otherwise yylex will chop it into pieces
at each ';'.
*/
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
/* we need that for disallowing subqueries */
Lex->sql_command= SQLCOM_ALTER_EVENT;
}
ev_alter_on_schedule_completion
opt_ev_rename_to
@ -4813,15 +4704,15 @@ alter:
*/
YYTHD->client_capabilities |= $<ulong_num>4;
/*
sql_command is set here because some rules in ev_sql_stmt
can overwrite it
*/
if (!($5 || $6 || $7 || $8 || $9))
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
/*
sql_command is set here because some rules in ev_sql_stmt
can overwrite it
*/
Lex->sql_command= SQLCOM_ALTER_EVENT;
}
| ALTER TABLESPACE alter_tablespace_info
@ -4857,7 +4748,7 @@ opt_ev_rename_to: /* empty */ { $$= 0;}
{
LEX *lex=Lex;
lex->spname= $3; //use lex's spname to hold the new name
//the original name is in the Event_timed object
//the original name is in the Event_parse_data object
$$= 1;
}
;
@ -7145,8 +7036,10 @@ select_derived2:
{
LEX *lex= Lex;
lex->derived_tables|= DERIVED_SUBQUERY;
if (lex->sql_command == (int)SQLCOM_HA_READ ||
lex->sql_command == (int)SQLCOM_KILL)
if (lex->sql_command == SQLCOM_HA_READ ||
lex->sql_command == SQLCOM_KILL ||
lex->sql_command == SQLCOM_CREATE_EVENT ||
lex->sql_command == SQLCOM_ALTER_EVENT)
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
@ -7740,29 +7633,9 @@ drop:
}
| DROP EVENT_SYM if_exists sp_name
{
LEX *lex=Lex;
if (lex->et)
{
/*
Recursive events are not possible because recursive SPs
are not also possible. lex->sp_head is not stacked.
*/
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "EVENT");
YYABORT;
}
if (!(lex->et= new (YYTHD->mem_root) Event_timed()))
YYABORT;
if (!lex->et_compile_phase)
{
lex->et->init_name(YYTHD, $4);
lex->et->init_definer(YYTHD);
}
lex->sql_command = SQLCOM_DROP_EVENT;
lex->drop_if_exists= $3;
Lex->drop_if_exists= $3;
Lex->spname= $4;
Lex->sql_command = SQLCOM_DROP_EVENT;
}
| DROP TRIGGER_SYM sp_name
{
@ -8479,12 +8352,8 @@ show_param:
}
| CREATE EVENT_SYM sp_name
{
Lex->sql_command = SQLCOM_SHOW_CREATE_EVENT;
Lex->spname= $3;
Lex->et= new (YYTHD->mem_root) Event_timed();
if (!Lex->et)
YYABORT;
Lex->et->init_definer(YYTHD);
Lex->sql_command = SQLCOM_SHOW_CREATE_EVENT;
}
;
@ -10789,8 +10658,10 @@ subselect_start:
'(' SELECT_SYM
{
LEX *lex=Lex;
if (lex->sql_command == (int)SQLCOM_HA_READ ||
lex->sql_command == (int)SQLCOM_KILL)
if (lex->sql_command == SQLCOM_HA_READ ||
lex->sql_command == SQLCOM_KILL ||
lex->sql_command == SQLCOM_CREATE_EVENT ||
lex->sql_command == SQLCOM_ALTER_EVENT)
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
@ -10814,20 +10685,22 @@ subselect_end:
**************************************************************************/
view_or_trigger_or_sp:
definer view_or_trigger_or_sp_tail
view_or_trigger_or_sp_or_event:
definer view_or_trigger_or_sp_or_event_tail
{}
| view_replace_or_algorithm definer view_tail
{}
;
view_or_trigger_or_sp_tail:
view_or_trigger_or_sp_or_event_tail:
view_tail
{}
| trigger_tail
{}
| sp_tail
{}
| event_tail
{}
;
/**************************************************************************