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:
commit
66fb56f115
1107
.bzrignore
1107
.bzrignore
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
|
@ -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
|
||||
|
4
mysql-test/include/not_valgrind.inc
Normal file
4
mysql-test/include/not_valgrind.inc
Normal file
@ -0,0 +1,4 @@
|
||||
--require r/not_valgrind.require
|
||||
--disable_query_log
|
||||
eval select $VALGRIND_TEST as using_valgrind;
|
||||
--enable_query_log
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
10
mysql-test/r/events_restart_phase1.result
Normal file
10
mysql-test/r/events_restart_phase1.result
Normal 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"
|
6
mysql-test/r/events_restart_phase2.result
Normal file
6
mysql-test/r/events_restart_phase2.result
Normal 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"
|
9
mysql-test/r/events_restart_phase3.result
Normal file
9
mysql-test/r/events_restart_phase3.result
Normal 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;
|
@ -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;
|
||||
|
@ -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;
|
||||
|
2
mysql-test/r/not_valgrind.require
Normal file
2
mysql-test/r/not_valgrind.require
Normal file
@ -0,0 +1,2 @@
|
||||
using_valgrind
|
||||
0
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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|
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
#
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
17
mysql-test/t/events_restart_phase1.test
Normal file
17
mysql-test/t/events_restart_phase1.test
Normal 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"
|
1
mysql-test/t/events_restart_phase2-master.opt
Normal file
1
mysql-test/t/events_restart_phase2-master.opt
Normal file
@ -0,0 +1 @@
|
||||
--event-scheduler=1
|
9
mysql-test/t/events_restart_phase2.test
Normal file
9
mysql-test/t/events_restart_phase2.test
Normal 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"
|
1
mysql-test/t/events_restart_phase3-master.opt
Normal file
1
mysql-test/t/events_restart_phase3-master.opt
Normal file
@ -0,0 +1 @@
|
||||
--event-scheduler=1
|
14
mysql-test/t/events_restart_phase3.test
Normal file
14
mysql-test/t/events_restart_phase3.test
Normal 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;
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
285
sql/event_data_objects.h
Normal 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
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
108
sql/event_db_repository.h
Normal 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
1084
sql/event_queue.cc
Normal file
File diff suppressed because it is too large
Load Diff
119
sql/event_queue.h
Normal file
119
sql/event_queue.h
Normal 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
@ -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 */
|
||||
|
@ -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_ */
|
1282
sql/events.cc
1282
sql/events.cc
File diff suppressed because it is too large
Load Diff
126
sql/events.h
126
sql/events.h
@ -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 &);
|
||||
|
@ -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_ */
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -2084,6 +2084,7 @@ bool Security_context::set_user(char *user_arg)
|
||||
return user == 0;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Handling of open and locked tables states.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
/*
|
||||
|
115
sql/sql_parse.cc
115
sql/sql_parse.cc
@ -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();
|
||||
|
185
sql/sql_show.cc
185
sql/sql_show.cc
@ -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,
|
||||
|
@ -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 */
|
||||
|
387
sql/sql_yacc.yy
387
sql/sql_yacc.yy
@ -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
|
||||
{}
|
||||
;
|
||||
|
||||
/**************************************************************************
|
||||
|
Loading…
x
Reference in New Issue
Block a user