Merge bk-internal.mysql.com:/data0/bk/mysql-5.1-runtime
into bk-internal.mysql.com:/data0/bk/mysql-5.1-wl3337 client/mysqltest.c: Auto merged libmysqld/Makefile.am: Auto merged mysql-test/mysql-test-run.pl: Auto merged mysql-test/r/events.result: Auto merged mysql-test/r/not_embedded_server.result: Auto merged mysql-test/t/events.test: 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_lex.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_show.cc: Auto merged sql/sql_yacc.yy: Auto merged sql/table.cc: Auto merged sql/table.h: Auto merged
This commit is contained in:
commit
23a46f410f
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 sp_protocol= 0, sp_protocol_enabled= 0;
|
||||||
static my_bool view_protocol= 0, view_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 cursor_protocol= 0, cursor_protocol_enabled= 0;
|
||||||
|
static my_bool opt_valgrind_test= 0;
|
||||||
static int parsing_disabled= 0;
|
static int parsing_disabled= 0;
|
||||||
|
|
||||||
static char **default_argv;
|
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},
|
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,
|
{"user", 'u', "User for login.", (gptr*) &user, (gptr*) &user, 0, GET_STR,
|
||||||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
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,
|
{"verbose", 'v', "Write more.", (gptr*) &verbose, (gptr*) &verbose, 0,
|
||||||
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
{"version", 'V', "Output version information and exit.",
|
{"version", 'V', "Output version information and exit.",
|
||||||
@ -5060,6 +5063,9 @@ static void init_var_hash(MYSQL *mysql)
|
|||||||
die("Variable hash initialization failed");
|
die("Variable hash initialization failed");
|
||||||
my_hash_insert(&var_hash, (byte*) var_init(0,"BIG_TEST", 0,
|
my_hash_insert(&var_hash, (byte*) var_init(0,"BIG_TEST", 0,
|
||||||
(opt_big_test) ? "1" : "0", 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);
|
v= var_init(0,"MAX_TABLES", 0, (sizeof(ulong) == 4) ? "31" : "62",0);
|
||||||
my_hash_insert(&var_hash, (byte*) v);
|
my_hash_insert(&var_hash, (byte*) v);
|
||||||
v= var_init(0,"SERVER_VERSION", 0, mysql_get_server_info(mysql), 0);
|
v= var_init(0,"SERVER_VERSION", 0, mysql_get_server_info(mysql), 0);
|
||||||
|
@ -67,7 +67,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 \
|
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 \
|
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 \
|
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 \
|
rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
|
||||||
sql_tablespace.cc \
|
sql_tablespace.cc \
|
||||||
rpl_injector.cc my_user.c partition_info.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
|
@ -3635,6 +3635,11 @@ sub run_mysqltest ($) {
|
|||||||
mtr_add_arg($args, "--big-test");
|
mtr_add_arg($args, "--big-test");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( $opt_valgrind )
|
||||||
|
{
|
||||||
|
mtr_add_arg($args, "--valgrind");
|
||||||
|
}
|
||||||
|
|
||||||
if ( $opt_compress )
|
if ( $opt_compress )
|
||||||
{
|
{
|
||||||
mtr_add_arg($args, "--compress");
|
mtr_add_arg($args, "--compress");
|
||||||
|
@ -17,13 +17,13 @@ db_x
|
|||||||
SHOW TABLES FROM db_x;
|
SHOW TABLES FROM db_x;
|
||||||
Tables_in_db_x
|
Tables_in_db_x
|
||||||
x_table
|
x_table
|
||||||
SET GLOBAL event_scheduler=2;
|
SET GLOBAL event_scheduler=off;
|
||||||
DROP EVENT e_x1;
|
DROP EVENT e_x1;
|
||||||
DROP EVENT e_x2;
|
DROP EVENT e_x2;
|
||||||
DROP DATABASE db_x;
|
DROP DATABASE db_x;
|
||||||
DROP USER pauline@localhost;
|
DROP USER pauline@localhost;
|
||||||
USE events_test;
|
USE events_test;
|
||||||
SET GLOBAL event_scheduler=2;
|
SET GLOBAL event_scheduler=off;
|
||||||
drop event if exists event1;
|
drop event if exists event1;
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1305 Event event1 does not exist
|
Note 1305 Event event1 does not exist
|
||||||
@ -85,13 +85,24 @@ SHOW EVENTS;
|
|||||||
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
|
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
|
events_test event_starts_test root@localhost RECURRING NULL 20 SECOND # # ENABLED
|
||||||
DROP EVENT event_starts_test;
|
DROP EVENT event_starts_test;
|
||||||
|
create table test_nested(a int);
|
||||||
create event e_43 on schedule every 1 second do set @a = 5;
|
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;
|
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 = on;
|
||||||
select db, name, body, status, interval_field, interval_value from mysql.event;
|
select db, name, body, status, interval_field, interval_value from mysql.event;
|
||||||
db name body status interval_field interval_value
|
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 event e_43;
|
||||||
|
drop table test_nested;
|
||||||
"Let's check whether we can use non-qualified names"
|
"Let's check whether we can use non-qualified names"
|
||||||
create table non_qualif(a int);
|
create table non_qualif(a int);
|
||||||
create event non_qualif_ev on schedule every 10 minute do insert into non_qualif values (800219);
|
create event non_qualif_ev on schedule every 10 minute do insert into non_qualif values (800219);
|
||||||
@ -100,7 +111,15 @@ a
|
|||||||
800219
|
800219
|
||||||
drop event non_qualif_ev;
|
drop event non_qualif_ev;
|
||||||
drop table non_qualif;
|
drop table non_qualif;
|
||||||
set global event_scheduler = 2;
|
alter event non_existant rename to non_existant_too;
|
||||||
|
ERROR HY000: Unknown event 'non_existant'
|
||||||
|
set global event_scheduler = off;
|
||||||
|
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);
|
create table t_event3 (a int, b float);
|
||||||
drop event if exists event3;
|
drop event if exists event3;
|
||||||
Warnings:
|
Warnings:
|
||||||
@ -195,6 +214,10 @@ ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
|
|||||||
SHOW EVENTS;
|
SHOW EVENTS;
|
||||||
ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
|
ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
|
||||||
drop event root22;
|
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 root6;
|
||||||
drop event root7;
|
drop event root7;
|
||||||
drop event root8;
|
drop event root8;
|
||||||
@ -285,19 +308,21 @@ 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
|
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
|
events_test e_26 set @a = 5 root@localhost 2017-01-01 00:00:00 DROP
|
||||||
drop event e_26;
|
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'
|
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'
|
ERROR HY000: Incorrect AT value: 'definitely not a datetime'
|
||||||
set names utf8;
|
set names utf8;
|
||||||
create event задачка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1;
|
create event задачка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1;
|
||||||
drop event задачка;
|
drop event задачка;
|
||||||
set event_scheduler=2;
|
set event_scheduler=off;
|
||||||
ERROR HY000: Variable 'event_scheduler' is a GLOBAL variable and should be set with SET GLOBAL
|
ERROR HY000: Variable 'event_scheduler' is a GLOBAL variable and should be set with SET GLOBAL
|
||||||
set global event_scheduler=3;
|
set global event_scheduler=3;
|
||||||
ERROR 42000: Variable 'event_scheduler' can't be set to the value of '3'
|
ERROR 42000: Variable 'event_scheduler' can't be set to the value of '3'
|
||||||
|
set global event_scheduler=disabled;
|
||||||
|
ERROR 42000: Variable 'event_scheduler' can't be set to the value of 'disabled'
|
||||||
"DISABLE the scheduler. Testing that it does not work when the variable is 0"
|
"DISABLE the scheduler. Testing that it does not work when the variable is 0"
|
||||||
set global event_scheduler=2;
|
set global event_scheduler=off;
|
||||||
select definer, name, db from mysql.event;
|
select definer, name, db from mysql.event;
|
||||||
definer name db
|
definer name db
|
||||||
select get_lock("test_lock1", 20);
|
select get_lock("test_lock1", 20);
|
||||||
@ -311,7 +336,6 @@ root@localhost закачка events_test
|
|||||||
"Should be only 1 process"
|
"Should be only 1 process"
|
||||||
select /*1*/ user, host, db, command, state, info from information_schema.processlist where command!='Daemon' and (info is null or info not like '%processlist%') order by info;
|
select /*1*/ user, host, db, command, state, info from information_schema.processlist where command!='Daemon' and (info is null or info not like '%processlist%') order by info;
|
||||||
user host db command state info
|
user host db command state info
|
||||||
event_scheduler localhost NULL Connect Suspended NULL
|
|
||||||
select release_lock("test_lock1");
|
select release_lock("test_lock1");
|
||||||
release_lock("test_lock1")
|
release_lock("test_lock1")
|
||||||
1
|
1
|
||||||
@ -321,7 +345,7 @@ select count(*) from mysql.event;
|
|||||||
count(*)
|
count(*)
|
||||||
0
|
0
|
||||||
"ENABLE the scheduler and get a lock"
|
"ENABLE the scheduler and get a lock"
|
||||||
set global event_scheduler=1;
|
set global event_scheduler=on;
|
||||||
select get_lock("test_lock2", 20);
|
select get_lock("test_lock2", 20);
|
||||||
get_lock("test_lock2", 20)
|
get_lock("test_lock2", 20)
|
||||||
1
|
1
|
||||||
@ -331,7 +355,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"
|
"Should have only 2 processes: the scheduler and the locked event"
|
||||||
select /*2*/ user, host, db, command, state, info from information_schema.processlist where command!='Daemon' and (info is null or info not like '%processlist%') order by info;
|
select /*2*/ user, host, db, command, state, info from information_schema.processlist where command!='Daemon' and (info is null or info not like '%processlist%') order by info;
|
||||||
user host db command state 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)
|
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."
|
||||||
"Release the mutex, the event worker should finish."
|
"Release the mutex, the event worker should finish."
|
||||||
@ -347,18 +371,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"
|
"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 command!='Daemon' and (info is null or info not like '%processlist%') order by info;
|
select /*3*/ user, host, db, command, state, info from information_schema.processlist where command!='Daemon' and (info is null or info not like '%processlist%') order by info;
|
||||||
user host db command state 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)
|
root localhost events_test Connect User lock select get_lock("test_lock2_1", 20)
|
||||||
set global event_scheduler=2;
|
set global event_scheduler=off;
|
||||||
"Should have only our process now:"
|
"Should have only our process now:"
|
||||||
select /*4*/ user, host, db, command, state, info from information_schema.processlist where command!='Daemon' and (info is null or info not like '%processlist%') order by info;
|
select /*4*/ user, host, db, command, state, info from information_schema.processlist where command!='Daemon' and (info is null or info not like '%processlist%') order by info;
|
||||||
user host db command state 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)
|
root localhost events_test Connect User lock select get_lock("test_lock2_1", 20)
|
||||||
drop event закачка21;
|
drop event закачка21;
|
||||||
create table t_16 (s1 int);
|
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;
|
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;
|
drop table t_16;
|
||||||
create event white_space
|
create event white_space
|
||||||
on schedule every 10 hour
|
on schedule every 10 hour
|
||||||
|
@ -17,28 +17,28 @@ DROP EVENT ДОЛЕН_регистър_утф8;
|
|||||||
SET NAMES latin1;
|
SET NAMES latin1;
|
||||||
set @a=3;
|
set @a=3;
|
||||||
CREATE PROCEDURE p_16 () CREATE EVENT e_16 ON SCHEDULE EVERY @a SECOND DO SET @a=5;
|
CREATE PROCEDURE p_16 () CREATE EVENT e_16 ON SCHEDULE EVERY @a SECOND DO SET @a=5;
|
||||||
call p_16();
|
ERROR HY000: Recursivity of EVENT DDL statements is forbidden when body is present
|
||||||
"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;
|
|
||||||
create event e_55 on schedule at 99990101000000 do drop table t;
|
create event e_55 on schedule at 99990101000000 do drop table t;
|
||||||
ERROR HY000: Incorrect AT value: '99990101000000'
|
ERROR HY000: Incorrect AT value: '99990101000000'
|
||||||
create event e_55 on schedule every 10 hour starts 99990101000000 do drop table t;
|
create event e_55 on schedule every 10 hour starts 99990101000000 do drop table t;
|
||||||
ERROR HY000: Incorrect STARTS value: '99990101000000'
|
ERROR HY000: Incorrect STARTS value: '99990101000000'
|
||||||
create event e_55 on schedule every 10 minute ends 99990101000000 do drop table t;
|
create event e_55 on schedule every 10 minute ends 99990101000000 do drop table t;
|
||||||
ERROR HY000: ENDS is either invalid or before STARTS
|
ERROR HY000: ENDS is either invalid or before STARTS
|
||||||
set global event_scheduler=2;
|
create event e_55 on schedule at 10000101000000 do drop table t;
|
||||||
"Wait a bit to settle down"
|
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=off;
|
||||||
delete from mysql.event;
|
delete from mysql.event;
|
||||||
set global event_scheduler= 1;
|
set global event_scheduler= on;
|
||||||
set @old_sql_mode:=@@sql_mode;
|
set @old_sql_mode:=@@sql_mode;
|
||||||
set sql_mode=ansi;
|
set sql_mode=ansi;
|
||||||
select get_lock('test_bug16407', 60);
|
select get_lock('test_bug16407', 60);
|
||||||
@ -50,14 +50,14 @@ select get_lock('test_bug16407', 60);
|
|||||||
drop table "hashed_num";
|
drop table "hashed_num";
|
||||||
end|
|
end|
|
||||||
"Now if everything is fine the event has compiled and is locked
|
"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 command!='Daemon' and (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;
|
||||||
user host db command state info
|
user host db info
|
||||||
event_scheduler localhost NULL Connect Sleeping NULL
|
event_scheduler localhost NULL NULL
|
||||||
root localhost events_test Connect User lock select get_lock('test_bug16407', 60)
|
root localhost events_test select get_lock('test_bug16407', 60)
|
||||||
select release_lock('test_bug16407');
|
select release_lock('test_bug16407');
|
||||||
release_lock('test_bug16407')
|
release_lock('test_bug16407')
|
||||||
1
|
1
|
||||||
set global event_scheduler= 2;
|
set global event_scheduler= off;
|
||||||
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
|
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
|
||||||
event_schema event_name sql_mode
|
event_schema event_name sql_mode
|
||||||
events_test e_16407 REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI
|
events_test e_16407 REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI
|
||||||
@ -68,6 +68,11 @@ select event_schema, event_name, sql_mode from information_schema.events order b
|
|||||||
event_schema event_name sql_mode
|
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
|
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;
|
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"
|
"Another sql_mode test"
|
||||||
set sql_mode="traditional";
|
set sql_mode="traditional";
|
||||||
create table events_smode_test(ev_name char(10), a date) engine=myisam;
|
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
|
create event ee_16407_2 on schedule every 60 second do
|
||||||
begin
|
begin
|
||||||
select get_lock('ee_16407_2', 60) /*ee_16407_2*/;
|
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');
|
insert into events_test.events_smode_test values('ee_16407_2','1980-19-02');
|
||||||
end|
|
end|
|
||||||
insert into events_smode_test values ('test','1980-19-02')|
|
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
|
create event ee_16407_3 on schedule every 60 second do
|
||||||
begin
|
begin
|
||||||
select get_lock('ee_16407_2', 60) /*ee_16407_3*/;
|
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-19');
|
||||||
insert into events_test.events_smode_test values ('ee_16407_3','1980-02-29');
|
insert into events_test.events_smode_test values ('ee_16407_3','1980-02-29');
|
||||||
end|
|
end|
|
||||||
@ -91,6 +98,7 @@ set sql_mode=""|
|
|||||||
create event ee_16407_4 on schedule every 60 second do
|
create event ee_16407_4 on schedule every 60 second do
|
||||||
begin
|
begin
|
||||||
select get_lock('ee_16407_2', 60) /*ee_16407_4*/;
|
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');
|
insert into events_test.events_smode_test values ('ee_16407_4','10-11-1956');
|
||||||
end|
|
end|
|
||||||
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
|
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
|
||||||
@ -98,24 +106,19 @@ 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_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_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
|
events_test ee_16407_4
|
||||||
set sql_mode="ansi";
|
select /*2*/ user, host, db, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||||
select get_lock('ee_16407_2', 60);
|
user host db info
|
||||||
get_lock('ee_16407_2', 60)
|
event_scheduler localhost NULL NULL
|
||||||
1
|
root localhost events_test select get_lock('ee_16407_2', 60)
|
||||||
set global event_scheduler= 1;
|
root localhost events_test select get_lock('ee_16407_2', 60)
|
||||||
select /*2*/ user, host, db, command, state, info from information_schema.processlist where command!='Daemon' and (info is null or info not like '%processlist%') order by info;
|
root localhost events_test select get_lock('ee_16407_2', 60)
|
||||||
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 release_lock('ee_16407_2');
|
select release_lock('ee_16407_2');
|
||||||
release_lock('ee_16407_2')
|
release_lock('ee_16407_2')
|
||||||
1
|
1
|
||||||
select /*3*/ user, host, db, command, state, info from information_schema.processlist where command!='Daemon' and (info is null or info not like '%processlist%') order by info;
|
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 command state info
|
user host db info
|
||||||
event_scheduler localhost NULL Connect Sleeping NULL
|
event_scheduler localhost NULL NULL
|
||||||
set global event_scheduler= 2;
|
set global event_scheduler= off;
|
||||||
select * from events_smode_test order by ev_name, a;
|
select * from events_smode_test order by ev_name, a;
|
||||||
ev_name a
|
ev_name a
|
||||||
ee_16407_3 1980-02-19
|
ee_16407_3 1980-02-19
|
||||||
@ -132,37 +135,39 @@ drop event ee_16407_3;
|
|||||||
drop event ee_16407_4;
|
drop event ee_16407_4;
|
||||||
"And now one last test regarding sql_mode and call of SP from an event"
|
"And now one last test regarding sql_mode and call of SP from an event"
|
||||||
delete from events_smode_test;
|
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= on;
|
||||||
set sql_mode='traditional';
|
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_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 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
|
create event ee_16407_5 on schedule every 60 second do
|
||||||
begin
|
begin
|
||||||
select get_lock('ee_16407_5', 60) /*ee_16407_5*/;
|
select get_lock('ee_16407_5', 60) /*ee_16407_5*/;
|
||||||
|
select release_lock('ee_16407_5');
|
||||||
call events_test.ee_16407_5_pendant();
|
call events_test.ee_16407_5_pendant();
|
||||||
end|
|
end|
|
||||||
create event ee_16407_6 on schedule every 60 second do
|
create event ee_16407_6 on schedule every 60 second do
|
||||||
begin
|
begin
|
||||||
select get_lock('ee_16407_5', 60) /*ee_16407_6*/;
|
select get_lock('ee_16407_5', 60) /*ee_16407_6*/;
|
||||||
|
select release_lock('ee_16407_5');
|
||||||
call events_test.ee_16407_6_pendant();
|
call events_test.ee_16407_6_pendant();
|
||||||
end|
|
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"
|
"Should have 2 locked processes"
|
||||||
select /*4*/ user, host, db, command, state, info from information_schema.processlist where command!='Daemon' and (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;
|
||||||
user host db command state info
|
user host db info
|
||||||
event_scheduler localhost NULL Connect Sleeping NULL
|
event_scheduler localhost NULL NULL
|
||||||
root localhost events_test Connect User lock select get_lock('ee_16407_5', 60)
|
root localhost events_test select get_lock('ee_16407_5', 60)
|
||||||
root localhost events_test Connect User lock select get_lock('ee_16407_5', 60)
|
root localhost events_test select get_lock('ee_16407_5', 60)
|
||||||
select release_lock('ee_16407_5');
|
select release_lock('ee_16407_5');
|
||||||
release_lock('ee_16407_5')
|
release_lock('ee_16407_5')
|
||||||
1
|
1
|
||||||
"Should have 0 processes locked"
|
"Should have 0 processes locked"
|
||||||
select /*5*/ user, host, db, command, state, info from information_schema.processlist where command!='Daemon' and (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;
|
||||||
user host db command state info
|
user host db info
|
||||||
event_scheduler localhost NULL Connect Sleeping NULL
|
event_scheduler localhost NULL NULL
|
||||||
select * from events_smode_test order by ev_name, a;
|
select * from events_smode_test order by ev_name, a;
|
||||||
ev_name a
|
ev_name a
|
||||||
ee_16407_6 2004-02-29
|
ee_16407_6 2004-02-29
|
||||||
@ -175,10 +180,10 @@ drop event ee_16407_5;
|
|||||||
drop event ee_16407_6;
|
drop event ee_16407_6;
|
||||||
drop procedure ee_16407_5_pendant;
|
drop procedure ee_16407_5_pendant;
|
||||||
drop procedure ee_16407_6_pendant;
|
drop procedure ee_16407_6_pendant;
|
||||||
set global event_scheduler= 2;
|
set global event_scheduler= off;
|
||||||
drop table events_smode_test;
|
drop table events_smode_test;
|
||||||
set sql_mode=@old_sql_mode;
|
set sql_mode=@old_sql_mode;
|
||||||
set global event_scheduler=2;
|
set global event_scheduler=off;
|
||||||
delete from mysql.user where User like 'mysqltest_%';
|
delete from mysql.user where User like 'mysqltest_%';
|
||||||
delete from mysql.db where User like 'mysqltest_%';
|
delete from mysql.db where User like 'mysqltest_%';
|
||||||
flush privileges;
|
flush privileges;
|
||||||
@ -201,4 +206,12 @@ events_test mysqltest_user1 mysqltest_user1@localhost RECURRING ENABLED
|
|||||||
drop event events_test.mysqltest_user1;
|
drop event events_test.mysqltest_user1;
|
||||||
drop user mysqltest_user1@localhost;
|
drop user mysqltest_user1@localhost;
|
||||||
drop database mysqltest_db1;
|
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;
|
drop database events_test;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
create database if not exists events_test;
|
CREATE DATABASE IF NOT EXISTS events_test;
|
||||||
use events_test;
|
USE events_test;
|
||||||
"We use procedure here because its statements won't be logged into the general log"
|
"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"
|
"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"
|
"the test suite is run in normal mode or with --ps-protocol"
|
||||||
@ -8,21 +8,24 @@ BEGIN
|
|||||||
SELECT user_host, argument FROM mysql.general_log WHERE argument LIKE '%alabala%';
|
SELECT user_host, argument FROM mysql.general_log WHERE argument LIKE '%alabala%';
|
||||||
END|
|
END|
|
||||||
"Check General Query Log"
|
"Check General Query Log"
|
||||||
SET GLOBAL event_scheduler=2;
|
CALL select_general_log();
|
||||||
create event log_general on schedule every 1 minute do SELect 'alabala', sleep(3) from dual;
|
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=on;
|
||||||
TRUNCATE mysql.general_log;
|
TRUNCATE mysql.general_log;
|
||||||
"1 row, the current statement!"
|
CREATE EVENT log_general ON SCHEDULE EVERY 1 MINUTE DO SELECT 'alabala', SLEEP(1) FROM DUAL;
|
||||||
call select_general_log();
|
|
||||||
user_host argument
|
|
||||||
SET GLOBAL event_scheduler=1;
|
|
||||||
"Wait the scheduler to start"
|
"Wait the scheduler to start"
|
||||||
"Should see 3 rows - the 'SELect' is in the middle. The other two are selects from general_log"
|
"Should see 2 rows - the 'SELECT' is in the middle. The other two are selects from general_log"
|
||||||
call select_general_log();
|
CALL select_general_log();
|
||||||
user_host argument
|
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 PROCEDURE select_general_log;
|
||||||
DROP EVENT log_general;
|
DROP EVENT log_general;
|
||||||
SET GLOBAL event_scheduler=2;
|
SET GLOBAL event_scheduler=off;
|
||||||
"Check slow query log"
|
"Check slow query log"
|
||||||
"Save the values"
|
"Save the values"
|
||||||
SET @old_global_long_query_time:=(select get_value());
|
SET @old_global_long_query_time:=(select get_value());
|
||||||
@ -52,19 +55,20 @@ TRUNCATE mysql.slow_log;
|
|||||||
CREATE TABLE slow_event_test (slo_val tinyint, val tinyint);
|
CREATE TABLE slow_event_test (slo_val tinyint, val tinyint);
|
||||||
SET SESSION long_query_time=1;
|
SET SESSION long_query_time=1;
|
||||||
"This won't go to the slow log"
|
"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;
|
SELECT * FROM slow_event_test;
|
||||||
slo_val val
|
slo_val val
|
||||||
SET GLOBAL event_scheduler=1;
|
SET SESSION long_query_time=1;
|
||||||
|
SET GLOBAL event_scheduler=on;
|
||||||
|
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"
|
"Sleep some more time than the actual event run will take"
|
||||||
SHOW VARIABLES LIKE 'event_scheduler';
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
event_scheduler 1
|
event_scheduler ON
|
||||||
"Check our table. Should see 1 row"
|
"Check our table. Should see 1 row"
|
||||||
SELECT * FROM slow_event_test;
|
SELECT * FROM slow_event_test;
|
||||||
slo_val val
|
slo_val val
|
||||||
4 0
|
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;
|
SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
|
||||||
user_host query_time db sql_text
|
user_host query_time db sql_text
|
||||||
"This should go to the slow log"
|
"This should go to the slow log"
|
||||||
@ -89,4 +93,4 @@ TRUNCATE mysql.slow_log;
|
|||||||
DROP TABLE slow_event_test;
|
DROP TABLE slow_event_test;
|
||||||
SET GLOBAL long_query_time =@old_global_long_query_time;
|
SET GLOBAL long_query_time =@old_global_long_query_time;
|
||||||
SET SESSION long_query_time =@old_session_long_query_time;
|
SET SESSION long_query_time =@old_session_long_query_time;
|
||||||
drop database events_test;
|
DROP DATABASE events_test;
|
||||||
|
12
mysql-test/r/events_restart_phase1.result
Normal file
12
mysql-test/r/events_restart_phase1.result
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
create database if not exists mysqltest_events_test;
|
||||||
|
use mysqltest_events_test;
|
||||||
|
set global event_scheduler=off;
|
||||||
|
create table execution_log(name char(10));
|
||||||
|
create event abc1 on schedule every 1 second do insert into execution_log value('abc1');
|
||||||
|
create event abc2 on schedule every 1 second do insert into execution_log value('abc2');
|
||||||
|
create event abc3 on schedule every 1 second do insert into execution_log value('abc3');
|
||||||
|
select name from execution_log;
|
||||||
|
name
|
||||||
|
insert into mysql.event values ('db1','bad','select 42','root@localhost',NULL,1000,'MICROSECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment1');
|
||||||
|
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"
|
12
mysql-test/r/events_restart_phase3.result
Normal file
12
mysql-test/r/events_restart_phase3.result
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use mysqltest_events_test;
|
||||||
|
"Should get 3 rows : abc1, abc2, abc3
|
||||||
|
select distinct name from execution_log order by name;
|
||||||
|
name
|
||||||
|
abc1
|
||||||
|
abc2
|
||||||
|
abc3
|
||||||
|
drop event abc1;
|
||||||
|
drop event abc2;
|
||||||
|
drop event abc3;
|
||||||
|
drop table execution_log;
|
||||||
|
drop database mysqltest_events_test;
|
@ -1,12 +1,47 @@
|
|||||||
CREATE DATABASE IF NOT EXISTS events_test;
|
CREATE DATABASE IF NOT EXISTS events_test;
|
||||||
USE events_test;
|
USE events_test;
|
||||||
|
SET GLOBAL event_scheduler=OFF;
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
Variable_name Value
|
||||||
|
event_scheduler OFF
|
||||||
|
SET GLOBAL event_scheduler=1;
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
Variable_name Value
|
||||||
|
event_scheduler ON
|
||||||
|
SET GLOBAL event_scheduler=0;
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
Variable_name Value
|
||||||
|
event_scheduler OFF
|
||||||
|
SET GLOBAL event_scheduler=ON;
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
Variable_name Value
|
||||||
|
event_scheduler ON
|
||||||
|
SET GLOBAL event_scheduler=DISABLED;
|
||||||
|
ERROR 42000: Variable 'event_scheduler' can't be set to the value of 'DISABLED'
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
Variable_name Value
|
||||||
|
event_scheduler ON
|
||||||
|
SET GLOBAL event_scheduler=-1;
|
||||||
|
ERROR 42000: Variable 'event_scheduler' can't be set to the value of '-1'
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
Variable_name Value
|
||||||
|
event_scheduler ON
|
||||||
|
SET GLOBAL event_scheduler=2;
|
||||||
|
ERROR 42000: Variable 'event_scheduler' can't be set to the value of '2'
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
Variable_name Value
|
||||||
|
event_scheduler ON
|
||||||
|
SET GLOBAL event_scheduler=5;
|
||||||
|
ERROR 42000: Variable 'event_scheduler' can't be set to the value of '5'
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
Variable_name Value
|
||||||
|
event_scheduler ON
|
||||||
CREATE TABLE table_1(a int);
|
CREATE TABLE table_1(a int);
|
||||||
CREATE TABLE table_2(a int);
|
CREATE TABLE table_2(a int);
|
||||||
CREATE TABLE table_3(a int);
|
CREATE TABLE table_3(a int);
|
||||||
CREATE TABLE table_4(a int);
|
CREATE TABLE table_4(a int);
|
||||||
CREATE TABLE T19170(s1 TIMESTAMP);
|
CREATE TABLE T19170(s1 TIMESTAMP);
|
||||||
SET GLOBAL event_scheduler=1;
|
SET GLOBAL event_scheduler=ON;
|
||||||
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 two_sec ON SCHEDULE EVERY 2 SECOND DO INSERT INTO table_1 VALUES(1);
|
||||||
CREATE EVENT start_n_end
|
CREATE EVENT start_n_end
|
||||||
ON SCHEDULE EVERY 1 SECOND
|
ON SCHEDULE EVERY 1 SECOND
|
||||||
@ -39,17 +74,12 @@ DROP EVENT start_n_end;
|
|||||||
DROP EVENT only_one_time;
|
DROP EVENT only_one_time;
|
||||||
ERROR HY000: Unknown event 'only_one_time'
|
ERROR HY000: Unknown event 'only_one_time'
|
||||||
"Should be preserved"
|
"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
|
EVENT_NAME STATUS
|
||||||
E19170 ENABLED
|
|
||||||
two_time DISABLED
|
two_time DISABLED
|
||||||
DROP EVENT two_time;
|
DROP EVENT two_time;
|
||||||
DROP TABLE table_1;
|
DROP TABLE table_1;
|
||||||
DROP TABLE table_2;
|
DROP TABLE table_2;
|
||||||
DROP TABLE table_3;
|
DROP TABLE table_3;
|
||||||
DROP TABLE table_4;
|
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;
|
DROP DATABASE events_test;
|
||||||
|
@ -32,15 +32,15 @@ USE events_conn1_test2;
|
|||||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
||||||
COUNT(*)
|
COUNT(*)
|
||||||
50
|
50
|
||||||
SET GLOBAL event_scheduler=1;
|
SET GLOBAL event_scheduler=on;
|
||||||
DROP DATABASE events_conn1_test2;
|
DROP DATABASE events_conn1_test2;
|
||||||
SET GLOBAL event_scheduler=2;
|
SET GLOBAL event_scheduler=off;
|
||||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
||||||
COUNT(*)
|
COUNT(*)
|
||||||
0
|
0
|
||||||
CREATE DATABASE events_conn1_test3;
|
CREATE DATABASE events_conn1_test3;
|
||||||
USE events_conn1_test3;
|
USE events_conn1_test3;
|
||||||
SET GLOBAL event_scheduler=1;
|
SET GLOBAL event_scheduler=on;
|
||||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test3';
|
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test3';
|
||||||
COUNT(*)
|
COUNT(*)
|
||||||
50
|
50
|
||||||
@ -55,9 +55,9 @@ DROP DATABASE events_conn2_db;
|
|||||||
DROP DATABASE events_conn3_db;
|
DROP DATABASE events_conn3_db;
|
||||||
DROP DATABASE events_conn1_test2;
|
DROP DATABASE events_conn1_test2;
|
||||||
DROP DATABASE events_conn1_test3;
|
DROP DATABASE events_conn1_test3;
|
||||||
SET GLOBAL event_scheduler=2;
|
SET GLOBAL event_scheduler=off;
|
||||||
DROP DATABASE events_conn1_test4;
|
DROP DATABASE events_conn1_test4;
|
||||||
SET GLOBAL event_scheduler=1;
|
SET GLOBAL event_scheduler=on;
|
||||||
USE events_test;
|
USE events_test;
|
||||||
DROP TABLE fill_it1;
|
DROP TABLE fill_it1;
|
||||||
DROP TABLE fill_it2;
|
DROP TABLE fill_it2;
|
||||||
|
@ -2,5 +2,4 @@ prepare stmt1 from ' SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND!
|
|||||||
execute stmt1;
|
execute stmt1;
|
||||||
ID USER HOST DB COMMAND TIME STATE INFO
|
ID USER HOST DB COMMAND TIME STATE INFO
|
||||||
number root localhost test Query time preparing SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND!='Daemon'
|
number root localhost test Query time preparing SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND!='Daemon'
|
||||||
number event_scheduler localhost NULL Connect time Suspended NULL
|
|
||||||
deallocate prepare stmt1;
|
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;
|
show processlist;
|
||||||
Id User Host db Command Time State Info
|
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>
|
||||||
<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();
|
call bug9486();
|
||||||
show processlist;
|
show processlist;
|
||||||
Id User Host db Command Time State Info
|
Id User Host db Command Time State Info
|
||||||
# event_scheduler localhost NULL Connect # Suspended NULL
|
|
||||||
# root localhost test Sleep # NULL
|
# root localhost test Sleep # NULL
|
||||||
# root localhost test Query # Locked update t1, t2 set val= 1 where id1=id2
|
# root localhost test Query # Locked update t1, t2 set val= 1 where id1=id2
|
||||||
# root localhost test Query # NULL show processlist
|
# root localhost test Query # NULL show processlist
|
||||||
|
@ -18,11 +18,9 @@ show processlist;
|
|||||||
end|
|
end|
|
||||||
call bug4902_2()|
|
call bug4902_2()|
|
||||||
Id User Host db Command Time State Info
|
Id User Host db Command Time State Info
|
||||||
# event_scheduler localhost NULL Connect # Suspended NULL
|
|
||||||
# root localhost test Query # NULL show processlist
|
# root localhost test Query # NULL show processlist
|
||||||
call bug4902_2()|
|
call bug4902_2()|
|
||||||
Id User Host db Command Time State Info
|
Id User Host db Command Time State Info
|
||||||
# event_scheduler localhost NULL Connect # Suspended NULL
|
|
||||||
# root localhost test Query # NULL show processlist
|
# root localhost test Query # NULL show processlist
|
||||||
drop procedure bug4902_2|
|
drop procedure bug4902_2|
|
||||||
drop table if exists t1|
|
drop table if exists t1|
|
||||||
|
@ -52,22 +52,22 @@ drop table t1;
|
|||||||
FLUSH STATUS;
|
FLUSH STATUS;
|
||||||
SHOW STATUS LIKE 'max_used_connections';
|
SHOW STATUS LIKE 'max_used_connections';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Max_used_connections 2
|
Max_used_connections 1
|
||||||
SET @save_thread_cache_size=@@thread_cache_size;
|
SET @save_thread_cache_size=@@thread_cache_size;
|
||||||
SET GLOBAL thread_cache_size=3;
|
SET GLOBAL thread_cache_size=3;
|
||||||
SHOW STATUS LIKE 'max_used_connections';
|
SHOW STATUS LIKE 'max_used_connections';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Max_used_connections 4
|
Max_used_connections 3
|
||||||
FLUSH STATUS;
|
FLUSH STATUS;
|
||||||
SHOW STATUS LIKE 'max_used_connections';
|
SHOW STATUS LIKE 'max_used_connections';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
|
Max_used_connections 2
|
||||||
|
SHOW STATUS LIKE 'max_used_connections';
|
||||||
|
Variable_name Value
|
||||||
Max_used_connections 3
|
Max_used_connections 3
|
||||||
SHOW STATUS LIKE 'max_used_connections';
|
SHOW STATUS LIKE 'max_used_connections';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Max_used_connections 4
|
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;
|
SET GLOBAL thread_cache_size=@save_thread_cache_size;
|
||||||
show status like 'com_show_status';
|
show status like 'com_show_status';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
|
@ -18,10 +18,10 @@ CREATE EVENT e_x2 ON SCHEDULE EVERY 1 SECOND DO DROP TABLE x_table;
|
|||||||
connection default;
|
connection default;
|
||||||
SHOW DATABASES LIKE 'db_x';
|
SHOW DATABASES LIKE 'db_x';
|
||||||
SET GLOBAL event_scheduler=1;
|
SET GLOBAL event_scheduler=1;
|
||||||
--sleep 1.5
|
--sleep 1.2
|
||||||
SHOW DATABASES LIKE 'db_x';
|
SHOW DATABASES LIKE 'db_x';
|
||||||
SHOW TABLES FROM db_x;
|
SHOW TABLES FROM db_x;
|
||||||
SET GLOBAL event_scheduler=2;
|
SET GLOBAL event_scheduler=off;
|
||||||
connection priv_conn;
|
connection priv_conn;
|
||||||
DROP EVENT e_x1;
|
DROP EVENT e_x1;
|
||||||
DROP EVENT e_x2;
|
DROP EVENT e_x2;
|
||||||
@ -33,7 +33,7 @@ USE events_test;
|
|||||||
#
|
#
|
||||||
# END: BUG #17289 Events: missing privilege check for drop database
|
# END: BUG #17289 Events: missing privilege check for drop database
|
||||||
#
|
#
|
||||||
SET GLOBAL event_scheduler=2;
|
SET GLOBAL event_scheduler=off;
|
||||||
drop event if exists event1;
|
drop event if exists event1;
|
||||||
create event event1 on schedule every 15 minute starts now() ends date_add(now(), interval 5 hour) DO begin end;
|
create event event1 on schedule every 15 minute starts now() ends date_add(now(), interval 5 hour) DO begin end;
|
||||||
alter event event1 rename to event2 enable;
|
alter event event1 rename to event2 enable;
|
||||||
@ -81,23 +81,42 @@ SHOW EVENTS;
|
|||||||
DROP EVENT event_starts_test;
|
DROP EVENT event_starts_test;
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
create table test_nested(a int);
|
||||||
create event e_43 on schedule every 1 second do set @a = 5;
|
create event e_43 on schedule every 1 second do set @a = 5;
|
||||||
set global event_scheduler = 1;
|
--error ER_EVENT_RECURSIVITY_FORBIDDEN
|
||||||
--sleep 2
|
|
||||||
alter event e_43 do alter event e_43 do set @a = 4;
|
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 = on;
|
||||||
|
--sleep 3
|
||||||
select db, name, body, status, interval_field, interval_value from mysql.event;
|
select db, name, body, status, interval_field, interval_value from mysql.event;
|
||||||
drop event e_43;
|
drop event e_43;
|
||||||
--sleep 1
|
drop table test_nested;
|
||||||
|
|
||||||
--echo "Let's check whether we can use non-qualified names"
|
--echo "Let's check whether we can use non-qualified names"
|
||||||
create table non_qualif(a int);
|
create table non_qualif(a int);
|
||||||
create event non_qualif_ev on schedule every 10 minute do insert into non_qualif values (800219);
|
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;
|
select * from non_qualif;
|
||||||
drop event non_qualif_ev;
|
drop event non_qualif_ev;
|
||||||
drop table non_qualif;
|
drop table non_qualif;
|
||||||
set global event_scheduler = 2;
|
|
||||||
|
--error ER_EVENT_DOES_NOT_EXIST
|
||||||
|
alter event non_existant rename to non_existant_too;
|
||||||
|
|
||||||
|
set global event_scheduler = off;
|
||||||
|
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);
|
create table t_event3 (a int, b float);
|
||||||
drop event if exists event3;
|
drop event if exists event3;
|
||||||
@ -156,6 +175,10 @@ show create event root22;
|
|||||||
--error ER_NOT_SUPPORTED_YET
|
--error ER_NOT_SUPPORTED_YET
|
||||||
SHOW EVENTS;
|
SHOW EVENTS;
|
||||||
drop event root22;
|
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 root6;
|
||||||
drop event root7;
|
drop event root7;
|
||||||
drop event root8;
|
drop event root8;
|
||||||
@ -201,34 +224,34 @@ SHOW EVENTS;
|
|||||||
CREATE TABLE event_like LIKE mysql.event;
|
CREATE TABLE event_like LIKE mysql.event;
|
||||||
INSERT INTO event_like SELECT * FROM mysql.event;
|
INSERT INTO event_like SELECT * FROM mysql.event;
|
||||||
#sleep a bit or we won't catch the change of time
|
#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 '';
|
ALTER TABLE mysql.event MODIFY db char(64) character set cp1251 default '';
|
||||||
--error ER_CANNOT_LOAD_FROM_TABLE
|
--error ER_CANNOT_LOAD_FROM_TABLE
|
||||||
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
||||||
ALTER TABLE mysql.event MODIFY db char(20) character set utf8 collate utf8_bin default '';
|
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
|
#wait a bit or we won't see the difference because of seconds resolution
|
||||||
--sleep 1
|
--sleep 1.1
|
||||||
SHOW CREATE TABLE mysql.event;
|
SHOW CREATE TABLE mysql.event;
|
||||||
--error ER_CANNOT_LOAD_FROM_TABLE
|
--error ER_CANNOT_LOAD_FROM_TABLE
|
||||||
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
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 '';
|
ALTER TABLE mysql.event MODIFY db char(64) character set utf8 collate utf8_bin default '';
|
||||||
--sleep 1
|
--sleep 1.1
|
||||||
--echo "This should work"
|
--echo "This should work"
|
||||||
--replace_column 8 # 9 #
|
--replace_column 8 # 9 #
|
||||||
SHOW EVENTS;
|
SHOW EVENTS;
|
||||||
--sleep 1
|
--sleep 1.1
|
||||||
ALTER TABLE mysql.event MODIFY db char(64) character set cp1251 default '';
|
ALTER TABLE mysql.event MODIFY db char(64) character set cp1251 default '';
|
||||||
--error ER_CANNOT_LOAD_FROM_TABLE
|
--error ER_CANNOT_LOAD_FROM_TABLE
|
||||||
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
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 '';
|
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
|
--error ER_CANNOT_LOAD_FROM_TABLE
|
||||||
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
||||||
--sleep 1
|
--sleep 1.1
|
||||||
ALTER TABLE mysql.event DROP comment, DROP starts;
|
ALTER TABLE mysql.event DROP comment, DROP starts;
|
||||||
--sleep 1
|
--sleep 1.1
|
||||||
--error ER_COL_COUNT_DOESNT_MATCH_CORRUPTED
|
--error ER_COL_COUNT_DOESNT_MATCH_CORRUPTED
|
||||||
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
|
||||||
DROP TABLE mysql.event;
|
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;
|
select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event;
|
||||||
drop event e_26;
|
drop event e_26;
|
||||||
--error ER_WRONG_VALUE
|
--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
|
--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;
|
set names utf8;
|
||||||
create event задачка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1;
|
create event задачка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1;
|
||||||
@ -256,13 +279,15 @@ drop event задачка;
|
|||||||
|
|
||||||
# event_scheduler is a global var
|
# event_scheduler is a global var
|
||||||
--error ER_GLOBAL_VARIABLE
|
--error ER_GLOBAL_VARIABLE
|
||||||
set event_scheduler=2;
|
set event_scheduler=off;
|
||||||
# event_scheduler could be only either 1 or 2
|
# event_scheduler could be only either 1 or 2
|
||||||
--error ER_WRONG_VALUE_FOR_VAR
|
--error ER_WRONG_VALUE_FOR_VAR
|
||||||
set global event_scheduler=3;
|
set global event_scheduler=3;
|
||||||
|
--error ER_WRONG_VALUE_FOR_VAR
|
||||||
|
set global event_scheduler=disabled;
|
||||||
|
|
||||||
--echo "DISABLE the scheduler. Testing that it does not work when the variable is 0"
|
--echo "DISABLE the scheduler. Testing that it does not work when the variable is 0"
|
||||||
set global event_scheduler=2;
|
set global event_scheduler=off;
|
||||||
select definer, name, db from mysql.event;
|
select definer, name, db from mysql.event;
|
||||||
select get_lock("test_lock1", 20);
|
select get_lock("test_lock1", 20);
|
||||||
create event закачка on schedule every 10 hour do select get_lock("test_lock1", 20);
|
create event закачка on schedule every 10 hour do select get_lock("test_lock1", 20);
|
||||||
@ -280,7 +305,7 @@ select count(*) from mysql.event;
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
--echo "ENABLE the scheduler and get a lock"
|
--echo "ENABLE the scheduler and get a lock"
|
||||||
set global event_scheduler=1;
|
set global event_scheduler=on;
|
||||||
select get_lock("test_lock2", 20);
|
select get_lock("test_lock2", 20);
|
||||||
--echo "Create an event which tries to acquire a mutex. The event locks on the mutex"
|
--echo "Create an event which tries to acquire a mutex. The event locks on the mutex"
|
||||||
create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20);
|
create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20);
|
||||||
@ -306,7 +331,8 @@ create event закачка21 on schedule every 10 hour do select get_lock("test
|
|||||||
--sleep 1
|
--sleep 1
|
||||||
--echo "Should have only 3 processes: the scheduler, our conn and the locked event"
|
--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 command!='Daemon' and (info is null or info not like '%processlist%') order by info;
|
select /*3*/ user, host, db, command, state, info from information_schema.processlist where command!='Daemon' and (info is null or info not like '%processlist%') order by info;
|
||||||
set global event_scheduler=2;
|
set global event_scheduler=off;
|
||||||
|
--sleep 0.8
|
||||||
--echo "Should have only our process now:"
|
--echo "Should have only our process now:"
|
||||||
select /*4*/ user, host, db, command, state, info from information_schema.processlist where command!='Daemon' and (info is null or info not like '%processlist%') order by info;
|
select /*4*/ user, host, db, command, state, info from information_schema.processlist where command!='Daemon' and (info is null or info not like '%processlist%') order by info;
|
||||||
drop event закачка21;
|
drop event закачка21;
|
||||||
@ -315,7 +341,7 @@ drop event закачка21;
|
|||||||
# Bug #16410 Events: CREATE EVENT is legal in a CREATE TRIGGER statement
|
# Bug #16410 Events: CREATE EVENT is legal in a CREATE TRIGGER statement
|
||||||
#
|
#
|
||||||
create table t_16 (s1 int);
|
create table t_16 (s1 int);
|
||||||
--error 1422
|
--error ER_EVENT_RECURSIVITY_FORBIDDEN
|
||||||
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;
|
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;
|
drop table t_16;
|
||||||
#
|
#
|
||||||
@ -372,7 +398,7 @@ drop event e1;
|
|||||||
##drop event закачка4;
|
##drop event закачка4;
|
||||||
##select release_lock("test_lock4");
|
##select release_lock("test_lock4");
|
||||||
|
|
||||||
##set global event_scheduler=2;
|
##set global event_scheduler=off;
|
||||||
##select sleep(2);
|
##select sleep(2);
|
||||||
##--replace_column 1 # 6 #
|
##--replace_column 1 # 6 #
|
||||||
##show processlist;
|
##show processlist;
|
||||||
|
@ -30,19 +30,8 @@ SET NAMES latin1;
|
|||||||
# START - BUG#16408: Events: crash for an event in a procedure
|
# START - BUG#16408: Events: crash for an event in a procedure
|
||||||
#
|
#
|
||||||
set @a=3;
|
set @a=3;
|
||||||
|
--error ER_EVENT_RECURSIVITY_FORBIDDEN
|
||||||
CREATE PROCEDURE p_16 () CREATE EVENT e_16 ON SCHEDULE EVERY @a SECOND DO SET @a=5;
|
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
|
# 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;
|
create event e_55 on schedule every 10 hour starts 99990101000000 do drop table t;
|
||||||
--error ER_EVENT_ENDS_BEFORE_STARTS
|
--error ER_EVENT_ENDS_BEFORE_STARTS
|
||||||
create event e_55 on schedule every 10 minute ends 99990101000000 do drop table t;
|
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
|
# End - 16396: Events: Distant-future dates become past dates
|
||||||
#
|
#
|
||||||
@ -63,11 +65,9 @@ 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
|
# Start - 16407: Events: Changes in sql_mode won't be taken into account
|
||||||
#
|
#
|
||||||
set global event_scheduler=2;
|
set global event_scheduler=off;
|
||||||
--echo "Wait a bit to settle down"
|
|
||||||
--sleep 1
|
|
||||||
delete from mysql.event;
|
delete from mysql.event;
|
||||||
set global event_scheduler= 1;
|
set global event_scheduler= on;
|
||||||
set @old_sql_mode:=@@sql_mode;
|
set @old_sql_mode:=@@sql_mode;
|
||||||
set sql_mode=ansi;
|
set sql_mode=ansi;
|
||||||
select get_lock('test_bug16407', 60);
|
select get_lock('test_bug16407', 60);
|
||||||
@ -78,11 +78,13 @@ begin
|
|||||||
drop table "hashed_num";
|
drop table "hashed_num";
|
||||||
end|
|
end|
|
||||||
delimiter ;|
|
delimiter ;|
|
||||||
--sleep 1
|
--sleep 0.8
|
||||||
--echo "Now if everything is fine the event has compiled and is locked
|
--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 command!='Daemon' and (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');
|
select release_lock('test_bug16407');
|
||||||
set global event_scheduler= 2;
|
|
||||||
|
set global event_scheduler= off;
|
||||||
|
|
||||||
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
|
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"
|
--echo "Let's check whether we change the sql_mode on ALTER EVENT"
|
||||||
set sql_mode='traditional';
|
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;
|
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
|
||||||
drop event e_16407;
|
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"
|
--echo "Another sql_mode test"
|
||||||
set sql_mode="traditional";
|
set sql_mode="traditional";
|
||||||
create table events_smode_test(ev_name char(10), a date) engine=myisam;
|
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
|
create event ee_16407_2 on schedule every 60 second do
|
||||||
begin
|
begin
|
||||||
select get_lock('ee_16407_2', 60) /*ee_16407_2*/;
|
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');
|
insert into events_test.events_smode_test values('ee_16407_2','1980-19-02');
|
||||||
end|
|
end|
|
||||||
--error ER_TRUNCATED_WRONG_VALUE
|
--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
|
create event ee_16407_3 on schedule every 60 second do
|
||||||
begin
|
begin
|
||||||
select get_lock('ee_16407_2', 60) /*ee_16407_3*/;
|
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-19');
|
||||||
insert into events_test.events_smode_test values ('ee_16407_3','1980-02-29');
|
insert into events_test.events_smode_test values ('ee_16407_3','1980-02-29');
|
||||||
end|
|
end|
|
||||||
@ -114,19 +122,17 @@ set sql_mode=""|
|
|||||||
create event ee_16407_4 on schedule every 60 second do
|
create event ee_16407_4 on schedule every 60 second do
|
||||||
begin
|
begin
|
||||||
select get_lock('ee_16407_2', 60) /*ee_16407_4*/;
|
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');
|
insert into events_test.events_smode_test values ('ee_16407_4','10-11-1956');
|
||||||
end|
|
end|
|
||||||
delimiter ;|
|
delimiter ;|
|
||||||
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
|
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
|
||||||
set sql_mode="ansi";
|
|
||||||
select get_lock('ee_16407_2', 60);
|
|
||||||
set global event_scheduler= 1;
|
|
||||||
--sleep 1
|
--sleep 1
|
||||||
select /*2*/ user, host, db, command, state, info from information_schema.processlist where command!='Daemon' and (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');
|
select release_lock('ee_16407_2');
|
||||||
--sleep 2
|
--sleep 1.2
|
||||||
select /*3*/ user, host, db, command, state, info from information_schema.processlist where command!='Daemon' and (info is null or info not like '%processlist%') order by info;
|
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;
|
set global event_scheduler= off;
|
||||||
select * from events_smode_test order by ev_name, a;
|
select * from events_smode_test order by ev_name, a;
|
||||||
--echo "OK, last check before we drop them"
|
--echo "OK, last check before we drop them"
|
||||||
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
|
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
|
||||||
@ -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"
|
--echo "And now one last test regarding sql_mode and call of SP from an event"
|
||||||
delete from events_smode_test;
|
delete from events_smode_test;
|
||||||
|
set sql_mode='ansi';
|
||||||
|
select get_lock('ee_16407_5', 60);
|
||||||
|
|
||||||
|
set global event_scheduler= on;
|
||||||
|
|
||||||
set sql_mode='traditional';
|
set sql_mode='traditional';
|
||||||
delimiter |;
|
delimiter |;
|
||||||
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_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
|
create event ee_16407_5 on schedule every 60 second do
|
||||||
begin
|
begin
|
||||||
select get_lock('ee_16407_5', 60) /*ee_16407_5*/;
|
select get_lock('ee_16407_5', 60) /*ee_16407_5*/;
|
||||||
|
select release_lock('ee_16407_5');
|
||||||
call events_test.ee_16407_5_pendant();
|
call events_test.ee_16407_5_pendant();
|
||||||
end|
|
end|
|
||||||
create event ee_16407_6 on schedule every 60 second do
|
create event ee_16407_6 on schedule every 60 second do
|
||||||
begin
|
begin
|
||||||
select get_lock('ee_16407_5', 60) /*ee_16407_6*/;
|
select get_lock('ee_16407_5', 60) /*ee_16407_6*/;
|
||||||
|
select release_lock('ee_16407_5');
|
||||||
call events_test.ee_16407_6_pendant();
|
call events_test.ee_16407_6_pendant();
|
||||||
end|
|
end|
|
||||||
delimiter ;|
|
delimiter ;|
|
||||||
set sql_mode='ansi';
|
|
||||||
select get_lock('ee_16407_5', 60);
|
|
||||||
set global event_scheduler= 1;
|
|
||||||
--sleep 1
|
--sleep 1
|
||||||
--echo "Should have 2 locked processes"
|
--echo "Should have 2 locked processes"
|
||||||
select /*4*/ user, host, db, command, state, info from information_schema.processlist where command!='Daemon' and (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');
|
select release_lock('ee_16407_5');
|
||||||
--sleep 2
|
--sleep 1.3
|
||||||
--echo "Should have 0 processes locked"
|
--echo "Should have 0 processes locked"
|
||||||
select /*5*/ user, host, db, command, state, info from information_schema.processlist where command!='Daemon' and (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;
|
select * from events_smode_test order by ev_name, a;
|
||||||
--echo "And here we check one more time before we drop the events"
|
--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;
|
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
|
||||||
@ -169,7 +179,7 @@ drop event ee_16407_5;
|
|||||||
drop event ee_16407_6;
|
drop event ee_16407_6;
|
||||||
drop procedure ee_16407_5_pendant;
|
drop procedure ee_16407_5_pendant;
|
||||||
drop procedure ee_16407_6_pendant;
|
drop procedure ee_16407_6_pendant;
|
||||||
set global event_scheduler= 2;
|
set global event_scheduler= off;
|
||||||
drop table events_smode_test;
|
drop table events_smode_test;
|
||||||
set sql_mode=@old_sql_mode;
|
set sql_mode=@old_sql_mode;
|
||||||
#
|
#
|
||||||
@ -179,7 +189,7 @@ set sql_mode=@old_sql_mode;
|
|||||||
#
|
#
|
||||||
# START - 18897: Events: unauthorized action possible with alter event rename
|
# START - 18897: Events: unauthorized action possible with alter event rename
|
||||||
#
|
#
|
||||||
set global event_scheduler=2;
|
set global event_scheduler=off;
|
||||||
--disable_warnings
|
--disable_warnings
|
||||||
delete from mysql.user where User like 'mysqltest_%';
|
delete from mysql.user where User like 'mysqltest_%';
|
||||||
delete from mysql.db where User like 'mysqltest_%';
|
delete from mysql.db where User like 'mysqltest_%';
|
||||||
@ -209,4 +219,19 @@ drop database mysqltest_db1;
|
|||||||
# END - 18897: Events: unauthorized action possible with alter event rename
|
# 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;
|
drop database events_test;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
# Can't test with embedded server that doesn't support grants
|
# Can't test with embedded server that doesn't support grants
|
||||||
-- source include/not_embedded.inc
|
-- source include/not_embedded.inc
|
||||||
|
|
||||||
create database if not exists events_test;
|
CREATE DATABASE IF NOT EXISTS events_test;
|
||||||
use events_test;
|
USE events_test;
|
||||||
--echo "We use procedure here because its statements won't be logged into the general log"
|
--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 "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"
|
--echo "the test suite is run in normal mode or with --ps-protocol"
|
||||||
@ -13,22 +13,19 @@ BEGIN
|
|||||||
END|
|
END|
|
||||||
delimiter ;|
|
delimiter ;|
|
||||||
--echo "Check General Query Log"
|
--echo "Check General Query Log"
|
||||||
SET GLOBAL event_scheduler=2;
|
--replace_column 1 USER_HOST
|
||||||
create event log_general on schedule every 1 minute do SELect 'alabala', sleep(3) from dual;
|
CALL select_general_log();
|
||||||
|
SET GLOBAL event_scheduler=on;
|
||||||
TRUNCATE mysql.general_log;
|
TRUNCATE mysql.general_log;
|
||||||
--echo "1 row, the current statement!"
|
CREATE EVENT log_general ON SCHEDULE EVERY 1 MINUTE DO SELECT 'alabala', SLEEP(1) FROM DUAL;
|
||||||
--replace_column 1 USER_HOST
|
|
||||||
call select_general_log();
|
|
||||||
SET GLOBAL event_scheduler=1;
|
|
||||||
--echo "Wait the scheduler to start"
|
--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 1.5
|
||||||
--sleep 2
|
--echo "Should see 2 rows - the 'SELECT' is in the middle. The other two are selects from general_log"
|
||||||
--replace_column 1 USER_HOST
|
--replace_column 1 USER_HOST
|
||||||
call select_general_log();
|
CALL select_general_log();
|
||||||
DROP PROCEDURE select_general_log;
|
DROP PROCEDURE select_general_log;
|
||||||
DROP EVENT log_general;
|
DROP EVENT log_general;
|
||||||
SET GLOBAL event_scheduler=2;
|
SET GLOBAL event_scheduler=off;
|
||||||
--sleep 1
|
|
||||||
|
|
||||||
--echo "Check slow query log"
|
--echo "Check slow query log"
|
||||||
--disable_query_log
|
--disable_query_log
|
||||||
@ -72,15 +69,16 @@ TRUNCATE mysql.slow_log;
|
|||||||
CREATE TABLE slow_event_test (slo_val tinyint, val tinyint);
|
CREATE TABLE slow_event_test (slo_val tinyint, val tinyint);
|
||||||
SET SESSION long_query_time=1;
|
SET SESSION long_query_time=1;
|
||||||
--echo "This won't go to the slow log"
|
--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;
|
SELECT * FROM slow_event_test;
|
||||||
SET GLOBAL event_scheduler=1;
|
SET SESSION long_query_time=1;
|
||||||
|
SET GLOBAL event_scheduler=on;
|
||||||
|
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"
|
--echo "Sleep some more time than the actual event run will take"
|
||||||
--sleep 5
|
--sleep 2
|
||||||
SHOW VARIABLES LIKE 'event_scheduler';
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
--echo "Check our table. Should see 1 row"
|
--echo "Check our table. Should see 1 row"
|
||||||
SELECT * FROM slow_event_test;
|
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;
|
SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
|
||||||
--echo "This should go to the slow log"
|
--echo "This should go to the slow log"
|
||||||
DROP EVENT long_event;
|
DROP EVENT long_event;
|
||||||
@ -88,7 +86,7 @@ SET SESSION long_query_time=10;
|
|||||||
SET GLOBAL long_query_time=1;
|
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);
|
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"
|
--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"
|
--echo "Check our table. Should see 2 rows"
|
||||||
SELECT * FROM slow_event_test;
|
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"
|
--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 GLOBAL long_query_time =@old_global_long_query_time;
|
||||||
SET SESSION long_query_time =@old_session_long_query_time;
|
SET SESSION long_query_time =@old_session_long_query_time;
|
||||||
|
|
||||||
drop database events_test;
|
DROP DATABASE events_test;
|
||||||
|
19
mysql-test/t/events_restart_phase1.test
Normal file
19
mysql-test/t/events_restart_phase1.test
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# 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=off;
|
||||||
|
create table execution_log(name char(10));
|
||||||
|
create event abc1 on schedule every 1 second do insert into execution_log value('abc1');
|
||||||
|
create event abc2 on schedule every 1 second do insert into execution_log value('abc2');
|
||||||
|
create event abc3 on schedule every 1 second do insert into execution_log value('abc3');
|
||||||
|
--sleep 1.5
|
||||||
|
select name from execution_log;
|
||||||
|
|
||||||
|
insert into mysql.event values ('db1','bad','select 42','root@localhost',NULL,1000,'MICROSECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment1');
|
||||||
|
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=on
|
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,17 +1,39 @@
|
|||||||
# Can't test with embedded server that doesn't support grants
|
# Can't test with embedded server that doesn't support grants
|
||||||
-- source include/not_embedded.inc
|
-- source include/not_embedded.inc
|
||||||
|
-- source include/not_valgrind.inc
|
||||||
|
|
||||||
CREATE DATABASE IF NOT EXISTS events_test;
|
CREATE DATABASE IF NOT EXISTS events_test;
|
||||||
USE events_test;
|
USE events_test;
|
||||||
|
|
||||||
|
SET GLOBAL event_scheduler=OFF;
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
SET GLOBAL event_scheduler=1;
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
SET GLOBAL event_scheduler=0;
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
SET GLOBAL event_scheduler=ON;
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
--error ER_WRONG_VALUE_FOR_VAR
|
||||||
|
SET GLOBAL event_scheduler=DISABLED;
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
--error ER_WRONG_VALUE_FOR_VAR
|
||||||
|
SET GLOBAL event_scheduler=-1;
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
--error ER_WRONG_VALUE_FOR_VAR
|
||||||
|
SET GLOBAL event_scheduler=2;
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
--error ER_WRONG_VALUE_FOR_VAR
|
||||||
|
SET GLOBAL event_scheduler=5;
|
||||||
|
SHOW VARIABLES LIKE 'event_scheduler';
|
||||||
|
|
||||||
CREATE TABLE table_1(a int);
|
CREATE TABLE table_1(a int);
|
||||||
CREATE TABLE table_2(a int);
|
CREATE TABLE table_2(a int);
|
||||||
CREATE TABLE table_3(a int);
|
CREATE TABLE table_3(a int);
|
||||||
CREATE TABLE table_4(a int);
|
CREATE TABLE table_4(a int);
|
||||||
CREATE TABLE T19170(s1 TIMESTAMP);
|
CREATE TABLE T19170(s1 TIMESTAMP);
|
||||||
SET GLOBAL event_scheduler=1;
|
SET GLOBAL event_scheduler=ON;
|
||||||
# We need to have 2 to make it safe with valgrind. This is probably because
|
# We need to have 2 to make it safe with valgrind. This is probably because
|
||||||
# of when we calculate the timestamp value
|
# 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 two_sec ON SCHEDULE EVERY 2 SECOND DO INSERT INTO table_1 VALUES(1);
|
||||||
CREATE EVENT start_n_end
|
CREATE EVENT start_n_end
|
||||||
ON SCHEDULE EVERY 1 SECOND
|
ON SCHEDULE EVERY 1 SECOND
|
||||||
@ -34,12 +56,10 @@ DROP EVENT start_n_end;
|
|||||||
--error ER_EVENT_DOES_NOT_EXIST
|
--error ER_EVENT_DOES_NOT_EXIST
|
||||||
DROP EVENT only_one_time;
|
DROP EVENT only_one_time;
|
||||||
--echo "Should be preserved"
|
--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 EVENT two_time;
|
||||||
DROP TABLE table_1;
|
DROP TABLE table_1;
|
||||||
DROP TABLE table_2;
|
DROP TABLE table_2;
|
||||||
DROP TABLE table_3;
|
DROP TABLE table_3;
|
||||||
DROP TABLE table_4;
|
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;
|
DROP DATABASE events_test;
|
||||||
|
@ -61,11 +61,11 @@ while ($1)
|
|||||||
}
|
}
|
||||||
--enable_query_log
|
--enable_query_log
|
||||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
||||||
SET GLOBAL event_scheduler=1;
|
SET GLOBAL event_scheduler=on;
|
||||||
--sleep 6
|
--sleep 2.5
|
||||||
DROP DATABASE events_conn1_test2;
|
DROP DATABASE events_conn1_test2;
|
||||||
|
|
||||||
SET GLOBAL event_scheduler=2;
|
SET GLOBAL event_scheduler=off;
|
||||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
||||||
CREATE DATABASE events_conn1_test3;
|
CREATE DATABASE events_conn1_test3;
|
||||||
USE events_conn1_test3;
|
USE events_conn1_test3;
|
||||||
@ -77,7 +77,7 @@ while ($1)
|
|||||||
dec $1;
|
dec $1;
|
||||||
}
|
}
|
||||||
--enable_query_log
|
--enable_query_log
|
||||||
SET GLOBAL event_scheduler=1;
|
SET GLOBAL event_scheduler=on;
|
||||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test3';
|
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test3';
|
||||||
CREATE DATABASE events_conn1_test4;
|
CREATE DATABASE events_conn1_test4;
|
||||||
USE events_conn1_test4;
|
USE events_conn1_test4;
|
||||||
@ -101,7 +101,7 @@ while ($1)
|
|||||||
}
|
}
|
||||||
--enable_query_log
|
--enable_query_log
|
||||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
||||||
--sleep 6
|
--sleep 2.5
|
||||||
connection conn2;
|
connection conn2;
|
||||||
--send
|
--send
|
||||||
DROP DATABASE events_conn2_db;
|
DROP DATABASE events_conn2_db;
|
||||||
@ -112,9 +112,9 @@ connection default;
|
|||||||
--send
|
--send
|
||||||
DROP DATABASE events_conn1_test2;
|
DROP DATABASE events_conn1_test2;
|
||||||
DROP DATABASE events_conn1_test3;
|
DROP DATABASE events_conn1_test3;
|
||||||
SET GLOBAL event_scheduler=2;
|
SET GLOBAL event_scheduler=off;
|
||||||
DROP DATABASE events_conn1_test4;
|
DROP DATABASE events_conn1_test4;
|
||||||
SET GLOBAL event_scheduler=1;
|
SET GLOBAL event_scheduler=on;
|
||||||
connection conn2;
|
connection conn2;
|
||||||
reap;
|
reap;
|
||||||
disconnect conn2;
|
disconnect conn2;
|
||||||
|
@ -50,7 +50,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_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
|
sql_update.cc sql_view.cc strfunc.cc table.cc thr_malloc.cc
|
||||||
time.cc tztime.cc uniques.cc unireg.cc item_xmlfunc.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
|
sql_tablespace.cc events.cc ../sql-common/my_user.c
|
||||||
partition_info.cc rpl_injector.cc sql_locale.cc
|
partition_info.cc rpl_injector.cc sql_locale.cc
|
||||||
${PROJECT_SOURCE_DIR}/sql/sql_yacc.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\
|
tztime.h my_decimal.h\
|
||||||
sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \
|
sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \
|
||||||
parse_file.h sql_view.h sql_trigger.h \
|
parse_file.h sql_view.h sql_trigger.h \
|
||||||
sql_array.h sql_cursor.h events.h events_priv.h \
|
sql_array.h sql_cursor.h events.h \
|
||||||
sql_plugin.h authors.h sql_partition.h event_timed.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 \
|
partition_info.h partition_element.h event_scheduler.h \
|
||||||
contributors.h
|
contributors.h
|
||||||
mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
|
mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
|
||||||
@ -102,7 +103,8 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
|
|||||||
tztime.cc my_time.c my_user.c my_decimal.cc\
|
tztime.cc my_time.c my_user.c my_decimal.cc\
|
||||||
sp_head.cc sp_pcontext.cc sp_rcontext.cc sp.cc \
|
sp_head.cc sp_pcontext.cc sp_rcontext.cc sp.cc \
|
||||||
sp_cache.cc parse_file.cc sql_trigger.cc \
|
sp_cache.cc parse_file.cc sql_trigger.cc \
|
||||||
event_scheduler.cc events.cc event_timed.cc \
|
event_scheduler.cc event_data_objects.cc \
|
||||||
|
event_queue.cc event_db_repository.cc events.cc \
|
||||||
sql_plugin.cc sql_binlog.cc \
|
sql_plugin.cc sql_binlog.cc \
|
||||||
sql_builtin.cc sql_tablespace.cc partition_info.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 *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_ */
|
979
sql/event_db_repository.cc
Normal file
979
sql/event_db_repository.cc
Normal file
@ -0,0 +1,979 @@
|
|||||||
|
/* 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 */
|
||||||
|
|
||||||
|
#include "mysql_priv.h"
|
||||||
|
#include "event_db_repository.h"
|
||||||
|
#include "event_data_objects.h"
|
||||||
|
#include "events.h"
|
||||||
|
#include "sql_show.h"
|
||||||
|
#include "sp.h"
|
||||||
|
#include "sp_head.h"
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
|
time_t mysql_event_last_create_time= 0L;
|
||||||
|
|
||||||
|
static
|
||||||
|
const TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{ C_STRING_WITH_LEN("db") },
|
||||||
|
{ C_STRING_WITH_LEN("char(64)") },
|
||||||
|
{ C_STRING_WITH_LEN("utf8") }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ C_STRING_WITH_LEN("name") },
|
||||||
|
{ C_STRING_WITH_LEN("char(64)") },
|
||||||
|
{ C_STRING_WITH_LEN("utf8") }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ C_STRING_WITH_LEN("body") },
|
||||||
|
{ C_STRING_WITH_LEN("longblob") },
|
||||||
|
{NULL, 0}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ C_STRING_WITH_LEN("definer") },
|
||||||
|
{ C_STRING_WITH_LEN("char(77)") },
|
||||||
|
{ C_STRING_WITH_LEN("utf8") }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ C_STRING_WITH_LEN("execute_at") },
|
||||||
|
{ C_STRING_WITH_LEN("datetime") },
|
||||||
|
{NULL, 0}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ C_STRING_WITH_LEN("interval_value") },
|
||||||
|
{ C_STRING_WITH_LEN("int(11)") },
|
||||||
|
{NULL, 0}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ C_STRING_WITH_LEN("interval_field") },
|
||||||
|
{ C_STRING_WITH_LEN("enum('YEAR','QUARTER','MONTH','DAY',"
|
||||||
|
"'HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR',"
|
||||||
|
"'DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND',"
|
||||||
|
"'DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND',"
|
||||||
|
"'SECOND_MICROSECOND')") },
|
||||||
|
{NULL, 0}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ C_STRING_WITH_LEN("created") },
|
||||||
|
{ C_STRING_WITH_LEN("timestamp") },
|
||||||
|
{NULL, 0}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ C_STRING_WITH_LEN("modified") },
|
||||||
|
{ C_STRING_WITH_LEN("timestamp") },
|
||||||
|
{NULL, 0}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ C_STRING_WITH_LEN("last_executed") },
|
||||||
|
{ C_STRING_WITH_LEN("datetime") },
|
||||||
|
{NULL, 0}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ C_STRING_WITH_LEN("starts") },
|
||||||
|
{ C_STRING_WITH_LEN("datetime") },
|
||||||
|
{NULL, 0}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ C_STRING_WITH_LEN("ends") },
|
||||||
|
{ C_STRING_WITH_LEN("datetime") },
|
||||||
|
{NULL, 0}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ C_STRING_WITH_LEN("status") },
|
||||||
|
{ C_STRING_WITH_LEN("enum('ENABLED','DISABLED')") },
|
||||||
|
{NULL, 0}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ C_STRING_WITH_LEN("on_completion") },
|
||||||
|
{ C_STRING_WITH_LEN("enum('DROP','PRESERVE')") },
|
||||||
|
{NULL, 0}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ C_STRING_WITH_LEN("sql_mode") },
|
||||||
|
{ C_STRING_WITH_LEN("set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES',"
|
||||||
|
"'IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION',"
|
||||||
|
"'NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB',"
|
||||||
|
"'NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40',"
|
||||||
|
"'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES',"
|
||||||
|
"'STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES',"
|
||||||
|
"'ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER',"
|
||||||
|
"'HIGH_NOT_PRECEDENCE')") },
|
||||||
|
{NULL, 0}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ C_STRING_WITH_LEN("comment") },
|
||||||
|
{ C_STRING_WITH_LEN("char(64)") },
|
||||||
|
{ C_STRING_WITH_LEN("utf8") }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Puts some data common to CREATE and ALTER EVENT into a row.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
mysql_event_fill_row()
|
||||||
|
thd THD
|
||||||
|
table The row to fill out
|
||||||
|
et Event's data
|
||||||
|
is_update CREATE EVENT or ALTER EVENT
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
0 OK
|
||||||
|
EVEX_GENERAL_ERROR Bad data
|
||||||
|
EVEX_GET_FIELD_FAILED Field count does not match. table corrupted?
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
Used both when an event is created and when it is altered.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et,
|
||||||
|
my_bool is_update)
|
||||||
|
{
|
||||||
|
CHARSET_INFO *scs= system_charset_info;
|
||||||
|
enum enum_events_table_field f_num;
|
||||||
|
Field **fields= table->field;
|
||||||
|
|
||||||
|
DBUG_ENTER("mysql_event_fill_row");
|
||||||
|
|
||||||
|
DBUG_PRINT("info", ("dbname=[%s]", et->dbname.str));
|
||||||
|
DBUG_PRINT("info", ("name =[%s]", et->name.str));
|
||||||
|
DBUG_PRINT("info", ("body =[%s]", et->body.str));
|
||||||
|
|
||||||
|
if (fields[f_num= ET_FIELD_DEFINER]->
|
||||||
|
store(et->definer.str, et->definer.length, scs))
|
||||||
|
goto err_truncate;
|
||||||
|
|
||||||
|
if (fields[f_num= ET_FIELD_DB]->store(et->dbname.str, et->dbname.length, scs))
|
||||||
|
goto err_truncate;
|
||||||
|
|
||||||
|
if (fields[f_num= ET_FIELD_NAME]->store(et->name.str, et->name.length, scs))
|
||||||
|
goto err_truncate;
|
||||||
|
|
||||||
|
/* both ON_COMPLETION and STATUS are NOT NULL thus not calling set_notnull()*/
|
||||||
|
fields[ET_FIELD_ON_COMPLETION]->store((longlong)et->on_completion, TRUE);
|
||||||
|
|
||||||
|
fields[ET_FIELD_STATUS]->store((longlong)et->status, TRUE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Change the SQL_MODE only if body was present in an ALTER EVENT and of course
|
||||||
|
always during CREATE EVENT.
|
||||||
|
*/
|
||||||
|
if (et->body.str)
|
||||||
|
{
|
||||||
|
fields[ET_FIELD_SQL_MODE]->store((longlong)thd->variables.sql_mode, TRUE);
|
||||||
|
if (fields[f_num= ET_FIELD_BODY]->store(et->body.str, et->body.length, scs))
|
||||||
|
goto err_truncate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (et->expression)
|
||||||
|
{
|
||||||
|
fields[ET_FIELD_INTERVAL_EXPR]->set_notnull();
|
||||||
|
fields[ET_FIELD_INTERVAL_EXPR]->store((longlong)et->expression, TRUE);
|
||||||
|
|
||||||
|
fields[ET_FIELD_TRANSIENT_INTERVAL]->set_notnull();
|
||||||
|
/*
|
||||||
|
In the enum (C) intervals start from 0 but in mysql enum valid values
|
||||||
|
start from 1. Thus +1 offset is needed!
|
||||||
|
*/
|
||||||
|
fields[ET_FIELD_TRANSIENT_INTERVAL]->store((longlong)et->interval+1, TRUE);
|
||||||
|
|
||||||
|
fields[ET_FIELD_EXECUTE_AT]->set_null();
|
||||||
|
|
||||||
|
if (!et->starts_null)
|
||||||
|
{
|
||||||
|
fields[ET_FIELD_STARTS]->set_notnull();
|
||||||
|
fields[ET_FIELD_STARTS]->store_time(&et->starts, MYSQL_TIMESTAMP_DATETIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!et->ends_null)
|
||||||
|
{
|
||||||
|
fields[ET_FIELD_ENDS]->set_notnull();
|
||||||
|
fields[ET_FIELD_ENDS]->store_time(&et->ends, MYSQL_TIMESTAMP_DATETIME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (et->execute_at.year)
|
||||||
|
{
|
||||||
|
fields[ET_FIELD_INTERVAL_EXPR]->set_null();
|
||||||
|
fields[ET_FIELD_TRANSIENT_INTERVAL]->set_null();
|
||||||
|
fields[ET_FIELD_STARTS]->set_null();
|
||||||
|
fields[ET_FIELD_ENDS]->set_null();
|
||||||
|
|
||||||
|
fields[ET_FIELD_EXECUTE_AT]->set_notnull();
|
||||||
|
fields[ET_FIELD_EXECUTE_AT]->
|
||||||
|
store_time(&et->execute_at, MYSQL_TIMESTAMP_DATETIME);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(is_update);
|
||||||
|
/*
|
||||||
|
it is normal to be here when the action is update
|
||||||
|
this is an error if the action is create. something is borked
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
((Field_timestamp *)fields[ET_FIELD_MODIFIED])->set_time();
|
||||||
|
|
||||||
|
if (et->comment.str)
|
||||||
|
{
|
||||||
|
if (fields[f_num= ET_FIELD_COMMENT]->
|
||||||
|
store(et->comment.str, et->comment.length, scs))
|
||||||
|
goto err_truncate;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
|
err_truncate:
|
||||||
|
my_error(ER_EVENT_DATA_TOO_LONG, MYF(0), fields[f_num]->field_name);
|
||||||
|
DBUG_RETURN(EVEX_GENERAL_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Performs an index scan of event_table (mysql.event) and fills schema_table.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
Event_db_repository::index_read_for_db_for_i_s()
|
||||||
|
thd Thread
|
||||||
|
schema_table The I_S.EVENTS table
|
||||||
|
event_table The event table to use for loading (mysql.event)
|
||||||
|
db For which schema to do an index scan.
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
0 OK
|
||||||
|
1 Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
Event_db_repository::index_read_for_db_for_i_s(THD *thd, TABLE *schema_table,
|
||||||
|
TABLE *event_table,
|
||||||
|
const char *db)
|
||||||
|
{
|
||||||
|
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("Event_db_repository::index_read_for_db_for_i_s");
|
||||||
|
|
||||||
|
DBUG_PRINT("info", ("Using prefix scanning on PK"));
|
||||||
|
event_table->file->ha_index_init(0, 1);
|
||||||
|
event_table->field[ET_FIELD_DB]->store(db, strlen(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(FALSE);
|
||||||
|
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Performs a table scan of event_table (mysql.event) and fills schema_table.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
Events_db_repository::table_scan_all_for_i_s()
|
||||||
|
thd Thread
|
||||||
|
schema_table The I_S.EVENTS in memory table
|
||||||
|
event_table The event table to use for loading.
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
FALSE OK
|
||||||
|
TRUE Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
Event_db_repository::table_scan_all_for_i_s(THD *thd, TABLE *schema_table,
|
||||||
|
TABLE *event_table)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
READ_RECORD read_record_info;
|
||||||
|
DBUG_ENTER("Event_db_repository::table_scan_all_for_i_s");
|
||||||
|
|
||||||
|
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? FALSE:TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Fills I_S.EVENTS with data loaded from mysql.event. Also used by
|
||||||
|
SHOW EVENTS
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
Event_db_repository::fill_schema_events()
|
||||||
|
thd Thread
|
||||||
|
tables The schema table
|
||||||
|
db If not NULL then get events only from this schema
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
FALSE OK
|
||||||
|
TRUE Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
Event_db_repository::fill_schema_events(THD *thd, TABLE_LIST *tables,
|
||||||
|
const char *db)
|
||||||
|
{
|
||||||
|
TABLE *schema_table= tables->table;
|
||||||
|
TABLE *event_table= NULL;
|
||||||
|
Open_tables_state backup;
|
||||||
|
int ret= 0;
|
||||||
|
|
||||||
|
DBUG_ENTER("Event_db_repository::fill_schema_events");
|
||||||
|
DBUG_PRINT("info",("db=%s", db? db:"(null)"));
|
||||||
|
|
||||||
|
thd->reset_n_backup_open_tables_state(&backup);
|
||||||
|
if (open_event_table(thd, TL_READ, &event_table))
|
||||||
|
{
|
||||||
|
sql_print_error("Table mysql.event is damaged.");
|
||||||
|
thd->restore_backup_open_tables_state(&backup);
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 (db)
|
||||||
|
ret= index_read_for_db_for_i_s(thd, schema_table, event_table, db);
|
||||||
|
else
|
||||||
|
ret= table_scan_all_for_i_s(thd, schema_table, event_table);
|
||||||
|
|
||||||
|
close_thread_tables(thd);
|
||||||
|
thd->restore_backup_open_tables_state(&backup);
|
||||||
|
|
||||||
|
DBUG_PRINT("info", ("Return code=%d", ret));
|
||||||
|
DBUG_RETURN(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Open mysql.event table for read
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
Events::open_event_table()
|
||||||
|
thd [in] Thread context
|
||||||
|
lock_type [in] How to lock the table
|
||||||
|
table [out] We will store the open table here
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
1 Cannot lock table
|
||||||
|
2 The table is corrupted - different number of fields
|
||||||
|
0 OK
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type,
|
||||||
|
TABLE **table)
|
||||||
|
{
|
||||||
|
TABLE_LIST tables;
|
||||||
|
DBUG_ENTER("Event_db_repository::open_event_table");
|
||||||
|
|
||||||
|
bzero((char*) &tables, sizeof(tables));
|
||||||
|
tables.db= (char*) "mysql";
|
||||||
|
tables.table_name= tables.alias= (char*) "event";
|
||||||
|
tables.lock_type= lock_type;
|
||||||
|
|
||||||
|
if (simple_open_n_lock_tables(thd, &tables))
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
|
if (table_check_intact(tables.table, ET_FIELD_COUNT,
|
||||||
|
event_table_fields,
|
||||||
|
&mysql_event_last_create_time,
|
||||||
|
ER_CANNOT_LOAD_FROM_TABLE))
|
||||||
|
{
|
||||||
|
close_thread_tables(thd);
|
||||||
|
DBUG_RETURN(2);
|
||||||
|
}
|
||||||
|
*table= tables.table;
|
||||||
|
tables.table->use_all_columns();
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Checks parameters which we got from the parsing phase.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
check_parse_params()
|
||||||
|
thd Thread context
|
||||||
|
parse_data Event's data
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
FALSE OK
|
||||||
|
TRUE Error (reported)
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_parse_params(THD *thd, Event_parse_data *parse_data)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("check_parse_params");
|
||||||
|
|
||||||
|
if (parse_data->check_parse_data(thd))
|
||||||
|
DBUG_RETURN(EVEX_BAD_PARAMS);
|
||||||
|
|
||||||
|
if (!parse_data->dbname.str ||
|
||||||
|
(thd->lex->sql_command == SQLCOM_ALTER_EVENT && thd->lex->spname &&
|
||||||
|
!thd->lex->spname->m_db.str))
|
||||||
|
{
|
||||||
|
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
|
||||||
|
DBUG_RETURN(EVEX_BAD_PARAMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_access(thd, EVENT_ACL, parse_data->dbname.str, 0, 0, 0,
|
||||||
|
is_schema_db(parse_data->dbname.str)) ||
|
||||||
|
(thd->lex->sql_command == SQLCOM_ALTER_EVENT && thd->lex->spname &&
|
||||||
|
(check_access(thd, EVENT_ACL, thd->lex->spname->m_db.str, 0, 0, 0,
|
||||||
|
is_schema_db(thd->lex->spname->m_db.str)))))
|
||||||
|
DBUG_RETURN(EVEX_BAD_PARAMS);
|
||||||
|
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Creates an event in mysql.event
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
Event_db_repository::create_event()
|
||||||
|
thd [in] THD
|
||||||
|
parse_data [in] Object containing info about the event
|
||||||
|
create_if_not [in] Whether to generate anwarning in case event exists
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
0 OK
|
||||||
|
EVEX_GENERAL_ERROR Failure
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
Creates an event. Relies on mysql_event_fill_row which is shared with
|
||||||
|
::update_event. The name of the event is inside "et".
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
|
||||||
|
my_bool create_if_not)
|
||||||
|
{
|
||||||
|
int ret= 0;
|
||||||
|
CHARSET_INFO *scs= system_charset_info;
|
||||||
|
TABLE *table= NULL;
|
||||||
|
char old_db_buf[NAME_LEN+1];
|
||||||
|
LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) };
|
||||||
|
bool dbchanged= FALSE;
|
||||||
|
|
||||||
|
DBUG_ENTER("Event_db_repository::create_event");
|
||||||
|
|
||||||
|
if (check_parse_params(thd, parse_data))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
DBUG_PRINT("info", ("open mysql.event for update"));
|
||||||
|
if (open_event_table(thd, TL_WRITE, &table))
|
||||||
|
{
|
||||||
|
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DBUG_PRINT("info", ("name: %.*s", parse_data->name.length,
|
||||||
|
parse_data->name.str));
|
||||||
|
|
||||||
|
DBUG_PRINT("info", ("check existance of an event with the same name"));
|
||||||
|
if (!find_named_event(thd, parse_data->dbname, parse_data->name, table))
|
||||||
|
{
|
||||||
|
if (create_if_not)
|
||||||
|
{
|
||||||
|
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||||
|
ER_EVENT_ALREADY_EXISTS, ER(ER_EVENT_ALREADY_EXISTS),
|
||||||
|
parse_data->name.str);
|
||||||
|
goto ok;
|
||||||
|
}
|
||||||
|
my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), parse_data->name.str);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBUG_PRINT("info", ("non-existant, go forward"));
|
||||||
|
|
||||||
|
if ((ret= sp_use_new_db(thd, parse_data->dbname, &old_db, 0, &dbchanged)))
|
||||||
|
{
|
||||||
|
my_error(ER_BAD_DB_ERROR, MYF(0));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
restore_record(table, s->default_values); // Get default values for fields
|
||||||
|
|
||||||
|
if (system_charset_info->cset->
|
||||||
|
numchars(system_charset_info, parse_data->dbname.str,
|
||||||
|
parse_data->dbname.str + parse_data->dbname.length) >
|
||||||
|
table->field[ET_FIELD_DB]->char_length())
|
||||||
|
{
|
||||||
|
my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->dbname.str);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (system_charset_info->cset->
|
||||||
|
numchars(system_charset_info, parse_data->name.str,
|
||||||
|
parse_data->name.str + parse_data->name.length) >
|
||||||
|
table->field[ET_FIELD_NAME]->char_length())
|
||||||
|
{
|
||||||
|
my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->name.str);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parse_data->body.length > table->field[ET_FIELD_BODY]->field_length)
|
||||||
|
{
|
||||||
|
my_error(ER_TOO_LONG_BODY, MYF(0), parse_data->name.str);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(parse_data->expression) && !(parse_data->execute_at.year))
|
||||||
|
{
|
||||||
|
DBUG_PRINT("error", ("neither expression nor execute_at are set!"));
|
||||||
|
my_error(ER_EVENT_NEITHER_M_EXPR_NOR_M_AT, MYF(0));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
((Field_timestamp *)table->field[ET_FIELD_CREATED])->set_time();
|
||||||
|
|
||||||
|
/*
|
||||||
|
mysql_event_fill_row() calls my_error() in case of error so no need to
|
||||||
|
handle it here
|
||||||
|
*/
|
||||||
|
if ((ret= mysql_event_fill_row(thd, table, parse_data, FALSE)))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* Close active transaction only if We are going to modify disk */
|
||||||
|
if (end_active_trans(thd))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (table->file->ha_write_row(table->record[0]))
|
||||||
|
{
|
||||||
|
my_error(ER_EVENT_STORE_FAILED, MYF(0), parse_data->name.str, ret);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok:
|
||||||
|
if (dbchanged)
|
||||||
|
(void) mysql_change_db(thd, old_db.str, 1);
|
||||||
|
/*
|
||||||
|
This statement may cause a spooky valgrind warning at startup
|
||||||
|
inside init_key_cache on my system (ahristov, 2006/08/10)
|
||||||
|
*/
|
||||||
|
close_thread_tables(thd);
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
|
||||||
|
err:
|
||||||
|
if (dbchanged)
|
||||||
|
(void) mysql_change_db(thd, old_db.str, 1);
|
||||||
|
if (table)
|
||||||
|
close_thread_tables(thd);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Used to execute ALTER EVENT. Pendant to Events::update_event().
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
Event_db_repository::update_event()
|
||||||
|
thd THD
|
||||||
|
sp_name the name of the event to alter
|
||||||
|
et event's data
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
FALSE OK
|
||||||
|
TRUE Error (reported)
|
||||||
|
|
||||||
|
NOTES
|
||||||
|
sp_name is passed since this is the name of the event to
|
||||||
|
alter in case of RENAME TO.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
|
||||||
|
LEX_STRING *new_dbname, LEX_STRING *new_name)
|
||||||
|
{
|
||||||
|
CHARSET_INFO *scs= system_charset_info;
|
||||||
|
TABLE *table= NULL;
|
||||||
|
DBUG_ENTER("Event_db_repository::update_event");
|
||||||
|
|
||||||
|
if (open_event_table(thd, TL_WRITE, &table))
|
||||||
|
{
|
||||||
|
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_parse_params(thd, parse_data))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
DBUG_PRINT("info", ("dbname: %s", parse_data->dbname.str));
|
||||||
|
DBUG_PRINT("info", ("name: %s", parse_data->name.str));
|
||||||
|
DBUG_PRINT("info", ("user: %s", parse_data->definer.str));
|
||||||
|
if (new_dbname)
|
||||||
|
DBUG_PRINT("info", ("rename to: %s@%s", new_dbname->str, new_name->str));
|
||||||
|
|
||||||
|
/* first look whether we overwrite */
|
||||||
|
if (new_name)
|
||||||
|
{
|
||||||
|
if (!sortcmp_lex_string(parse_data->name, *new_name, scs) &&
|
||||||
|
!sortcmp_lex_string(parse_data->dbname, *new_dbname, scs))
|
||||||
|
{
|
||||||
|
my_error(ER_EVENT_SAME_NAME, MYF(0), parse_data->name.str);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!find_named_event(thd, *new_dbname, *new_name, table))
|
||||||
|
{
|
||||||
|
my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), new_name->str);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
...and then if there is such an event. Don't exchange the blocks
|
||||||
|
because you will get error 120 from table handler because new_name will
|
||||||
|
overwrite the key and SE will tell us that it cannot find the already found
|
||||||
|
row (copied into record[1] later
|
||||||
|
*/
|
||||||
|
if (find_named_event(thd, parse_data->dbname, parse_data->name, table))
|
||||||
|
{
|
||||||
|
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), parse_data->name.str);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
store_record(table,record[1]);
|
||||||
|
|
||||||
|
/* Don't update create on row update. */
|
||||||
|
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
|
||||||
|
|
||||||
|
/*
|
||||||
|
mysql_event_fill_row() calls my_error() in case of error so no need to
|
||||||
|
handle it here
|
||||||
|
*/
|
||||||
|
if (mysql_event_fill_row(thd, table, parse_data, TRUE))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (new_dbname)
|
||||||
|
{
|
||||||
|
table->field[ET_FIELD_DB]->store(new_dbname->str, new_dbname->length, scs);
|
||||||
|
table->field[ET_FIELD_NAME]->store(new_name->str, new_name->length, scs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close active transaction only if We are going to modify disk */
|
||||||
|
if (end_active_trans(thd))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
int res;
|
||||||
|
if ((res= table->file->ha_update_row(table->record[1], table->record[0])))
|
||||||
|
{
|
||||||
|
my_error(ER_EVENT_STORE_FAILED, MYF(0), parse_data->name.str, res);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close mysql.event or we crash later when loading the event from disk */
|
||||||
|
close_thread_tables(thd);
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
|
||||||
|
err:
|
||||||
|
if (table)
|
||||||
|
close_thread_tables(thd);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Drops an event
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
Event_db_repository::drop_event()
|
||||||
|
thd [in] THD
|
||||||
|
db [in] Database name
|
||||||
|
name [in] Event's name
|
||||||
|
drop_if_exists [in] If set and the event not existing => warning
|
||||||
|
onto the stack
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
FALSE OK
|
||||||
|
TRUE Error (reported)
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
Event_db_repository::drop_event(THD *thd, LEX_STRING db, LEX_STRING name,
|
||||||
|
bool drop_if_exists)
|
||||||
|
{
|
||||||
|
TABLE *table= NULL;
|
||||||
|
Open_tables_state backup;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
DBUG_ENTER("Event_db_repository::drop_event");
|
||||||
|
DBUG_PRINT("enter", ("%s@%s", db.str, name.str));
|
||||||
|
|
||||||
|
thd->reset_n_backup_open_tables_state(&backup);
|
||||||
|
if ((ret= open_event_table(thd, TL_WRITE, &table)))
|
||||||
|
{
|
||||||
|
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ret= find_named_event(thd, db, name, table)))
|
||||||
|
{
|
||||||
|
/* Close active transaction only if we are actually going to modify disk */
|
||||||
|
if (!(ret= end_active_trans(thd)) &&
|
||||||
|
(ret= table->file->ha_delete_row(table->record[0])))
|
||||||
|
my_error(ER_EVENT_CANNOT_DELETE, MYF(0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (drop_if_exists)
|
||||||
|
{
|
||||||
|
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||||
|
ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
|
||||||
|
"Event", name.str);
|
||||||
|
ret= 0;
|
||||||
|
} else
|
||||||
|
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (table)
|
||||||
|
close_thread_tables(thd);
|
||||||
|
thd->restore_backup_open_tables_state(&backup);
|
||||||
|
|
||||||
|
DBUG_RETURN(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Positions the internal pointer of `table` to the place where (db, name)
|
||||||
|
is stored.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
Event_db_repository::find_named_event()
|
||||||
|
thd Thread
|
||||||
|
db Schema
|
||||||
|
name Event name
|
||||||
|
table Opened mysql.event
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
FALSE OK
|
||||||
|
TRUE No such event
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
Event_db_repository::find_named_event(THD *thd, LEX_STRING db, LEX_STRING name,
|
||||||
|
TABLE *table)
|
||||||
|
{
|
||||||
|
byte key[MAX_KEY_LENGTH];
|
||||||
|
DBUG_ENTER("Event_db_repository::find_named_event");
|
||||||
|
DBUG_PRINT("enter", ("name: %.*s", name.length, name.str));
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create key to find row. We have to use field->store() to be able to
|
||||||
|
handle VARCHAR and CHAR fields.
|
||||||
|
Assumption here is that the two first fields in the table are
|
||||||
|
'db' and 'name' and the first key is the primary key over the
|
||||||
|
same fields.
|
||||||
|
*/
|
||||||
|
if (db.length > table->field[ET_FIELD_DB]->field_length ||
|
||||||
|
name.length > table->field[ET_FIELD_NAME]->field_length)
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
|
table->field[ET_FIELD_DB]->store(db.str, db.length, &my_charset_bin);
|
||||||
|
table->field[ET_FIELD_NAME]->store(name.str, name.length, &my_charset_bin);
|
||||||
|
|
||||||
|
key_copy(key, table->record[0], table->key_info, table->key_info->key_length);
|
||||||
|
|
||||||
|
if (table->file->index_read_idx(table->record[0], 0, key,
|
||||||
|
table->key_info->key_length,
|
||||||
|
HA_READ_KEY_EXACT))
|
||||||
|
{
|
||||||
|
DBUG_PRINT("info", ("Row not found"));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBUG_PRINT("info", ("Row found!"));
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Drops all events in the selected database, from mysql.event.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
Event_db_repository::drop_schema_events()
|
||||||
|
thd Thread
|
||||||
|
schema The database to clean from events
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
Event_db_repository::drop_schema_events(THD *thd, LEX_STRING schema)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Event_db_repository::drop_schema_events");
|
||||||
|
drop_events_by_field(thd, ET_FIELD_DB, schema);
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Drops all events by field which has specific value of the field
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
Event_db_repository::drop_events_by_field()
|
||||||
|
thd Thread
|
||||||
|
table mysql.event TABLE
|
||||||
|
field Which field of the row to use for matching
|
||||||
|
field_value The value that should match
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
Event_db_repository::drop_events_by_field(THD *thd,
|
||||||
|
enum enum_events_table_field field,
|
||||||
|
LEX_STRING field_value)
|
||||||
|
{
|
||||||
|
int ret= 0;
|
||||||
|
TABLE *table= NULL;
|
||||||
|
READ_RECORD read_record_info;
|
||||||
|
DBUG_ENTER("Event_db_repository::drop_events_by_field");
|
||||||
|
DBUG_PRINT("enter", ("field=%d field_value=%s", field, field_value.str));
|
||||||
|
|
||||||
|
if (open_event_table(thd, TL_WRITE, &table))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Currently being used only for DROP DATABASE - In this case we don't need
|
||||||
|
error message since the OK packet has been sent. But for DROP USER we
|
||||||
|
could need it.
|
||||||
|
|
||||||
|
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
|
||||||
|
*/
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only enabled events are in memory, so we go now and delete the rest */
|
||||||
|
init_read_record(&read_record_info, thd, table, NULL, 1, 0);
|
||||||
|
while (!ret && !(read_record_info.read_record(&read_record_info)) )
|
||||||
|
{
|
||||||
|
char *et_field= get_field(thd->mem_root, table->field[field]);
|
||||||
|
|
||||||
|
LEX_STRING et_field_lex= { et_field, strlen(et_field) };
|
||||||
|
DBUG_PRINT("info", ("Current event %s name=%s", et_field,
|
||||||
|
get_field(thd->mem_root, table->field[ET_FIELD_NAME])));
|
||||||
|
|
||||||
|
if (!sortcmp_lex_string(et_field_lex, field_value, system_charset_info))
|
||||||
|
{
|
||||||
|
DBUG_PRINT("info", ("Dropping"));
|
||||||
|
ret= table->file->ha_delete_row(table->record[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end_read_record(&read_record_info);
|
||||||
|
close_thread_tables(thd);
|
||||||
|
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Looks for a named event in mysql.event and then loads it from
|
||||||
|
the table, compiles and inserts it into the cache.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
Event_db_repository::load_named_event()
|
||||||
|
thd [in] Thread context
|
||||||
|
dbname [in] Event's db name
|
||||||
|
name [in] Event's name
|
||||||
|
etn [out] The loaded event
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
FALSE OK
|
||||||
|
TRUE Error (reported)
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname,
|
||||||
|
LEX_STRING name, Event_basic *etn)
|
||||||
|
{
|
||||||
|
TABLE *table= NULL;
|
||||||
|
int ret= 0;
|
||||||
|
Open_tables_state backup;
|
||||||
|
|
||||||
|
DBUG_ENTER("Event_db_repository::load_named_event");
|
||||||
|
DBUG_PRINT("enter",("thd=0x%lx name:%*s",thd, name.length, name.str));
|
||||||
|
|
||||||
|
thd->reset_n_backup_open_tables_state(&backup);
|
||||||
|
|
||||||
|
if ((ret= open_event_table(thd, TL_READ, &table)))
|
||||||
|
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
|
||||||
|
else if ((ret= find_named_event(thd, dbname, name, table)))
|
||||||
|
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str);
|
||||||
|
else if ((ret= etn->load_from_row(table)))
|
||||||
|
my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), "event");
|
||||||
|
|
||||||
|
if (table)
|
||||||
|
close_thread_tables(thd);
|
||||||
|
|
||||||
|
thd->restore_backup_open_tables_state(&backup);
|
||||||
|
/* In this case no memory was allocated so we don't need to clean */
|
||||||
|
|
||||||
|
DBUG_RETURN(ret);
|
||||||
|
}
|
102
sql/event_db_repository.h
Normal file
102
sql/event_db_repository.h
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
#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);
|
||||||
|
|
||||||
|
class Event_basic;
|
||||||
|
class Event_parse_data;
|
||||||
|
|
||||||
|
class Event_db_repository
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Event_db_repository(){}
|
||||||
|
|
||||||
|
bool
|
||||||
|
create_event(THD *thd, Event_parse_data *parse_data, my_bool create_if_not);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
void
|
||||||
|
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, const char *db);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void
|
||||||
|
drop_events_by_field(THD *thd, enum enum_events_table_field field,
|
||||||
|
LEX_STRING field_value);
|
||||||
|
bool
|
||||||
|
index_read_for_db_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table,
|
||||||
|
const char *db);
|
||||||
|
|
||||||
|
bool
|
||||||
|
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_ */
|
1019
sql/event_queue.cc
Normal file
1019
sql/event_queue.cc
Normal file
File diff suppressed because it is too large
Load Diff
120
sql/event_queue.h
Normal file
120
sql/event_queue.h
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
#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(THD *thd, Event_db_repository *db_repo);
|
||||||
|
|
||||||
|
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
|
||||||
|
recalculate_activation_times(THD *thd);
|
||||||
|
|
||||||
|
bool
|
||||||
|
get_top_for_execution_if_time(THD *thd, Event_job_data **job_data);
|
||||||
|
bool
|
||||||
|
dump_internal_status(THD *thd);
|
||||||
|
|
||||||
|
int
|
||||||
|
load_events_from_db(THD *thd);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void
|
||||||
|
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
|
||||||
|
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;
|
||||||
|
pthread_cond_t COND_queue_state;
|
||||||
|
|
||||||
|
Event_db_repository *db_repository;
|
||||||
|
|
||||||
|
Event_scheduler *scheduler;
|
||||||
|
|
||||||
|
/* The sorted queue with the Event_job_data objects */
|
||||||
|
QUEUE queue;
|
||||||
|
|
||||||
|
TIME next_activation_at;
|
||||||
|
|
||||||
|
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;
|
||||||
|
bool waiting_on_cond;
|
||||||
|
|
||||||
|
/* helper functions for working with mutexes & conditionals */
|
||||||
|
void
|
||||||
|
lock_data(const char *func, uint line);
|
||||||
|
|
||||||
|
void
|
||||||
|
unlock_data(const char *func, uint line);
|
||||||
|
|
||||||
|
void
|
||||||
|
cond_wait(THD *thd, struct timespec *abstime, const char* msg,
|
||||||
|
const char *func, uint line);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _EVENT_QUEUE_H_ */
|
File diff suppressed because it is too large
Load Diff
@ -16,225 +16,66 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
class Event_timed;
|
class Event_queue;
|
||||||
|
class Event_job_data;
|
||||||
class THD;
|
|
||||||
typedef bool * (*event_timed_identifier_comparator)(Event_timed*, Event_timed*);
|
|
||||||
|
|
||||||
int
|
|
||||||
events_init();
|
|
||||||
|
|
||||||
void
|
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
|
class Event_scheduler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/* Return codes */
|
Event_scheduler():state(UNINITIALIZED){}
|
||||||
enum enum_error_code
|
~Event_scheduler(){}
|
||||||
{
|
|
||||||
OP_OK= 0,
|
|
||||||
OP_NOT_RUNNING,
|
|
||||||
OP_CANT_KILL,
|
|
||||||
OP_CANT_INIT,
|
|
||||||
OP_DISABLED_EVENT,
|
|
||||||
OP_LOAD_ERROR,
|
|
||||||
OP_ALREADY_EXISTS
|
|
||||||
};
|
|
||||||
|
|
||||||
enum enum_state
|
|
||||||
{
|
|
||||||
UNINITIALIZED= 0,
|
|
||||||
INITIALIZED,
|
|
||||||
COMMENCING,
|
|
||||||
CANTSTART,
|
|
||||||
RUNNING,
|
|
||||||
SUSPENDED,
|
|
||||||
IN_SHUTDOWN
|
|
||||||
};
|
|
||||||
|
|
||||||
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 */
|
/* State changing methods follow */
|
||||||
|
|
||||||
bool
|
bool
|
||||||
start();
|
start();
|
||||||
|
|
||||||
enum enum_error_code
|
bool
|
||||||
stop();
|
stop();
|
||||||
|
|
||||||
bool
|
/*
|
||||||
start_suspended();
|
Need to be public because has to be called from the function
|
||||||
|
passed to pthread_create.
|
||||||
|
*/
|
||||||
bool
|
bool
|
||||||
run(THD *thd);
|
run(THD *thd);
|
||||||
|
|
||||||
enum enum_error_code
|
void
|
||||||
suspend_or_resume(enum enum_suspend_or_resume action);
|
init_scheduler(Event_queue *queue);
|
||||||
|
|
||||||
bool
|
|
||||||
init();
|
|
||||||
|
|
||||||
void
|
void
|
||||||
destroy();
|
deinit_scheduler();
|
||||||
|
|
||||||
static void
|
void
|
||||||
init_mutexes();
|
init_mutexes();
|
||||||
|
|
||||||
static void
|
|
||||||
destroy_mutexes();
|
|
||||||
|
|
||||||
void
|
void
|
||||||
report_error_during_start();
|
deinit_mutexes();
|
||||||
|
|
||||||
/* Information retrieving methods follow */
|
/* Information retrieving methods follow */
|
||||||
|
bool
|
||||||
enum enum_state
|
is_running();
|
||||||
get_state();
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
initialized();
|
|
||||||
|
|
||||||
static int
|
|
||||||
dump_internal_status(THD *thd);
|
dump_internal_status(THD *thd);
|
||||||
|
|
||||||
static bool
|
|
||||||
check_system_tables(THD *thd);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Event_timed *
|
|
||||||
find_event(Event_timed *etn, bool remove_from_q);
|
|
||||||
|
|
||||||
uint
|
uint
|
||||||
workers_count();
|
workers_count();
|
||||||
|
|
||||||
bool
|
|
||||||
is_running_or_suspended();
|
|
||||||
|
|
||||||
/* helper functions */
|
/* helper functions */
|
||||||
bool
|
bool
|
||||||
execute_top(THD *thd);
|
execute_top(THD *thd, Event_job_data *job_data);
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/* helper functions for working with mutexes & conditionals */
|
/* helper functions for working with mutexes & conditionals */
|
||||||
void
|
void
|
||||||
@ -243,8 +84,37 @@ private:
|
|||||||
void
|
void
|
||||||
unlock_data(const char *func, uint line);
|
unlock_data(const char *func, uint line);
|
||||||
|
|
||||||
int
|
void
|
||||||
cond_wait(enum enum_cond_vars, pthread_mutex_t *mutex);
|
cond_wait(THD *thd, struct timespec *abstime, const char* msg,
|
||||||
|
const char *func, uint line);
|
||||||
|
|
||||||
|
pthread_mutex_t LOCK_scheduler_state;
|
||||||
|
|
||||||
|
enum enum_state
|
||||||
|
{
|
||||||
|
UNINITIALIZED = 0,
|
||||||
|
INITIALIZED,
|
||||||
|
RUNNING,
|
||||||
|
STOPPING
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This is the current status of the life-cycle of the scheduler. */
|
||||||
|
enum enum_state state;
|
||||||
|
|
||||||
|
THD *scheduler_thd;
|
||||||
|
|
||||||
|
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:
|
private:
|
||||||
/* Prevent use of these */
|
/* 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_ */
|
|
1420
sql/events.cc
1420
sql/events.cc
File diff suppressed because it is too large
Load Diff
142
sql/events.h
142
sql/events.h
@ -16,78 +16,124 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
|
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
|
class Events
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static ulong opt_event_scheduler;
|
/*
|
||||||
static TYPELIB opt_typelib;
|
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.
|
||||||
|
*/
|
||||||
|
friend class Event_queue_element;
|
||||||
|
|
||||||
enum enum_table_field
|
/* The order should match the order in opt_typelib */
|
||||||
|
enum enum_opt_event_scheduler
|
||||||
{
|
{
|
||||||
FIELD_DB = 0,
|
EVENTS_OFF= 0,
|
||||||
FIELD_NAME,
|
EVENTS_ON= 1,
|
||||||
FIELD_BODY,
|
EVENTS_DISABLED= 5,
|
||||||
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 :) */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static enum_opt_event_scheduler opt_event_scheduler;
|
||||||
create_event(THD *thd, Event_timed *et, uint create_options,
|
static TYPELIB opt_typelib;
|
||||||
uint *rows_affected);
|
static TYPELIB var_typelib;
|
||||||
|
|
||||||
static int
|
bool
|
||||||
update_event(THD *thd, Event_timed *et, sp_name *new_name,
|
init();
|
||||||
uint *rows_affected);
|
|
||||||
|
|
||||||
static int
|
void
|
||||||
drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
|
deinit();
|
||||||
uint *rows_affected);
|
|
||||||
|
|
||||||
static int
|
void
|
||||||
|
init_mutexes();
|
||||||
|
|
||||||
|
void
|
||||||
|
destroy_mutexes();
|
||||||
|
|
||||||
|
bool
|
||||||
|
start_execution_of_events();
|
||||||
|
|
||||||
|
bool
|
||||||
|
stop_execution_of_events();
|
||||||
|
|
||||||
|
bool
|
||||||
|
is_execution_of_events_started();
|
||||||
|
|
||||||
|
static Events *
|
||||||
|
get_instance();
|
||||||
|
|
||||||
|
bool
|
||||||
|
create_event(THD *thd, Event_parse_data *parse_data, bool if_exists);
|
||||||
|
|
||||||
|
bool
|
||||||
|
update_event(THD *thd, Event_parse_data *parse_data, sp_name *rename_to);
|
||||||
|
|
||||||
|
bool
|
||||||
|
drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists,
|
||||||
|
bool only_from_disk);
|
||||||
|
|
||||||
|
void
|
||||||
|
drop_schema_events(THD *thd, char *db);
|
||||||
|
|
||||||
|
int
|
||||||
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
|
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
|
||||||
|
|
||||||
static int
|
bool
|
||||||
show_create_event(THD *thd, sp_name *spn);
|
show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name);
|
||||||
|
|
||||||
|
/* Needed for both SHOW CREATE EVENT and INFORMATION_SCHEMA */
|
||||||
static int
|
static int
|
||||||
reconstruct_interval_expression(String *buf, interval_type interval,
|
reconstruct_interval_expression(String *buf, interval_type interval,
|
||||||
longlong expression);
|
longlong expression);
|
||||||
|
|
||||||
static int
|
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);
|
dump_internal_status(THD *thd);
|
||||||
|
|
||||||
static int
|
|
||||||
init();
|
|
||||||
|
|
||||||
static void
|
|
||||||
shutdown();
|
|
||||||
|
|
||||||
static void
|
|
||||||
init_mutexes();
|
|
||||||
|
|
||||||
static void
|
|
||||||
destroy_mutexes();
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool
|
||||||
|
check_system_tables(THD *thd);
|
||||||
|
|
||||||
|
/* Singleton DP is used */
|
||||||
|
Events();
|
||||||
|
~Events(){}
|
||||||
|
|
||||||
|
/* Singleton instance */
|
||||||
|
static Events singleton;
|
||||||
|
|
||||||
|
Event_queue *event_queue;
|
||||||
|
Event_scheduler *scheduler;
|
||||||
|
Event_db_repository *db_repository;
|
||||||
|
|
||||||
|
pthread_mutex_t LOCK_event_metadata;
|
||||||
|
|
||||||
|
bool check_system_tables_error;
|
||||||
|
|
||||||
/* Prevent use of these */
|
/* Prevent use of these */
|
||||||
Events(const Events &);
|
Events(const Events &);
|
||||||
void operator=(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_ */
|
|
@ -838,7 +838,7 @@ static void close_connections(void)
|
|||||||
DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
|
DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
|
||||||
tmp->thread_id));
|
tmp->thread_id));
|
||||||
/* We skip slave threads & scheduler on this first loop through. */
|
/* 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;
|
continue;
|
||||||
|
|
||||||
tmp->killed= THD::KILL_CONNECTION;
|
tmp->killed= THD::KILL_CONNECTION;
|
||||||
@ -857,7 +857,7 @@ static void close_connections(void)
|
|||||||
}
|
}
|
||||||
(void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
|
(void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
|
||||||
|
|
||||||
Events::shutdown();
|
Events::get_instance()->deinit();
|
||||||
end_slave();
|
end_slave();
|
||||||
|
|
||||||
if (thread_count)
|
if (thread_count)
|
||||||
@ -1295,7 +1295,7 @@ static void clean_up_mutexes()
|
|||||||
(void) pthread_mutex_destroy(&LOCK_bytes_sent);
|
(void) pthread_mutex_destroy(&LOCK_bytes_sent);
|
||||||
(void) pthread_mutex_destroy(&LOCK_bytes_received);
|
(void) pthread_mutex_destroy(&LOCK_bytes_received);
|
||||||
(void) pthread_mutex_destroy(&LOCK_user_conn);
|
(void) pthread_mutex_destroy(&LOCK_user_conn);
|
||||||
Events::destroy_mutexes();
|
Events::get_instance()->destroy_mutexes();
|
||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
(void) pthread_mutex_destroy(&LOCK_des_key_file);
|
(void) pthread_mutex_destroy(&LOCK_des_key_file);
|
||||||
#ifndef HAVE_YASSL
|
#ifndef HAVE_YASSL
|
||||||
@ -2873,7 +2873,7 @@ static int init_thread_environment()
|
|||||||
(void) pthread_mutex_init(&LOCK_server_started, MY_MUTEX_INIT_FAST);
|
(void) pthread_mutex_init(&LOCK_server_started, MY_MUTEX_INIT_FAST);
|
||||||
(void) pthread_cond_init(&COND_server_started,NULL);
|
(void) pthread_cond_init(&COND_server_started,NULL);
|
||||||
sp_cache_init();
|
sp_cache_init();
|
||||||
Events::init_mutexes();
|
Events::get_instance()->init_mutexes();
|
||||||
/* Parameter for threads created for connections */
|
/* Parameter for threads created for connections */
|
||||||
(void) pthread_attr_init(&connection_attrib);
|
(void) pthread_attr_init(&connection_attrib);
|
||||||
(void) pthread_attr_setdetachstate(&connection_attrib,
|
(void) pthread_attr_setdetachstate(&connection_attrib,
|
||||||
@ -3660,7 +3660,8 @@ we force server id to 2, but this MySQL server will not act as a slave.");
|
|||||||
|
|
||||||
if (!opt_noacl)
|
if (!opt_noacl)
|
||||||
{
|
{
|
||||||
Events::init();
|
if (Events::get_instance()->init())
|
||||||
|
unireg_abort(1);
|
||||||
}
|
}
|
||||||
#if defined(__NT__) || defined(HAVE_SMEM)
|
#if defined(__NT__) || defined(HAVE_SMEM)
|
||||||
handle_connections_methods();
|
handle_connections_methods();
|
||||||
@ -5003,9 +5004,9 @@ struct my_option my_long_options[] =
|
|||||||
(gptr*) &global_system_variables.engine_condition_pushdown,
|
(gptr*) &global_system_variables.engine_condition_pushdown,
|
||||||
(gptr*) &global_system_variables.engine_condition_pushdown,
|
(gptr*) &global_system_variables.engine_condition_pushdown,
|
||||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
|
/* See how it's handled in get_one_option() */
|
||||||
{"event-scheduler", OPT_EVENT_SCHEDULER, "Enable/disable the event scheduler.",
|
{"event-scheduler", OPT_EVENT_SCHEDULER, "Enable/disable the event scheduler.",
|
||||||
(gptr*) &Events::opt_event_scheduler, (gptr*) &Events::opt_event_scheduler, 0, GET_ULONG,
|
NULL, NULL, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
REQUIRED_ARG, 2/*default*/, 0/*min-value*/, 2/*max-value*/, 0, 0, 0},
|
|
||||||
{"exit-info", 'T', "Used for debugging; Use at your own risk!", 0, 0, 0,
|
{"exit-info", 'T', "Used for debugging; Use at your own risk!", 0, 0, 0,
|
||||||
GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0},
|
GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
{"external-locking", OPT_USE_LOCKING, "Use system (external) locking (disabled by default). With this option enabled you can run myisamchk to test (not repair) tables while the MySQL server is running. Disable with --skip-external-locking.",
|
{"external-locking", OPT_USE_LOCKING, "Use system (external) locking (disabled by default). With this option enabled you can run myisamchk to test (not repair) tables while the MySQL server is running. Disable with --skip-external-locking.",
|
||||||
@ -7307,20 +7308,33 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
|||||||
#endif
|
#endif
|
||||||
case OPT_EVENT_SCHEDULER:
|
case OPT_EVENT_SCHEDULER:
|
||||||
if (!argument)
|
if (!argument)
|
||||||
Events::opt_event_scheduler= 2;
|
Events::opt_event_scheduler= Events::EVENTS_DISABLED;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
if ((type=find_type(argument, &Events::opt_typelib, 1)) <= 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"Unknown option to event-scheduler: %s\n",argument);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
type= 1 2 3 4 5 6
|
type= 5 1 2 3 4
|
||||||
(OFF | 0) - (ON | 1) - (2 | SUSPEND)
|
(DISABLE ) - (OFF | ON) - (0 | 1)
|
||||||
*/
|
*/
|
||||||
Events::opt_event_scheduler= (type-1) / 2;
|
switch ((type=find_type(argument, &Events::opt_typelib, 1))) {
|
||||||
|
case 0:
|
||||||
|
fprintf(stderr, "Unknown option to event-scheduler: %s\n",argument);
|
||||||
|
exit(1);
|
||||||
|
case 5: /* OPT_DISABLED */
|
||||||
|
Events::opt_event_scheduler= Events::EVENTS_DISABLED;
|
||||||
|
break;
|
||||||
|
case 2: /* OPT_ON */
|
||||||
|
case 4: /* 1 */
|
||||||
|
Events::opt_event_scheduler= Events::EVENTS_ON;
|
||||||
|
break;
|
||||||
|
case 1: /* OPT_OFF */
|
||||||
|
case 3: /* 0 */
|
||||||
|
Events::opt_event_scheduler= Events::EVENTS_OFF;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
unireg_abort(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case (int) OPT_SKIP_NEW:
|
case (int) OPT_SKIP_NEW:
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
#include <myisam.h>
|
#include <myisam.h>
|
||||||
#include <my_dir.h>
|
#include <my_dir.h>
|
||||||
|
|
||||||
#include "event_scheduler.h"
|
#include "events.h"
|
||||||
|
|
||||||
/* WITH_INNOBASE_STORAGE_ENGINE */
|
/* WITH_INNOBASE_STORAGE_ENGINE */
|
||||||
extern uint innobase_flush_log_at_trx_commit;
|
extern uint innobase_flush_log_at_trx_commit;
|
||||||
@ -3899,6 +3899,7 @@ bool sys_var_thd_dbug::update(THD *thd, set_var *var)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
byte *sys_var_thd_dbug::value_ptr(THD *thd, enum_var_type type, LEX_STRING *b)
|
byte *sys_var_thd_dbug::value_ptr(THD *thd, enum_var_type type, LEX_STRING *b)
|
||||||
{
|
{
|
||||||
char buf[256];
|
char buf[256];
|
||||||
@ -3910,6 +3911,12 @@ byte *sys_var_thd_dbug::value_ptr(THD *thd, enum_var_type type, LEX_STRING *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool sys_var_event_scheduler::check(THD *thd, set_var *var)
|
||||||
|
{
|
||||||
|
return check_enum(thd, var, &Events::var_typelib);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The update method of the global variable event_scheduler.
|
The update method of the global variable event_scheduler.
|
||||||
If event_scheduler is switched from 0 to 1 then the scheduler main
|
If event_scheduler is switched from 0 to 1 then the scheduler main
|
||||||
@ -3928,30 +3935,30 @@ byte *sys_var_thd_dbug::value_ptr(THD *thd, enum_var_type type, LEX_STRING *b)
|
|||||||
bool
|
bool
|
||||||
sys_var_event_scheduler::update(THD *thd, set_var *var)
|
sys_var_event_scheduler::update(THD *thd, set_var *var)
|
||||||
{
|
{
|
||||||
enum Event_scheduler::enum_error_code res;
|
int res;
|
||||||
Event_scheduler *scheduler= Event_scheduler::get_instance();
|
|
||||||
/* here start the thread if not running. */
|
/* here start the thread if not running. */
|
||||||
DBUG_ENTER("sys_var_event_scheduler::update");
|
DBUG_ENTER("sys_var_event_scheduler::update");
|
||||||
|
if (Events::opt_event_scheduler == Events::EVENTS_DISABLED)
|
||||||
|
{
|
||||||
|
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--event-scheduler=DISABLED");
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
DBUG_PRINT("new_value", ("%lu", (bool)var->save_result.ulong_value));
|
DBUG_PRINT("new_value", ("%lu", (bool)var->save_result.ulong_value));
|
||||||
if (!scheduler->initialized())
|
|
||||||
{
|
|
||||||
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--event-scheduler=0");
|
|
||||||
DBUG_RETURN(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (var->save_result.ulonglong_value < 1 ||
|
Item_result var_type= var->value->result_type();
|
||||||
var->save_result.ulonglong_value > 2)
|
|
||||||
|
if (var->save_result.ulong_value == Events::EVENTS_ON)
|
||||||
|
res= Events::get_instance()->start_execution_of_events();
|
||||||
|
else if (var->save_result.ulong_value == Events::EVENTS_OFF)
|
||||||
|
res= Events::get_instance()->stop_execution_of_events();
|
||||||
|
else
|
||||||
{
|
{
|
||||||
char buf[64];
|
DBUG_ASSERT(0);
|
||||||
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "event_scheduler",
|
|
||||||
llstr(var->save_result.ulonglong_value, buf));
|
|
||||||
DBUG_RETURN(true);
|
|
||||||
}
|
}
|
||||||
if ((res= scheduler->suspend_or_resume(var->save_result.ulonglong_value == 1?
|
if (res)
|
||||||
Event_scheduler::RESUME :
|
my_error(ER_EVENT_SET_VAR_ERROR, MYF(0));
|
||||||
Event_scheduler::SUSPEND)))
|
|
||||||
my_error(ER_EVENT_SET_VAR_ERROR, MYF(0), (uint) res);
|
|
||||||
DBUG_RETURN((bool) res);
|
DBUG_RETURN((bool) res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3959,16 +3966,15 @@ sys_var_event_scheduler::update(THD *thd, set_var *var)
|
|||||||
byte *sys_var_event_scheduler::value_ptr(THD *thd, enum_var_type type,
|
byte *sys_var_event_scheduler::value_ptr(THD *thd, enum_var_type type,
|
||||||
LEX_STRING *base)
|
LEX_STRING *base)
|
||||||
{
|
{
|
||||||
Event_scheduler *scheduler= Event_scheduler::get_instance();
|
int state;
|
||||||
|
if (Events::opt_event_scheduler == Events::EVENTS_DISABLED)
|
||||||
if (!scheduler->initialized())
|
state= Events::EVENTS_DISABLED; // This should be DISABLED
|
||||||
thd->sys_var_tmp.long_value= 0;
|
else if (Events::get_instance()->is_execution_of_events_started())
|
||||||
else if (scheduler->get_state() == Event_scheduler::RUNNING)
|
state= Events::EVENTS_ON; // This should be ON
|
||||||
thd->sys_var_tmp.long_value= 1;
|
|
||||||
else
|
else
|
||||||
thd->sys_var_tmp.long_value= 2;
|
state= Events::EVENTS_OFF; // This should be OFF
|
||||||
|
|
||||||
return (byte*) &thd->sys_var_tmp;
|
return (byte*) Events::opt_typelib.type_names[state];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -932,6 +932,12 @@ public:
|
|||||||
sys_var_long_ptr(name_arg, NULL, NULL) {};
|
sys_var_long_ptr(name_arg, NULL, NULL) {};
|
||||||
bool update(THD *thd, set_var *var);
|
bool update(THD *thd, set_var *var);
|
||||||
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
|
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
|
||||||
|
SHOW_TYPE type() { return SHOW_CHAR; }
|
||||||
|
bool check(THD *thd, set_var *var);
|
||||||
|
bool check_update_type(Item_result type)
|
||||||
|
{
|
||||||
|
return type != STRING_RESULT && type != INT_RESULT;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef HAVE_ROW_BASED_REPLICATION
|
#ifdef HAVE_ROW_BASED_REPLICATION
|
||||||
|
@ -657,10 +657,12 @@ sp_head::create(THD *thd)
|
|||||||
|
|
||||||
sp_head::~sp_head()
|
sp_head::~sp_head()
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("sp_head::~sp_head");
|
||||||
destroy();
|
destroy();
|
||||||
delete m_next_cached_sp;
|
delete m_next_cached_sp;
|
||||||
if (m_thd)
|
if (m_thd)
|
||||||
restore_thd_mem_root(m_thd);
|
restore_thd_mem_root(m_thd);
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2084,6 +2084,7 @@ bool Security_context::set_user(char *user_arg)
|
|||||||
return user == 0;
|
return user == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Handling of open and locked tables states.
|
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:
|
exit:
|
||||||
(void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */
|
(void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */
|
||||||
error= Events::drop_schema_events(thd, db);
|
Events::get_instance()->drop_schema_events(thd, db);
|
||||||
/*
|
/*
|
||||||
If this database was the client's selected database, we silently
|
If this database was the client's selected database, we silently
|
||||||
change the client's selected database to nothing (to have an empty
|
change the client's selected database to nothing (to have an empty
|
||||||
|
@ -169,14 +169,16 @@ void lex_start(THD *thd, const uchar *buf, uint length)
|
|||||||
lex->sql_command= SQLCOM_END;
|
lex->sql_command= SQLCOM_END;
|
||||||
lex->duplicates= DUP_ERROR;
|
lex->duplicates= DUP_ERROR;
|
||||||
lex->ignore= 0;
|
lex->ignore= 0;
|
||||||
|
lex->spname= NULL;
|
||||||
lex->sphead= NULL;
|
lex->sphead= NULL;
|
||||||
lex->spcont= NULL;
|
lex->spcont= NULL;
|
||||||
lex->proc_list.first= 0;
|
lex->proc_list.first= 0;
|
||||||
lex->escape_used= lex->et_compile_phase= FALSE;
|
lex->escape_used= FALSE;
|
||||||
lex->reset_query_tables_list(FALSE);
|
lex->reset_query_tables_list(FALSE);
|
||||||
|
lex->expr_allows_subselect= TRUE;
|
||||||
|
|
||||||
lex->name= 0;
|
lex->name= 0;
|
||||||
lex->et= NULL;
|
lex->event_parse_data= NULL;
|
||||||
|
|
||||||
lex->nest_level=0 ;
|
lex->nest_level=0 ;
|
||||||
lex->allow_sum_func= 0;
|
lex->allow_sum_func= 0;
|
||||||
|
@ -27,7 +27,7 @@ class sp_instr;
|
|||||||
class sp_pcontext;
|
class sp_pcontext;
|
||||||
class st_alter_tablespace;
|
class st_alter_tablespace;
|
||||||
class partition_info;
|
class partition_info;
|
||||||
class Event_timed;
|
class Event_parse_data;
|
||||||
|
|
||||||
#ifdef MYSQL_SERVER
|
#ifdef MYSQL_SERVER
|
||||||
/*
|
/*
|
||||||
@ -958,6 +958,14 @@ typedef struct st_lex : public Query_tables_list
|
|||||||
*/
|
*/
|
||||||
nesting_map allow_sum_func;
|
nesting_map allow_sum_func;
|
||||||
enum_sql_command sql_command;
|
enum_sql_command sql_command;
|
||||||
|
/*
|
||||||
|
Usually `expr` rule of yacc is quite reused but some commands better
|
||||||
|
not support subqueries which comes standard with this rule, like
|
||||||
|
KILL, HA_READ, CREATE/ALTER EVENT etc. Set this to `false` to get
|
||||||
|
syntax error back.
|
||||||
|
*/
|
||||||
|
bool expr_allows_subselect;
|
||||||
|
|
||||||
thr_lock_type lock_option;
|
thr_lock_type lock_option;
|
||||||
enum SSL_type ssl_type; /* defined in violite.h */
|
enum SSL_type ssl_type; /* defined in violite.h */
|
||||||
enum my_lex_states next_state;
|
enum my_lex_states next_state;
|
||||||
@ -1035,8 +1043,7 @@ typedef struct st_lex : public Query_tables_list
|
|||||||
|
|
||||||
st_sp_chistics sp_chistics;
|
st_sp_chistics sp_chistics;
|
||||||
|
|
||||||
Event_timed *et;
|
Event_parse_data *event_parse_data;
|
||||||
bool et_compile_phase;
|
|
||||||
|
|
||||||
bool only_view; /* used for SHOW CREATE TABLE/VIEW */
|
bool only_view; /* used for SHOW CREATE TABLE/VIEW */
|
||||||
/*
|
/*
|
||||||
|
111
sql/sql_parse.cc
111
sql/sql_parse.cc
@ -27,7 +27,7 @@
|
|||||||
#include "sp.h"
|
#include "sp.h"
|
||||||
#include "sp_cache.h"
|
#include "sp_cache.h"
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
#include "event_timed.h"
|
#include "event_data_objects.h"
|
||||||
|
|
||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
/*
|
/*
|
||||||
@ -3896,73 +3896,43 @@ end_with_restore_list:
|
|||||||
}
|
}
|
||||||
case SQLCOM_CREATE_EVENT:
|
case SQLCOM_CREATE_EVENT:
|
||||||
case SQLCOM_ALTER_EVENT:
|
case SQLCOM_ALTER_EVENT:
|
||||||
case SQLCOM_DROP_EVENT:
|
|
||||||
{
|
{
|
||||||
uint rows_affected= 1;
|
DBUG_ASSERT(lex->event_parse_data);
|
||||||
DBUG_ASSERT(lex->et);
|
switch (lex->sql_command) {
|
||||||
do {
|
case SQLCOM_CREATE_EVENT:
|
||||||
if (! lex->et->dbname.str ||
|
res= Events::get_instance()->
|
||||||
(lex->sql_command == SQLCOM_ALTER_EVENT && lex->spname &&
|
create_event(thd, lex->event_parse_data,
|
||||||
!lex->spname->m_db.str))
|
lex->create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS);
|
||||||
{
|
break;
|
||||||
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
|
case SQLCOM_ALTER_EVENT:
|
||||||
res= true;
|
res= Events::get_instance()->update_event(thd, lex->event_parse_data,
|
||||||
break;
|
lex->spname);
|
||||||
}
|
break;
|
||||||
|
default:
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
}
|
||||||
|
DBUG_PRINT("info",("DDL error code=%d", res));
|
||||||
|
if (!res)
|
||||||
|
send_ok(thd);
|
||||||
|
|
||||||
if (check_access(thd, EVENT_ACL, lex->et->dbname.str, 0, 0, 0,
|
/* Don't do it, if we are inside a SP */
|
||||||
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);
|
|
||||||
if (!thd->spcont)
|
if (!thd->spcont)
|
||||||
{
|
{
|
||||||
lex->et->free_sphead_on_delete= true;
|
delete lex->sphead;
|
||||||
lex->et->free_sp();
|
lex->sphead= NULL;
|
||||||
lex->et->deinit_mutexes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* lex->unit.cleanup() is called outside, no need to call it here */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SQLCOM_DROP_EVENT:
|
||||||
case SQLCOM_SHOW_CREATE_EVENT:
|
case SQLCOM_SHOW_CREATE_EVENT:
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(lex->spname);
|
DBUG_ASSERT(lex->spname);
|
||||||
DBUG_ASSERT(lex->et);
|
|
||||||
if (! lex->spname->m_db.str)
|
if (! lex->spname->m_db.str)
|
||||||
{
|
{
|
||||||
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
|
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
|
||||||
res= true;
|
goto error;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (check_access(thd, EVENT_ACL, lex->spname->m_db.str, 0, 0, 0,
|
if (check_access(thd, EVENT_ACL, lex->spname->m_db.str, 0, 0, 0,
|
||||||
is_schema_db(lex->spname->m_db.str)))
|
is_schema_db(lex->spname->m_db.str)))
|
||||||
@ -3971,15 +3941,29 @@ end_with_restore_list:
|
|||||||
if (lex->spname->m_name.length > NAME_LEN)
|
if (lex->spname->m_name.length > NAME_LEN)
|
||||||
{
|
{
|
||||||
my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
|
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;
|
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,
|
||||||
|
FALSE)))
|
||||||
|
send_ok(thd);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
case SQLCOM_SHOW_SCHEDULER_STATUS:
|
case SQLCOM_SHOW_SCHEDULER_STATUS:
|
||||||
{
|
{
|
||||||
res= Events::dump_internal_status(thd);
|
res= Events::get_instance()->dump_internal_status(thd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -6073,14 +6057,6 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
|
|||||||
{
|
{
|
||||||
delete lex->sphead;
|
delete lex->sphead;
|
||||||
lex->sphead= NULL;
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -6117,13 +6093,6 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
|
|||||||
delete lex->sphead;
|
delete lex->sphead;
|
||||||
lex->sphead= NULL;
|
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->proc_info="freeing items";
|
||||||
thd->end_statement();
|
thd->end_statement();
|
||||||
|
185
sql/sql_show.cc
185
sql/sql_show.cc
@ -27,7 +27,7 @@
|
|||||||
#include "authors.h"
|
#include "authors.h"
|
||||||
#include "contributors.h"
|
#include "contributors.h"
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
#include "event_timed.h"
|
#include "event_data_objects.h"
|
||||||
#include <my_dir.h>
|
#include <my_dir.h>
|
||||||
|
|
||||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||||
@ -4217,7 +4217,7 @@ extern LEX_STRING interval_type_to_name[];
|
|||||||
1 Error
|
1 Error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
int
|
||||||
copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
|
copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
|
||||||
{
|
{
|
||||||
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
|
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
|
||||||
@ -4228,7 +4228,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
|
|||||||
|
|
||||||
restore_record(sch_table, s->default_values);
|
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));
|
my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0));
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
@ -4352,183 +4352,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)
|
int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("fill_open_tables");
|
DBUG_ENTER("fill_open_tables");
|
||||||
@ -5631,7 +5454,7 @@ ST_SCHEMA_TABLE schema_tables[]=
|
|||||||
{"ENGINES", engines_fields_info, create_schema_table,
|
{"ENGINES", engines_fields_info, create_schema_table,
|
||||||
fill_schema_engines, make_old_format, 0, -1, -1, 0},
|
fill_schema_engines, make_old_format, 0, -1, -1, 0},
|
||||||
{"EVENTS", events_fields_info, create_schema_table,
|
{"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,
|
{"FILES", files_fields_info, create_schema_table,
|
||||||
fill_schema_files, 0, 0, -1, -1, 0},
|
fill_schema_files, 0, 0, -1, -1, 0},
|
||||||
{"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
|
{"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);
|
HA_CREATE_INFO *create_info_arg);
|
||||||
int view_store_create_info(THD *thd, TABLE_LIST *table, String *buff);
|
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 */
|
#endif /* SQL_SHOW_H */
|
||||||
|
415
sql/sql_yacc.yy
415
sql/sql_yacc.yy
@ -38,7 +38,7 @@
|
|||||||
#include "sp_pcontext.h"
|
#include "sp_pcontext.h"
|
||||||
#include "sp_rcontext.h"
|
#include "sp_rcontext.h"
|
||||||
#include "sp.h"
|
#include "sp.h"
|
||||||
#include "event_timed.h"
|
#include "event_data_objects.h"
|
||||||
#include <myisam.h>
|
#include <myisam.h>
|
||||||
#include <myisammrg.h>
|
#include <myisammrg.h>
|
||||||
|
|
||||||
@ -907,7 +907,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
|||||||
sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
|
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
|
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
|
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_suid view_tail view_list_opt view_list view_select
|
||||||
view_check_option trigger_tail sp_tail
|
view_check_option trigger_tail sp_tail
|
||||||
install uninstall partition_entry binlog_base64_event
|
install uninstall partition_entry binlog_base64_event
|
||||||
@ -1284,29 +1285,41 @@ create:
|
|||||||
lex->name=$4.str;
|
lex->name=$4.str;
|
||||||
lex->create_info.options=$3;
|
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
|
BE CAREFUL when you add a new rule to update the block where
|
||||||
YYTHD->client_capabilities is set back to original value
|
YYTHD->client_capabilities is set back to original value
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
Lex->create_info.options= $2;
|
||||||
|
|
||||||
if (lex->et)
|
if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD)))
|
||||||
{
|
|
||||||
/*
|
|
||||||
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()
|
|
||||||
YYABORT;
|
YYABORT;
|
||||||
|
Lex->event_parse_data->identifier= $3;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We have to turn of CLIENT_MULTI_QUERIES while parsing a
|
We have to turn of CLIENT_MULTI_QUERIES while parsing a
|
||||||
@ -1316,11 +1329,9 @@ create:
|
|||||||
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
|
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
|
||||||
YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES);
|
YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES);
|
||||||
|
|
||||||
if (!lex->et_compile_phase)
|
Lex->sql_command= SQLCOM_CREATE_EVENT;
|
||||||
{
|
/* We need that for disallowing subqueries */
|
||||||
lex->et->init_name(YYTHD, $4);
|
Lex->expr_allows_subselect= FALSE;
|
||||||
lex->et->init_definer(YYTHD);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ON SCHEDULE_SYM ev_schedule_time
|
ON SCHEDULE_SYM ev_schedule_time
|
||||||
opt_ev_on_completion
|
opt_ev_on_completion
|
||||||
@ -1330,160 +1341,62 @@ create:
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Restore flag if it was cleared above
|
Restore flag if it was cleared above
|
||||||
$1 - CREATE
|
$1 - EVENT_SYM
|
||||||
$2 - EVENT_SYM
|
$2 - opt_if_not_exists
|
||||||
$3 - opt_if_not_exists
|
$3 - sp_name
|
||||||
$4 - sp_name
|
$4 - the block above
|
||||||
$5 - 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
|
sql_command is set here because some rules in ev_sql_stmt
|
||||||
can overwrite it
|
can overwrite it
|
||||||
*/
|
*/
|
||||||
Lex->sql_command= SQLCOM_CREATE_EVENT;
|
Lex->sql_command= SQLCOM_CREATE_EVENT;
|
||||||
|
Lex->expr_allows_subselect= TRUE;
|
||||||
}
|
}
|
||||||
| 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
|
ev_schedule_time: EVERY_SYM expr interval
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
Lex->event_parse_data->item_expression= $2;
|
||||||
if (!lex->et_compile_phase)
|
Lex->event_parse_data->interval= $3;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ev_starts
|
ev_starts
|
||||||
ev_ends
|
ev_ends
|
||||||
| AT_SYM expr
|
| AT_SYM expr
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
Lex->event_parse_data->item_execute_at= $2;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
opt_ev_status: /* empty */ { $$= 0; }
|
opt_ev_status: /* empty */ { $$= 0; }
|
||||||
| ENABLE_SYM
|
| ENABLE_SYM
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
Lex->event_parse_data->status= Event_parse_data::ENABLED;
|
||||||
if (!lex->et_compile_phase)
|
|
||||||
lex->et->status= Event_timed::ENABLED;
|
|
||||||
$$= 1;
|
$$= 1;
|
||||||
}
|
}
|
||||||
| DISABLE_SYM
|
| DISABLE_SYM
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
Lex->event_parse_data->status= Event_parse_data::DISABLED;
|
||||||
|
|
||||||
if (!lex->et_compile_phase)
|
|
||||||
lex->et->status= Event_timed::DISABLED;
|
|
||||||
$$= 1;
|
$$= 1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
ev_starts: /* empty */
|
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
|
| STARTS_SYM expr
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
Lex->event_parse_data->item_starts= $2;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
ev_ends: /* empty */
|
ev_ends: /* empty */
|
||||||
| ENDS_SYM expr
|
| ENDS_SYM expr
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
Lex->event_parse_data->item_ends= $2;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -1494,16 +1407,14 @@ opt_ev_on_completion: /* empty */ { $$= 0; }
|
|||||||
ev_on_completion:
|
ev_on_completion:
|
||||||
ON COMPLETION_SYM PRESERVE_SYM
|
ON COMPLETION_SYM PRESERVE_SYM
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
Lex->event_parse_data->on_completion=
|
||||||
if (!lex->et_compile_phase)
|
Event_parse_data::ON_COMPLETION_PRESERVE;
|
||||||
lex->et->on_completion= Event_timed::ON_COMPLETION_PRESERVE;
|
|
||||||
$$= 1;
|
$$= 1;
|
||||||
}
|
}
|
||||||
| ON COMPLETION_SYM NOT_SYM PRESERVE_SYM
|
| ON COMPLETION_SYM NOT_SYM PRESERVE_SYM
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
Lex->event_parse_data->on_completion=
|
||||||
if (!lex->et_compile_phase)
|
Event_parse_data::ON_COMPLETION_DROP;
|
||||||
lex->et->on_completion= Event_timed::ON_COMPLETION_DROP;
|
|
||||||
$$= 1;
|
$$= 1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@ -1511,64 +1422,65 @@ ev_on_completion:
|
|||||||
opt_ev_comment: /* empty */ { $$= 0; }
|
opt_ev_comment: /* empty */ { $$= 0; }
|
||||||
| COMMENT_SYM TEXT_STRING_sys
|
| COMMENT_SYM TEXT_STRING_sys
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
Lex->comment= Lex->event_parse_data->comment= $2;
|
||||||
if (!lex->et_compile_phase)
|
|
||||||
{
|
|
||||||
lex->comment= $2;
|
|
||||||
lex->et->init_comment(YYTHD, &$2);
|
|
||||||
}
|
|
||||||
$$= 1;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
ev_sql_stmt:
|
ev_sql_stmt:
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_head *sp;
|
|
||||||
|
|
||||||
$<sphead>$= lex->sphead;
|
/*
|
||||||
|
This stops the following :
|
||||||
if (!lex->sphead)
|
- 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()))
|
my_error(ER_EVENT_RECURSIVITY_FORBIDDEN, MYF(0));
|
||||||
YYABORT;
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lex->et_compile_phase)
|
if (!(lex->sphead= new sp_head()))
|
||||||
lex->et->body_begin= lex->ptr;
|
YYABORT;
|
||||||
|
|
||||||
|
lex->sphead->reset_thd_mem_root(YYTHD);
|
||||||
|
lex->sphead->init(lex);
|
||||||
|
lex->sphead->init_sp_name(YYTHD, Lex->event_parse_data->identifier);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
}
|
}
|
||||||
ev_sql_stmt_inner
|
ev_sql_stmt_inner
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
|
|
||||||
if (!$<sphead>1)
|
/* return back to the original memory root ASAP */
|
||||||
{
|
lex->sphead->init_strings(YYTHD, lex);
|
||||||
sp_head *sp= lex->sphead;
|
lex->sphead->restore_thd_mem_root(YYTHD);
|
||||||
// return back to the original memory root ASAP
|
|
||||||
sp->init_strings(YYTHD, lex);
|
|
||||||
sp->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->event_parse_data->init_body(YYTHD);
|
||||||
lex->sphead= NULL;
|
|
||||||
}
|
|
||||||
if (!lex->et_compile_phase)
|
|
||||||
{
|
|
||||||
lex->et->init_body(YYTHD);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -1643,10 +1555,10 @@ create_function_tail:
|
|||||||
if (lex->definer != NULL)
|
if (lex->definer != NULL)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
DEFINER is a concept meaningful when interpreting SQL code.
|
DEFINER is a concept meaningful when interpreting SQL code.
|
||||||
UDF functions are compiled.
|
UDF functions are compiled.
|
||||||
Using DEFINER with UDF has therefore no semantic,
|
Using DEFINER with UDF has therefore no semantic,
|
||||||
and is considered a parsing error.
|
and is considered a parsing error.
|
||||||
*/
|
*/
|
||||||
my_error(ER_WRONG_USAGE, MYF(0), "SONAME", "DEFINER");
|
my_error(ER_WRONG_USAGE, MYF(0), "SONAME", "DEFINER");
|
||||||
YYABORT;
|
YYABORT;
|
||||||
@ -1685,10 +1597,10 @@ create_function_tail:
|
|||||||
sp->m_type= TYPE_ENUM_FUNCTION;
|
sp->m_type= TYPE_ENUM_FUNCTION;
|
||||||
lex->sphead= sp;
|
lex->sphead= sp;
|
||||||
/*
|
/*
|
||||||
* We have to turn of CLIENT_MULTI_QUERIES while parsing a
|
We have to turn off CLIENT_MULTI_QUERIES while parsing a
|
||||||
* stored procedure, otherwise yylex will chop it into pieces
|
stored procedure, otherwise yylex will chop it into pieces
|
||||||
* at each ';'.
|
at each ';'.
|
||||||
*/
|
*/
|
||||||
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
|
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
|
||||||
YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
|
YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
|
||||||
lex->sphead->m_param_begin= lex->tok_start+1;
|
lex->sphead->m_param_begin= lex->tok_start+1;
|
||||||
@ -4790,41 +4702,33 @@ alter:
|
|||||||
{}
|
{}
|
||||||
| ALTER EVENT_SYM sp_name
|
| ALTER EVENT_SYM sp_name
|
||||||
/*
|
/*
|
||||||
BE CAREFUL when you add a new rule to update the block where
|
BE CAREFUL when you add a new rule to update the block where
|
||||||
YYTHD->client_capabilities is set back to original value
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
if (lex->et)
|
if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD)))
|
||||||
{
|
|
||||||
/*
|
|
||||||
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;
|
YYABORT;
|
||||||
}
|
Lex->event_parse_data->identifier= $3;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We have to turn of CLIENT_MULTI_QUERIES while parsing a
|
We have to turn off CLIENT_MULTI_QUERIES while parsing a
|
||||||
stored procedure, otherwise yylex will chop it into pieces
|
stored procedure, otherwise yylex will chop it into pieces
|
||||||
at each ';'.
|
at each ';'.
|
||||||
*/
|
*/
|
||||||
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
|
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
|
||||||
YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
|
YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
|
||||||
|
|
||||||
|
Lex->sql_command= SQLCOM_ALTER_EVENT;
|
||||||
|
/* we need that for disallowing subqueries */
|
||||||
|
Lex->expr_allows_subselect= FALSE;
|
||||||
}
|
}
|
||||||
ev_alter_on_schedule_completion
|
ev_alter_on_schedule_completion
|
||||||
opt_ev_rename_to
|
opt_ev_rename_to
|
||||||
@ -4840,16 +4744,17 @@ alter:
|
|||||||
*/
|
*/
|
||||||
YYTHD->client_capabilities |= $<ulong_num>4;
|
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))
|
if (!($5 || $6 || $7 || $8 || $9))
|
||||||
{
|
{
|
||||||
yyerror(ER(ER_SYNTAX_ERROR));
|
yyerror(ER(ER_SYNTAX_ERROR));
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
sql_command is set here because some rules in ev_sql_stmt
|
||||||
|
can overwrite it
|
||||||
|
*/
|
||||||
Lex->sql_command= SQLCOM_ALTER_EVENT;
|
Lex->sql_command= SQLCOM_ALTER_EVENT;
|
||||||
|
Lex->expr_allows_subselect= TRUE;
|
||||||
}
|
}
|
||||||
| ALTER TABLESPACE alter_tablespace_info
|
| ALTER TABLESPACE alter_tablespace_info
|
||||||
{
|
{
|
||||||
@ -4882,9 +4787,11 @@ ev_alter_on_schedule_completion: /* empty */ { $$= 0;}
|
|||||||
opt_ev_rename_to: /* empty */ { $$= 0;}
|
opt_ev_rename_to: /* empty */ { $$= 0;}
|
||||||
| RENAME TO_SYM sp_name
|
| RENAME TO_SYM sp_name
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
/*
|
||||||
lex->spname= $3; //use lex's spname to hold the new name
|
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
|
||||||
|
*/
|
||||||
|
Lex->spname= $3;
|
||||||
$$= 1;
|
$$= 1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@ -4908,7 +4815,7 @@ alter_commands:
|
|||||||
| remove_partitioning
|
| remove_partitioning
|
||||||
| partitioning
|
| partitioning
|
||||||
/*
|
/*
|
||||||
This part was added for release 5.1 by Mikael Ronström.
|
This part was added for release 5.1 by Mikael Ronström.
|
||||||
From here we insert a number of commands to manage the partitions of a
|
From here we insert a number of commands to manage the partitions of a
|
||||||
partitioned table such as adding partitions, dropping partitions,
|
partitioned table such as adding partitions, dropping partitions,
|
||||||
reorganising partitions in various manners. In future releases the list
|
reorganising partitions in various manners. In future releases the list
|
||||||
@ -7176,8 +7083,7 @@ select_derived2:
|
|||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
lex->derived_tables|= DERIVED_SUBQUERY;
|
lex->derived_tables|= DERIVED_SUBQUERY;
|
||||||
if (lex->sql_command == (int)SQLCOM_HA_READ ||
|
if (!lex->expr_allows_subselect)
|
||||||
lex->sql_command == (int)SQLCOM_KILL)
|
|
||||||
{
|
{
|
||||||
yyerror(ER(ER_SYNTAX_ERROR));
|
yyerror(ER(ER_SYNTAX_ERROR));
|
||||||
YYABORT;
|
YYABORT;
|
||||||
@ -7796,29 +7702,9 @@ drop:
|
|||||||
}
|
}
|
||||||
| DROP EVENT_SYM if_exists sp_name
|
| DROP EVENT_SYM if_exists sp_name
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
Lex->drop_if_exists= $3;
|
||||||
|
Lex->spname= $4;
|
||||||
if (lex->et)
|
Lex->sql_command = SQLCOM_DROP_EVENT;
|
||||||
{
|
|
||||||
/*
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
| DROP TRIGGER_SYM sp_name
|
| DROP TRIGGER_SYM sp_name
|
||||||
{
|
{
|
||||||
@ -8511,12 +8397,8 @@ show_param:
|
|||||||
}
|
}
|
||||||
| CREATE EVENT_SYM sp_name
|
| CREATE EVENT_SYM sp_name
|
||||||
{
|
{
|
||||||
Lex->sql_command = SQLCOM_SHOW_CREATE_EVENT;
|
|
||||||
Lex->spname= $3;
|
Lex->spname= $3;
|
||||||
Lex->et= new (YYTHD->mem_root) Event_timed();
|
Lex->sql_command = SQLCOM_SHOW_CREATE_EVENT;
|
||||||
if (!Lex->et)
|
|
||||||
YYABORT;
|
|
||||||
Lex->et->init_definer(YYTHD);
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -8696,11 +8578,17 @@ purge_option:
|
|||||||
/* kill threads */
|
/* kill threads */
|
||||||
|
|
||||||
kill:
|
kill:
|
||||||
KILL_SYM { Lex->sql_command= SQLCOM_KILL; } kill_option expr
|
KILL_SYM
|
||||||
|
{
|
||||||
|
Lex->sql_command= SQLCOM_KILL;
|
||||||
|
Lex->expr_allows_subselect= FALSE;
|
||||||
|
}
|
||||||
|
kill_option expr
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
lex->value_list.empty();
|
lex->value_list.empty();
|
||||||
lex->value_list.push_front($4);
|
lex->value_list.push_front($4);
|
||||||
|
Lex->expr_allows_subselect= TRUE;
|
||||||
};
|
};
|
||||||
|
|
||||||
kill_option:
|
kill_option:
|
||||||
@ -10187,6 +10075,7 @@ handler:
|
|||||||
my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
|
my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
|
lex->expr_allows_subselect= FALSE;
|
||||||
lex->sql_command = SQLCOM_HA_READ;
|
lex->sql_command = SQLCOM_HA_READ;
|
||||||
lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */
|
lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */
|
||||||
lex->current_select->select_limit= new Item_int((int32) 1);
|
lex->current_select->select_limit= new Item_int((int32) 1);
|
||||||
@ -10194,7 +10083,10 @@ handler:
|
|||||||
if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
|
if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
handler_read_or_scan where_clause opt_limit_clause {}
|
handler_read_or_scan where_clause opt_limit_clause
|
||||||
|
{
|
||||||
|
Lex->expr_allows_subselect= TRUE;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
handler_read_or_scan:
|
handler_read_or_scan:
|
||||||
@ -10819,8 +10711,7 @@ subselect_start:
|
|||||||
'(' SELECT_SYM
|
'(' SELECT_SYM
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
if (lex->sql_command == (int)SQLCOM_HA_READ ||
|
if (!lex->expr_allows_subselect)
|
||||||
lex->sql_command == (int)SQLCOM_KILL)
|
|
||||||
{
|
{
|
||||||
yyerror(ER(ER_SYNTAX_ERROR));
|
yyerror(ER(ER_SYNTAX_ERROR));
|
||||||
YYABORT;
|
YYABORT;
|
||||||
@ -10844,20 +10735,22 @@ subselect_end:
|
|||||||
|
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
view_or_trigger_or_sp:
|
view_or_trigger_or_sp_or_event:
|
||||||
definer view_or_trigger_or_sp_tail
|
definer view_or_trigger_or_sp_or_event_tail
|
||||||
{}
|
{}
|
||||||
| view_replace_or_algorithm definer view_tail
|
| view_replace_or_algorithm definer view_tail
|
||||||
{}
|
{}
|
||||||
;
|
;
|
||||||
|
|
||||||
view_or_trigger_or_sp_tail:
|
view_or_trigger_or_sp_or_event_tail:
|
||||||
view_tail
|
view_tail
|
||||||
{}
|
{}
|
||||||
| trigger_tail
|
| trigger_tail
|
||||||
{}
|
{}
|
||||||
| sp_tail
|
| sp_tail
|
||||||
{}
|
{}
|
||||||
|
| event_tail
|
||||||
|
{}
|
||||||
;
|
;
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
|
44
sql/table.cc
44
sql/table.cc
@ -2365,28 +2365,28 @@ bool check_column_name(const char *name)
|
|||||||
Checks whether a table is intact. Should be done *just* after the table has
|
Checks whether a table is intact. Should be done *just* after the table has
|
||||||
been opened.
|
been opened.
|
||||||
|
|
||||||
Synopsis
|
SYNOPSIS
|
||||||
table_check_intact()
|
table_check_intact()
|
||||||
table - the table to check
|
table The table to check
|
||||||
table_f_count - expected number of columns in the table
|
table_f_count Expected number of columns in the table
|
||||||
table_def - expected structure of the table (column name and type)
|
table_def Expected structure of the table (column name and type)
|
||||||
last_create_time- the table->file->create_time of the table in memory
|
last_create_time The table->file->create_time of the table in memory
|
||||||
we have checked last time
|
we have checked last time
|
||||||
error_num - ER_XXXX from the error messages file. When 0 no error
|
error_num ER_XXXX from the error messages file. When 0 no error
|
||||||
is sent to the client in case types does not match.
|
is sent to the client in case types does not match.
|
||||||
If different col number either
|
If different col number either
|
||||||
ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE or
|
ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE or
|
||||||
ER_COL_COUNT_DOESNT_MATCH_CORRUPTED is used
|
ER_COL_COUNT_DOESNT_MATCH_CORRUPTED is used
|
||||||
|
|
||||||
RETURNS
|
RETURNS
|
||||||
0 - OK
|
FALSE OK
|
||||||
1 - There was an error
|
TRUE There was an error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
my_bool
|
my_bool
|
||||||
table_check_intact(TABLE *table, uint table_f_count,
|
table_check_intact(TABLE *table, const uint table_f_count,
|
||||||
TABLE_FIELD_W_TYPE *table_def, time_t *last_create_time,
|
const TABLE_FIELD_W_TYPE *table_def,
|
||||||
int error_num)
|
time_t *last_create_time, int error_num)
|
||||||
{
|
{
|
||||||
uint i;
|
uint i;
|
||||||
my_bool error= FALSE;
|
my_bool error= FALSE;
|
||||||
@ -2401,7 +2401,7 @@ table_check_intact(TABLE *table, uint table_f_count,
|
|||||||
DBUG_PRINT("info", ("I am suspecting, checking table"));
|
DBUG_PRINT("info", ("I am suspecting, checking table"));
|
||||||
if (fields_diff_count)
|
if (fields_diff_count)
|
||||||
{
|
{
|
||||||
// previous MySQL version
|
/* previous MySQL version */
|
||||||
error= TRUE;
|
error= TRUE;
|
||||||
if (MYSQL_VERSION_ID > table->s->mysql_version)
|
if (MYSQL_VERSION_ID > table->s->mysql_version)
|
||||||
{
|
{
|
||||||
@ -2424,22 +2424,22 @@ table_check_intact(TABLE *table, uint table_f_count,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
moving from newer mysql to older one -> let's say not an error but
|
Moving from newer mysql to older one -> let's say not an error but
|
||||||
will check the definition afterwards. If a column was added at the
|
will check the definition afterwards. If a column was added at the
|
||||||
end then we don't care much since it's not in the middle.
|
end then we don't care much since it's not in the middle.
|
||||||
*/
|
*/
|
||||||
error= FALSE;
|
error= FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//definitely something has changed
|
/* definitely something has changed */
|
||||||
char buffer[255];
|
char buffer[255];
|
||||||
for (i=0 ; i < table_f_count; i++, table_def++)
|
for (i=0 ; i < table_f_count; i++, table_def++)
|
||||||
{
|
{
|
||||||
String sql_type(buffer, sizeof(buffer), system_charset_info);
|
String sql_type(buffer, sizeof(buffer), system_charset_info);
|
||||||
sql_type.length(0);
|
sql_type.length(0);
|
||||||
/*
|
/*
|
||||||
name changes are not fatal, we use sequence numbers => no prob for us
|
Name changes are not fatal, we use sequence numbers => no problem
|
||||||
but this can show tampered table or broken table.
|
for us but this can show tampered table or broken table.
|
||||||
*/
|
*/
|
||||||
if (i < table->s->fields)
|
if (i < table->s->fields)
|
||||||
{
|
{
|
||||||
@ -2453,7 +2453,7 @@ table_check_intact(TABLE *table, uint table_f_count,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
IF the type does not match than something is really wrong
|
If the type does not match than something is really wrong
|
||||||
Check up to length - 1. Why?
|
Check up to length - 1. Why?
|
||||||
1. datetime -> datetim -> the same
|
1. datetime -> datetim -> the same
|
||||||
2. int(11) -> int(11 -> the same
|
2. int(11) -> int(11 -> the same
|
||||||
|
@ -1029,9 +1029,9 @@ typedef struct st_table_field_w_type
|
|||||||
|
|
||||||
|
|
||||||
my_bool
|
my_bool
|
||||||
table_check_intact(TABLE *table, uint table_f_count,
|
table_check_intact(TABLE *table, const uint table_f_count,
|
||||||
TABLE_FIELD_W_TYPE *table_def, time_t *last_create_time,
|
const TABLE_FIELD_W_TYPE * const table_def,
|
||||||
int error_num);
|
time_t *last_create_time, int error_num);
|
||||||
|
|
||||||
static inline my_bitmap_map *tmp_use_all_columns(TABLE *table,
|
static inline my_bitmap_map *tmp_use_all_columns(TABLE *table,
|
||||||
MY_BITMAP *bitmap)
|
MY_BITMAP *bitmap)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user