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

into lmy004.:/work/mysql-5.1-events_i_s
This commit is contained in:
andrey@lmy004. 2006-01-30 17:20:46 +01:00
commit 0a0304b5e8
19 changed files with 598 additions and 75 deletions

View file

@ -596,7 +596,7 @@ CREATE TABLE event (
status ENUM('ENABLED','DISABLED') NOT NULL default 'ENABLED',
on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP',
comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
PRIMARY KEY (db,name)
PRIMARY KEY (definer, db, name)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
CREATE DATABASE IF NOT EXISTS cluster_replication;

View file

@ -34,13 +34,93 @@ create table t_event3 (a int, b float);
drop event if exists event3;
Warnings:
Note 1305 Event event3 does not exist
create event event3 on schedule every 50 + 10 minute starts date_add("20010101", interval 5 minute) ends date_add("20151010", interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand());
create event event3 on schedule every 50 + 10 minute starts date_add("20100101", interval 5 minute) ends date_add("20151010", interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand());
set max_allowed_packet=128000000;
select count(*) from t_event3;
count(*)
0
drop event event3;
drop table t_event3;
create event one_event on schedule every 10 second do select 123;
SHOW EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
events_test one_event root@localhost RECURRING NULL 10 INTERVAL_SECOND # # ENABLED
SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events;
EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT
NULL events_test one_event root@localhost select 123 RECURRING NULL 10 INTERVAL_SECOND ENABLED NOT PRESERVE
CREATE DATABASE events_test2;
CREATE USER ev_test@localhost;
GRANT ALL ON events_test.* to ev_test@localhost;
GRANT ALL on events_test2.* to ev_test@localhost;
REVOKE EVENT ON events_test2.* FROM ev_test@localhost;
REVOKE PROCESS on *.* from ev_test@localhost;
select "NEW CONNECTION";
NEW CONNECTION
NEW CONNECTION
SELECT USER(), DATABASE();
USER() DATABASE()
ev_test@localhost events_test2
SHOW GRANTS;
Grants for ev_test@localhost
GRANT USAGE ON *.* TO 'ev_test'@'localhost'
GRANT ALL PRIVILEGES ON `events_test`.* TO 'ev_test'@'localhost'
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE ON `events_test2`.* TO 'ev_test'@'localhost'
"Here comes an error:";
SHOW EVENTS;
ERROR 42000: Access denied for user 'ev_test'@'localhost' to database 'events_test2'
USE events_test;
"Now the list should be empty:";
SHOW EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
select concat("Let's create some new events from the name of ",user());
concat("Let's create some new events from the name of ",user())
Let's create some new events from the name of ev_test@localhost
create event one_event on schedule every 20 second do select 123;
create event two_event on schedule every 20 second on completion not preserve comment "two event" do select 123;
create event three_event on schedule every 20 second on completion preserve comment "three event" do select 123;
"Now we should see 3 events:";
SHOW EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
events_test one_event ev_test@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
events_test three_event ev_test@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
events_test two_event ev_test@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
"This should show us only 3 events:";
SHOW FULL EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
events_test one_event ev_test@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
events_test three_event ev_test@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
events_test two_event ev_test@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
"This should show us only 2 events:";
SHOW FULL EVENTS LIKE 't%event';
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
events_test three_event ev_test@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
events_test two_event ev_test@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
"This should show us no events:";
SHOW FULL EVENTS FROM test LIKE '%';
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
DROP DATABASE events_test2;
"should see 1 event:";
SHOW EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
events_test one_event root@localhost RECURRING NULL 10 INTERVAL_SECOND # # ENABLED
"we should see 4 events now:";
SHOW FULL EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
events_test one_event ev_test@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
events_test three_event ev_test@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
events_test two_event ev_test@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
events_test one_event root@localhost RECURRING NULL 10 INTERVAL_SECOND # # ENABLED
SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events;
EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT
NULL events_test one_event ev_test@localhost select 123 RECURRING NULL 20 INTERVAL_SECOND ENABLED NOT PRESERVE
NULL events_test three_event ev_test@localhost select 123 RECURRING NULL 20 INTERVAL_SECOND ENABLED PRESERVE three event
NULL events_test two_event ev_test@localhost select 123 RECURRING NULL 20 INTERVAL_SECOND ENABLED NOT PRESERVE two event
NULL events_test one_event root@localhost select 123 RECURRING NULL 10 INTERVAL_SECOND ENABLED NOT PRESERVE
drop event one_event;
drop event two_event;
drop event three_event;
drop user ev_test@localhost;
drop event one_event;
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;
db name body definer convert_tz(execute_at, 'UTC', 'SYSTEM') on_completion

View file

@ -44,6 +44,7 @@ COLLATION_CHARACTER_SET_APPLICABILITY
COLUMNS
COLUMN_PRIVILEGES
ENGINES
EVENTS
KEY_COLUMN_USAGE
PARTITIONS
PLUGINS
@ -734,7 +735,7 @@ CREATE TABLE t_crashme ( f1 BIGINT);
CREATE VIEW a1 (t_CRASHME) AS SELECT f1 FROM t_crashme GROUP BY f1;
CREATE VIEW a2 AS SELECT t_CRASHME FROM a1;
count(*)
109
110
drop view a2, a1;
drop table t_crashme;
select table_schema,table_name, column_name from
@ -742,6 +743,8 @@ information_schema.columns
where data_type = 'longtext';
table_schema table_name column_name
information_schema COLUMNS COLUMN_TYPE
information_schema EVENTS EVENT_BODY
information_schema EVENTS SQL_MODE
information_schema PARTITIONS PARTITION_EXPRESSION
information_schema PARTITIONS SUBPARTITION_EXPRESSION
information_schema PARTITIONS PARTITION_DESCRIPTION
@ -756,6 +759,12 @@ information_schema VIEWS VIEW_DEFINITION
select table_name, column_name, data_type from information_schema.columns
where data_type = 'datetime';
table_name column_name data_type
EVENTS EXECUTE_AT datetime
EVENTS STARTS datetime
EVENTS ENDS datetime
EVENTS CREATED datetime
EVENTS LAST_ALTERED datetime
EVENTS LAST_EXECUTED datetime
PARTITIONS CREATE_TIME datetime
PARTITIONS UPDATE_TIME datetime
PARTITIONS CHECK_TIME datetime
@ -817,7 +826,7 @@ flush privileges;
SELECT table_schema, count(*) FROM information_schema.TABLES GROUP BY TABLE_SCHEMA;
table_schema count(*)
cluster_replication 1
information_schema 19
information_schema 20
mysql 21
create table t1 (i int, j int);
create trigger trg1 before insert on t1 for each row

View file

@ -7,6 +7,7 @@ COLLATION_CHARACTER_SET_APPLICABILITY
COLUMNS
COLUMN_PRIVILEGES
ENGINES
EVENTS
KEY_COLUMN_USAGE
PARTITIONS
PLUGINS

View file

@ -204,7 +204,7 @@ event CREATE TABLE `event` (
`status` enum('ENABLED','DISABLED') NOT NULL default 'ENABLED',
`on_completion` enum('DROP','PRESERVE') NOT NULL default 'DROP',
`comment` char(64) character set utf8 collate utf8_bin NOT NULL default '',
PRIMARY KEY (`db`,`name`)
PRIMARY KEY (`definer`,`db`,`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events'
show create table general_log;
Table Create Table

View file

@ -27,12 +27,88 @@ set global event_scheduler = 0;
create table t_event3 (a int, b float);
drop event if exists event3;
create event event3 on schedule every 50 + 10 minute starts date_add("20010101", interval 5 minute) ends date_add("20151010", interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand());
create event event3 on schedule every 50 + 10 minute starts date_add("20100101", interval 5 minute) ends date_add("20151010", interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand());
set max_allowed_packet=128000000;
select count(*) from t_event3;
drop event event3;
drop table t_event3;
#
#INFORMATION_SCHEMA.EVENTS test begin
#
create event one_event on schedule every 10 second do select 123;
--replace_column 8 # 9 #
SHOW EVENTS;
SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events;
CREATE DATABASE events_test2;
CREATE USER ev_test@localhost;
GRANT ALL ON events_test.* to ev_test@localhost;
GRANT ALL on events_test2.* to ev_test@localhost;
REVOKE EVENT ON events_test2.* FROM ev_test@localhost;
REVOKE PROCESS on *.* from ev_test@localhost;
#now we are on con1
connect (ev_con1,localhost,ev_test,,events_test2);
select "NEW CONNECTION";
SELECT USER(), DATABASE();
SHOW GRANTS;
--echo "Here comes an error:";
#NO EVENT_ACL on events_test2
--error 1044
SHOW EVENTS;
USE events_test;
--echo "Now the list should be empty:";
--replace_column 8 # 9 #
SHOW EVENTS;
#now create an event with the same name but we are different user
select concat("Let's create some new events from the name of ",user());
create event one_event on schedule every 20 second do select 123;
create event two_event on schedule every 20 second on completion not preserve comment "two event" do select 123;
create event three_event on schedule every 20 second on completion preserve comment "three event" do select 123;
--echo "Now we should see 3 events:";
--replace_column 8 # 9 #
SHOW EVENTS;
--echo "This should show us only 3 events:";
--replace_column 8 # 9 #
SHOW FULL EVENTS;
--echo "This should show us only 2 events:";
--replace_column 8 # 9 #
SHOW FULL EVENTS LIKE 't%event';
--echo "This should show us no events:";
--replace_column 8 # 9 #
SHOW FULL EVENTS FROM test LIKE '%';
#ok, we are back
connection default;
DROP DATABASE events_test2;
--echo "should see 1 event:";
--replace_column 8 # 9 #
SHOW EVENTS;
--echo "we should see 4 events now:";
--replace_column 8 # 9 #
SHOW FULL EVENTS;
SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events;
connection ev_con1;
drop event one_event;
drop event two_event;
drop event three_event;
disconnect ev_con1;
connection default;
drop user ev_test@localhost;
drop event one_event;
#
##INFORMATION_SCHEMA.EVENTS test end
#
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;

View file

@ -792,7 +792,7 @@ then
c_ev="$c_ev status ENUM('ENABLED','DISABLED') NOT NULL default 'ENABLED',"
c_ev="$c_ev on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP',"
c_ev="$c_ev comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',"
c_ev="$c_ev PRIMARY KEY (db,name)"
c_ev="$c_ev PRIMARY KEY (definer, db, name)"
c_ev="$c_ev ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';"
fi

View file

@ -600,4 +600,6 @@ CREATE TABLE event (
ALTER TABLE user add Event_priv enum('N','Y') character set utf8 DEFAULT 'N' NOT NULL AFTER Create_user_priv;
ALTER TABLE db add Event_priv enum('N','Y') character set utf8 DEFAULT 'N' NOT NULL;
ALTER TABLE event DROP PRIMARY KEY;
ALTER TABLE event ADD PRIMARY KEY(definer, db, name);

View file

@ -77,7 +77,7 @@ evex_queue_init(EVEX_QUEUE_TYPE *queue)
}
static
int sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs)
{
return cs->coll->strnncollsp(cs, (unsigned char *) s.str,s.length,
@ -182,7 +182,9 @@ evex_open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table)
int
evex_db_find_event_aux(THD *thd, const LEX_STRING dbname,
const LEX_STRING ev_name, TABLE *table)
const LEX_STRING ev_name,
const LEX_STRING user_name,
TABLE *table)
{
byte key[MAX_KEY_LENGTH];
DBUG_ENTER("evex_db_find_event_aux");
@ -196,11 +198,17 @@ evex_db_find_event_aux(THD *thd, const LEX_STRING dbname,
same fields.
*/
if (dbname.length > table->field[EVEX_FIELD_DB]->field_length ||
ev_name.length > table->field[EVEX_FIELD_NAME]->field_length)
ev_name.length > table->field[EVEX_FIELD_NAME]->field_length ||
user_name.length > table->field[EVEX_FIELD_DEFINER]->field_length)
DBUG_RETURN(EVEX_KEY_NOT_FOUND);
table->field[0]->store(dbname.str, dbname.length, &my_charset_bin);
table->field[1]->store(ev_name.str, ev_name.length, &my_charset_bin);
table->field[EVEX_FIELD_DB]->store(dbname.str, dbname.length, &my_charset_bin);
table->field[EVEX_FIELD_NAME]->store(ev_name.str, ev_name.length,
&my_charset_bin);
table->field[EVEX_FIELD_DEFINER]->store(user_name.str, user_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,
@ -290,10 +298,15 @@ evex_fill_row(THD *thd, TABLE *table, event_timed *et, my_bool is_update)
from 1. Thus +1 offset is needed!
*/
table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->store((longlong)et->interval+1);
table->field[EVEX_FIELD_EXECUTE_AT]->set_null();
}
else if (et->execute_at.year)
{
// fix_fields already called in init_execute_at
table->field[EVEX_FIELD_INTERVAL_EXPR]->set_null();
table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->set_null();
table->field[EVEX_FIELD_EXECUTE_AT]->set_notnull();
table->field[EVEX_FIELD_EXECUTE_AT]->store_time(&et->execute_at,
MYSQL_TIMESTAMP_DATETIME);
@ -358,9 +371,9 @@ db_create_event(THD *thd, event_timed *et, my_bool create_if_not,
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
goto err;
}
DBUG_PRINT("info", ("check existance of an event with the same name"));
if (!evex_db_find_event_aux(thd, et->dbname, et->name, table))
if (!evex_db_find_event_aux(thd, et->dbname, et->name, et->definer, table))
{
if (create_if_not)
{
@ -410,10 +423,9 @@ db_create_event(THD *thd, event_timed *et, my_bool create_if_not,
goto err;
}
strxmov(definer, et->definer_user.str, "@", et->definer_host.str, NullS);
if ((ret=table->field[EVEX_FIELD_DEFINER]->
store(definer, et->definer_user.length + 1 + et->definer_host.length,
system_charset_info)))
if ((ret=table->field[EVEX_FIELD_DEFINER]->store(et->definer.str,
et->definer.length,
system_charset_info)))
{
my_error(ER_EVENT_STORE_FAILED, MYF(0), et->name.str, ret);
goto err;
@ -476,7 +488,9 @@ db_update_event(THD *thd, event_timed *et, sp_name *new_name)
TABLE *table;
int ret= EVEX_OPEN_TABLE_FAILED;
DBUG_ENTER("db_update_event");
DBUG_PRINT("enter", ("dbname: %.*s", et->dbname.length, et->dbname.str));
DBUG_PRINT("enter", ("name: %.*s", et->name.length, et->name.str));
DBUG_PRINT("enter", ("user: %.*s", et->name.length, et->name.str));
if (new_name)
DBUG_PRINT("enter", ("rename to: %.*s", new_name->m_name.length,
new_name->m_name.str));
@ -497,7 +511,8 @@ db_update_event(THD *thd, event_timed *et, sp_name *new_name)
goto err;
}
if (!evex_db_find_event_aux(thd, new_name->m_db, new_name->m_name, table))
if (!evex_db_find_event_aux(thd, new_name->m_db, new_name->m_name,
et->definer, table))
{
my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), new_name->m_name.str);
goto err;
@ -510,7 +525,7 @@ db_update_event(THD *thd, event_timed *et, sp_name *new_name)
row (copied into record[1] later
*/
if (EVEX_KEY_NOT_FOUND == evex_db_find_event_aux(thd, et->dbname, et->name,
table))
et->definer, table))
{
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), et->name.str);
goto err;
@ -559,6 +574,7 @@ err:
db_find_event()
thd THD
name the name of the event to find
definer who owns the event
ett event's data if event is found
tbl TABLE object to use when not NULL
@ -568,11 +584,11 @@ err:
*/
static int
db_find_event(THD *thd, sp_name *name, event_timed **ett, TABLE *tbl)
db_find_event(THD *thd, sp_name *name, LEX_STRING definer, event_timed **ett,
TABLE *tbl)
{
TABLE *table;
int ret;
const char *definer;
char *ptr;
event_timed *et;
DBUG_ENTER("db_find_event");
@ -587,7 +603,8 @@ db_find_event(THD *thd, sp_name *name, event_timed **ett, TABLE *tbl)
goto done;
}
if ((ret= evex_db_find_event_aux(thd, name->m_db, name->m_name, table)))
if ((ret= evex_db_find_event_aux(thd, name->m_db, name->m_name, definer,
table)))
{
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name->m_name.str);
goto done;
@ -628,6 +645,7 @@ done:
evex_load_and_compile_event()
thd THD
spn the name of the event to alter
definer who is the owner
use_lock whether to obtain a lock on LOCK_event_arrays or not
RETURN VALUE
@ -637,7 +655,8 @@ done:
*/
static int
evex_load_and_compile_event(THD * thd, sp_name *spn, bool use_lock)
evex_load_and_compile_event(THD * thd, sp_name *spn, LEX_STRING definer,
bool use_lock)
{
int ret= 0;
MEM_ROOT *tmp_mem_root;
@ -652,7 +671,7 @@ evex_load_and_compile_event(THD * thd, sp_name *spn, bool use_lock)
thd->reset_n_backup_open_tables_state(&backup);
// no need to use my_error() here because db_find_event() has done it
if ((ret= db_find_event(thd, spn, &ett, NULL)))
if ((ret= db_find_event(thd, spn, definer, &ett, NULL)))
goto done;
thd->restore_backup_open_tables_state(&backup);
@ -773,7 +792,7 @@ evex_create_event(THD *thd, event_timed *et, uint create_options,
if (evex_is_running && et->status == MYSQL_EVENT_ENABLED)
{
sp_name spn(et->dbname, et->name);
ret= evex_load_and_compile_event(thd, &spn, true);
ret= evex_load_and_compile_event(thd, &spn, et->definer, true);
}
VOID(pthread_mutex_unlock(&LOCK_evex_running));
@ -826,11 +845,11 @@ evex_update_event(THD *thd, event_timed *et, sp_name *new_name,
if (et->status == MYSQL_EVENT_ENABLED)
{
if (new_name)
ret= evex_load_and_compile_event(thd, new_name, false);
ret= evex_load_and_compile_event(thd, new_name, et->definer, false);
else
{
sp_name spn(et->dbname, et->name);
ret= evex_load_and_compile_event(thd, &spn, false);
ret= evex_load_and_compile_event(thd, &spn, et->definer, false);
}
if (ret == EVEX_COMPILE_ERROR)
my_error(ER_EVENT_COMPILE_ERROR, MYF(0));
@ -868,7 +887,7 @@ evex_drop_event(THD *thd, event_timed *et, bool drop_if_exists,
goto done;
}
if (!(ret= evex_db_find_event_aux(thd, et->dbname, et->name, table)))
if (!(ret= evex_db_find_event_aux(thd, et->dbname,et->name,et->definer,table)))
{
if ((ret= table->file->ha_delete_row(table->record[0])))
{

View file

@ -54,6 +54,25 @@ enum enum_event_status
MYSQL_EVENT_DISABLED
};
enum evex_table_field
{
EVEX_FIELD_DB = 0,
EVEX_FIELD_NAME,
EVEX_FIELD_BODY,
EVEX_FIELD_DEFINER,
EVEX_FIELD_EXECUTE_AT,
EVEX_FIELD_INTERVAL_EXPR,
EVEX_FIELD_TRANSIENT_INTERVAL,
EVEX_FIELD_CREATED,
EVEX_FIELD_MODIFIED,
EVEX_FIELD_LAST_EXECUTED,
EVEX_FIELD_STARTS,
EVEX_FIELD_ENDS,
EVEX_FIELD_STATUS,
EVEX_FIELD_ON_COMPLETION,
EVEX_FIELD_COMMENT,
EVEX_FIELD_COUNT /* a cool trick to count the number of fields :) */
} ;
class event_timed
{
@ -64,9 +83,10 @@ class event_timed
bool status_changed;
bool last_executed_changed;
TIME last_executed;
public:
TIME last_executed;
LEX_STRING dbname;
LEX_STRING name;
LEX_STRING body;
@ -83,8 +103,8 @@ public:
longlong expression;
interval_type interval;
longlong created;
longlong modified;
ulonglong created;
ulonglong modified;
enum enum_event_on_completion on_completion;
enum enum_event_status status;
sp_head *sphead;
@ -197,6 +217,10 @@ int
evex_drop_event(THD *thd, event_timed *et, bool drop_if_exists,
uint *rows_affected);
int
evex_open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
int sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
int
init_events();
@ -210,6 +234,7 @@ int
event_timed_compare(event_timed **a, event_timed **b);
/*
CREATE TABLE event (
db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
@ -233,7 +258,7 @@ CREATE TABLE event (
status ENUM('ENABLED','DISABLED') NOT NULL default 'ENABLED',
on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP',
comment varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
PRIMARY KEY (db,name)
PRIMARY KEY (definer,db,name)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
*/

View file

@ -348,7 +348,8 @@ event_executor_main(void *arg)
TIME_to_ulonglong_datetime(&et->execute_at)));
et->update_fields(thd);
DBUG_PRINT("info", (" Spawning a thread %d", ++iter_num));
++iter_num;
DBUG_PRINT("info", (" Spawning a thread %d", iter_num));
#ifndef DBUG_FAULTY_THR
if (pthread_create(&th, NULL, event_executor_worker, (void*)et))
{
@ -461,7 +462,7 @@ event_executor_worker(void *event_void)
thd->mem_root= &worker_mem_root;
pthread_detach(pthread_self());
if (init_event_thread(thd))
goto err;

View file

@ -24,26 +24,6 @@
#define UNLOCK_MUTEX_AND_BAIL_OUT(__mutex, __label) \
{ VOID(pthread_mutex_unlock(&__mutex)); goto __label; }
enum evex_table_field
{
EVEX_FIELD_DB = 0,
EVEX_FIELD_NAME,
EVEX_FIELD_BODY,
EVEX_FIELD_DEFINER,
EVEX_FIELD_EXECUTE_AT,
EVEX_FIELD_INTERVAL_EXPR,
EVEX_FIELD_TRANSIENT_INTERVAL,
EVEX_FIELD_CREATED,
EVEX_FIELD_MODIFIED,
EVEX_FIELD_LAST_EXECUTED,
EVEX_FIELD_STARTS,
EVEX_FIELD_ENDS,
EVEX_FIELD_STATUS,
EVEX_FIELD_ON_COMPLETION,
EVEX_FIELD_COMMENT,
EVEX_FIELD_COUNT /* a cool trick to count the number of fields :) */
} ;
#define EVEX_DB_FIELD_LEN 64
#define EVEX_NAME_FIELD_LEN 64
#define EVEX_MAX_INTERVAL_VALUE 2147483647L
@ -53,11 +33,10 @@ my_time_compare(TIME *a, TIME *b);
int
evex_db_find_event_aux(THD *thd, const LEX_STRING dbname,
const LEX_STRING rname, TABLE *table);
const LEX_STRING rname,
const LEX_STRING definer,
TABLE *table);
int
evex_open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
int
event_timed_compare_q(void *vptr, byte* a, byte *b);

View file

@ -307,6 +307,8 @@ event_timed::init_starts(THD *thd, Item *new_starts)
thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp,
(my_time_t) thd->query_start());
DBUG_PRINT("info",("now =%lld", TIME_to_ulonglong_datetime(&time_tmp)));
DBUG_PRINT("info",("starts=%lld", TIME_to_ulonglong_datetime(&ltime)));
if (TIME_to_ulonglong_datetime(&ltime) <
TIME_to_ulonglong_datetime(&time_tmp))
DBUG_RETURN(EVEX_BAD_PARAMS);
@ -413,6 +415,16 @@ event_timed::init_definer(THD *thd)
definer_host.str= strdup_root(thd->mem_root, thd->security_ctx->priv_host);
definer_host.length= strlen(thd->security_ctx->priv_host);
definer.length= definer_user.length + definer_host.length + 1;
definer.str= alloc_root(thd->mem_root, definer.length + 1);
memcpy(definer.str, definer_user.str, definer_user.length);
definer.str[definer_user.length]= '@';
memcpy(definer.str + definer_user.length + 1, definer_host.str,
definer_host.length);
definer.str[definer.length]= '\0';
DBUG_RETURN(0);
}
@ -486,7 +498,6 @@ event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table)
et->definer_host.str= strmake_root(mem_root, ptr + 1, len);//1: because of @
et->definer_host.length= len;
res1= table->field[EVEX_FIELD_STARTS]->
get_date(&et->starts, TIME_NO_ZERO_DATE);
@ -542,8 +553,7 @@ event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table)
goto error;
DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", et->name.str, ptr));
et->status= (ptr[0]=='E'? MYSQL_EVENT_ENABLED:
MYSQL_EVENT_DISABLED);
et->status= (ptr[0]=='E'? MYSQL_EVENT_ENABLED:MYSQL_EVENT_DISABLED);
// ToDo : Andrey . Find a way not to allocate ptr on event_mem_root
if ((ptr= get_field(mem_root,
@ -681,7 +691,8 @@ event_timed::compute_next_execution_time()
}
time((time_t *)&now);
my_tz_UTC->gmt_sec_to_TIME(&time_now, now);
/*
#ifdef ANDREY_0
sql_print_information("[%s.%s]", dbname.str, name.str);
sql_print_information("time_now : [%d-%d-%d %d:%d:%d ]",
time_now.year, time_now.month, time_now.day,
@ -696,7 +707,8 @@ event_timed::compute_next_execution_time()
last_executed.month, last_executed.day,
last_executed.hour, last_executed.minute,
last_executed.second);
*/
#endif
//if time_now is after ends don't execute anymore
if (ends.year && (tmp= my_time_compare(&ends, &time_now)) == -1)
{
@ -871,7 +883,7 @@ event_timed::drop(THD *thd)
if (evex_open_event_table(thd, TL_WRITE, &table))
DBUG_RETURN(-1);
if (evex_db_find_event_aux(thd, dbname, name, table))
if (evex_db_find_event_aux(thd, dbname, name, definer, table))
DBUG_RETURN(-2);
if ((ret= table->file->ha_delete_row(table->record[0])))
@ -907,11 +919,12 @@ event_timed::update_fields(THD *thd)
}
if ((ret= evex_db_find_event_aux(thd, dbname, name, table)))
if ((ret= evex_db_find_event_aux(thd, dbname, name, definer, table)))
goto done;
store_record(table,record[1]);
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; // Don't update create on row update.
// Don't update create on row update.
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
if (last_executed_changed)
{

View file

@ -6718,6 +6718,7 @@ SHOW_VAR status_vars[]= {
{"Com_show_engine_logs", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_LOGS]), SHOW_LONG_STATUS},
{"Com_show_engine_mutex", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_MUTEX]), SHOW_LONG_STATUS},
{"Com_show_engine_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_STATUS]), SHOW_LONG_STATUS},
{"Com_show_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_EVENTS]), SHOW_LONG_STATUS},
{"Com_show_errors", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ERRORS]), SHOW_LONG_STATUS},
{"Com_show_fields", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FIELDS]), SHOW_LONG_STATUS},
{"Com_show_grants", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS},

View file

@ -101,7 +101,7 @@ enum enum_sql_command {
SQLCOM_SHOW_AUTHORS, SQLCOM_BINLOG_BASE64_EVENT,
SQLCOM_SHOW_PLUGINS,
SQLCOM_CREATE_EVENT, SQLCOM_ALTER_EVENT, SQLCOM_DROP_EVENT,
SQLCOM_SHOW_CREATE_EVENT,
SQLCOM_SHOW_CREATE_EVENT, SQLCOM_SHOW_EVENTS,
/* This should be the last !!! */

View file

@ -2161,6 +2161,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
case SCH_TABLES:
case SCH_VIEWS:
case SCH_TRIGGERS:
case SCH_EVENTS:
#ifdef DONT_ALLOW_SHOW_COMMANDS
my_message(ER_NOT_ALLOWED_COMMAND,
ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */
@ -2449,11 +2450,15 @@ mysql_execute_command(THD *thd)
if (all_tables)
{
if (lex->orig_sql_command != SQLCOM_SHOW_STATUS_PROC &&
lex->orig_sql_command != SQLCOM_SHOW_STATUS_FUNC)
lex->orig_sql_command != SQLCOM_SHOW_STATUS_FUNC &&
lex->orig_sql_command != SQLCOM_SHOW_EVENTS)
res= check_table_access(thd,
lex->exchange ? SELECT_ACL | FILE_ACL :
SELECT_ACL,
all_tables, 0);
else if (lex->orig_sql_command == SQLCOM_SHOW_EVENTS)
res= check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0,
is_schema_db(thd->lex->select_lex.db));
}
else
res= check_access(thd,

View file

@ -25,6 +25,7 @@
#include "sp_head.h"
#include "sql_trigger.h"
#include "authors.h"
#include "event.h"
#include <my_dir.h>
#ifdef WITH_PARTITION_STORAGE_ENGINE
@ -1901,6 +1902,7 @@ void get_index_field_values(LEX *lex, INDEX_FIELD_VALUES *index_field_values)
case SQLCOM_SHOW_TABLES:
case SQLCOM_SHOW_TABLE_STATUS:
case SQLCOM_SHOW_TRIGGERS:
case SQLCOM_SHOW_EVENTS:
index_field_values->db_value= lex->select_lex.db;
index_field_values->table_value= wild;
break;
@ -3770,6 +3772,269 @@ static int get_schema_partitions_record(THD *thd, struct st_table_list *tables,
}
static LEX_STRING interval_type_to_name[] = {
{(char *) STRING_WITH_LEN("INTERVAL_YEAR")},
{(char *) STRING_WITH_LEN("INTERVAL_QUARTER")},
{(char *) STRING_WITH_LEN("INTERVAL_MONTH")},
{(char *) STRING_WITH_LEN("INTERVAL_DAY")},
{(char *) STRING_WITH_LEN("INTERVAL_HOUR")},
{(char *) STRING_WITH_LEN("INTERVAL_MINUTE")},
{(char *) STRING_WITH_LEN("INTERVAL_WEEK")},
{(char *) STRING_WITH_LEN("INTERVAL_SECOND")},
{(char *) STRING_WITH_LEN("INTERVAL_MICROSECOND ")},
{(char *) STRING_WITH_LEN("INTERVAL_YEAR_MONTH")},
{(char *) STRING_WITH_LEN("INTERVAL_DAY_HOUR")},
{(char *) STRING_WITH_LEN("INTERVAL_DAY_MINUTE")},
{(char *) STRING_WITH_LEN("INTERVAL_DAY_SECOND")},
{(char *) STRING_WITH_LEN("INTERVAL_HOUR_MINUTE")},
{(char *) STRING_WITH_LEN("INTERVAL_HOUR_SECOND")},
{(char *) STRING_WITH_LEN("INTERVAL_MINUTE_SECOND")},
{(char *) STRING_WITH_LEN("INTERVAL_DAY_MICROSECOND")},
{(char *) STRING_WITH_LEN("INTERVAL_HOUR_MICROSECOND")},
{(char *) STRING_WITH_LEN("INTERVAL_MINUTE_MICROSECOND")},
{(char *) STRING_WITH_LEN("INTERVAL_SECOND_MICROSECOND")}
};
static interval_type get_real_interval_type(interval_type i_type)
{
switch (i_type) {
case INTERVAL_YEAR:
return INTERVAL_YEAR;
case INTERVAL_QUARTER:
case INTERVAL_YEAR_MONTH:
case INTERVAL_MONTH:
return INTERVAL_MONTH;
case INTERVAL_WEEK:
case INTERVAL_DAY:
return INTERVAL_DAY;
case INTERVAL_DAY_HOUR:
case INTERVAL_HOUR:
return INTERVAL_HOUR;
case INTERVAL_DAY_MINUTE:
case INTERVAL_HOUR_MINUTE:
case INTERVAL_MINUTE:
return INTERVAL_MINUTE;
case INTERVAL_DAY_SECOND:
case INTERVAL_HOUR_SECOND:
case INTERVAL_MINUTE_SECOND:
case INTERVAL_SECOND:
return INTERVAL_SECOND;
case INTERVAL_DAY_MICROSECOND:
case INTERVAL_HOUR_MICROSECOND:
case INTERVAL_MINUTE_MICROSECOND:
case INTERVAL_SECOND_MICROSECOND:
case INTERVAL_MICROSECOND:
return INTERVAL_MICROSECOND;
}
DBUG_ASSERT(0);
return INTERVAL_SECOND;
}
static int
fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
{
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
CHARSET_INFO *scs= system_charset_info;
TIME time;
event_timed et;
DBUG_ENTER("fill_events_copy_to_schema_tab");
restore_record(sch_table, s->default_values);
if (et.load_from_row(thd->mem_root, event_table))
{
my_error(ER_EVENT_CANNOT_LOAD_FROM_TABLE, MYF(0));
DBUG_RETURN(1);
}
if (!(!wild || !wild[0] || !wild_compare(et.name.str, wild, 0)))
DBUG_RETURN(0);
//->field[0] is EVENT_CATALOG and is by default NULL
sch_table->field[1]->store(et.dbname.str, et.dbname.length, scs);
sch_table->field[2]->store(et.name.str, et.name.length, scs);
sch_table->field[3]->store(et.definer.str, et.definer.length, scs);
sch_table->field[4]->store(et.body.str, et.body.length, scs);
// [9] is SQL_MODE and is NULL for now, will be fixed later
sch_table->field[9]->set_null();
if (et.expression)
{
//type
sch_table->field[5]->store(STRING_WITH_LEN("RECURRING"), scs);
//execute_at
sch_table->field[6]->set_null();
//interval_value
sch_table->field[7]->set_notnull();
sch_table->field[7]->store((longlong) et.expression);
//interval_type
LEX_STRING *ival=&interval_type_to_name[get_real_interval_type(et.interval)];
sch_table->field[8]->set_notnull();
sch_table->field[8]->store(ival->str, ival->length, scs);
//starts & ends
sch_table->field[10]->set_notnull();
sch_table->field[10]->store_time(&et.starts, MYSQL_TIMESTAMP_DATETIME);
sch_table->field[11]->set_notnull();
sch_table->field[11]->store_time(&et.ends, MYSQL_TIMESTAMP_DATETIME);
}
else
{
//type
sch_table->field[5]->store(STRING_WITH_LEN("ONE TIME"), scs);
//execute_at
sch_table->field[6]->set_notnull();
sch_table->field[6]->store_time(&et.execute_at, MYSQL_TIMESTAMP_DATETIME);
//interval
sch_table->field[7]->set_null();
//interval_type
sch_table->field[8]->set_null();
//starts & ends
sch_table->field[10]->set_null();
sch_table->field[11]->set_null();
}
//status
if (et.status == MYSQL_EVENT_ENABLED)
sch_table->field[12]->store(STRING_WITH_LEN("ENABLED"), scs);
else
sch_table->field[12]->store(STRING_WITH_LEN("DISABLED"), scs);
//on_completion
if (et.on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
sch_table->field[13]->store(STRING_WITH_LEN("NOT PRESERVE"), scs);
else
sch_table->field[13]->store(STRING_WITH_LEN("PRESERVE"), scs);
int not_used=0;
number_to_datetime(et.created, &time, 0, &not_used);
DBUG_ASSERT(not_used==0);
sch_table->field[14]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
number_to_datetime(et.modified, &time, 0, &not_used);
DBUG_ASSERT(not_used==0);
sch_table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
if (et.last_executed.year)
sch_table->field[16]->store_time(&et.last_executed,MYSQL_TIMESTAMP_DATETIME);
else
sch_table->field[16]->set_null();
sch_table->field[17]->store(et.comment.str, et.comment.length, scs);
if (schema_table_store_record(thd, sch_table))
DBUG_RETURN(1);
DBUG_RETURN(0);
}
int fill_schema_events(THD *thd, TABLE_LIST *tables, COND *cond)
{
TABLE *table= tables->table;
CHARSET_INFO *scs= system_charset_info;
TABLE *event_table= NULL;
Open_tables_state backup;
int ret=0;
bool verbose= false;
char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
bool use_prefix_scanning= true;
uint key_len= 0;
byte *key_buf= NULL;
LINT_INIT(key_buf);
DBUG_ENTER("fill_schema_events");
strxmov(definer, thd->security_ctx->priv_user,"@",thd->security_ctx->priv_host,
NullS);
DBUG_PRINT("info",("db=%s current_user=%s", thd->lex->select_lex.db, definer));
thd->reset_n_backup_open_tables_state(&backup);
if ((ret= evex_open_event_table(thd, TL_READ, &event_table)))
{
sql_print_error("Table mysql.event is damaged.");
ret= 1;
goto err;
}
event_table->file->ha_index_init(0, 1);
/*
see others' events only if you have PROCESS_ACL !!
thd->lex->verbose is set either if SHOW FULL EVENTS or
in case of SELECT FROM I_S.EVENTS
*/
verbose= (thd->lex->verbose
&& (thd->security_ctx->master_access & PROCESS_ACL));
if (verbose && thd->security_ctx->user)
{
ret= event_table->file->index_first(event_table->record[0]);
use_prefix_scanning= false;
}
else
{
event_table->field[EVEX_FIELD_DEFINER]->store(definer, strlen(definer), scs);
key_len= event_table->key_info->key_part[0].store_length;
if (thd->lex->select_lex.db)
{
event_table->field[EVEX_FIELD_DB]->
store(thd->lex->select_lex.db, strlen(thd->lex->select_lex.db), scs);
key_len+= event_table->key_info->key_part[1].store_length;
}
if (!(key_buf= alloc_root(thd->mem_root, key_len)))
{
ret= 1;
goto err;
}
key_copy(key_buf, event_table->record[0], event_table->key_info, key_len);
ret= event_table->file->index_read(event_table->record[0], key_buf, key_len,
HA_READ_PREFIX);
}
if (ret)
{
ret= (ret == HA_ERR_END_OF_FILE || ret == HA_ERR_KEY_NOT_FOUND) ? 0 : 1;
goto err;
}
while (!ret)
{
if ((ret= fill_events_copy_to_schema_table(thd, table, event_table)))
goto err;
if (use_prefix_scanning)
ret= event_table->file->
index_next_same(event_table->record[0], key_buf, key_len);
else
ret= event_table->file->index_next(event_table->record[0]);
}
// ret is guaranteed to be != 0
ret= (ret != HA_ERR_END_OF_FILE);
err:
if (event_table)
{
event_table->file->ha_index_end();
close_thread_tables(thd);
}
thd->restore_backup_open_tables_state(&backup);
DBUG_RETURN(ret);
}
int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond)
{
DBUG_ENTER("fill_open_tables");
@ -4390,6 +4655,31 @@ ST_FIELD_INFO engines_fields_info[]=
};
ST_FIELD_INFO events_fields_info[]=
{
{"EVENT_CATALOG", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
{"EVENT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Db"},
{"EVENT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"},
{"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer"},
{"EVENT_BODY", 65535, MYSQL_TYPE_STRING, 0, 0, 0},
{"EVENT_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type"},
{"EXECUTE_AT", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Execute at"},
{"INTERVAL_VALUE", 11, MYSQL_TYPE_LONG, 0, 1, "Interval value"},
{"INTERVAL_FIELD", 18, MYSQL_TYPE_STRING, 0, 1, "Interval field"},
{"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 1, 0},
{"STARTS", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Starts"},
{"ENDS", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Ends"},
{"STATUS", 8, MYSQL_TYPE_STRING, 0, 0, "Status"},
{"ON_COMPLETION", 12, MYSQL_TYPE_STRING, 0, 0, 0},
{"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0},
{"LAST_ALTERED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0},
{"LAST_EXECUTED", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, 0},
{"EVENT_COMMENT", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
};
ST_FIELD_INFO coll_charset_app_fields_info[]=
{
{"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0},
@ -4655,6 +4945,8 @@ ST_SCHEMA_TABLE schema_tables[]=
fill_schema_column_privileges, 0, 0, -1, -1, 0},
{"ENGINES", engines_fields_info, create_schema_table,
fill_schema_engines, make_old_format, 0, -1, -1, 0},
{"EVENTS", events_fields_info, create_schema_table,
fill_schema_events, make_old_format, 0, -1, -1, 0},
{"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0},
{"OPEN_TABLES", open_tables_fields_info, create_schema_table,

View file

@ -1355,8 +1355,11 @@ create:
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES);
if (!lex->et_compile_phase)
if (!lex->et_compile_phase)
{
lex->et->init_name(YYTHD, $4);
lex->et->init_definer(YYTHD);
}
}
ON SCHEDULE_SYM ev_schedule_time
opt_ev_on_completion
@ -1599,7 +1602,6 @@ ev_sql_stmt:
if (!lex->et_compile_phase)
{
lex->et->init_body(YYTHD);
lex->et->init_definer(YYTHD);
}
}
;
@ -4816,8 +4818,13 @@ alter:
if (!(et= new event_timed()))// implicitly calls event_timed::init()
YYABORT;
lex->et = et;
et->init_name(YYTHD, $3);
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
stored procedure, otherwise yylex will chop it into pieces
@ -4825,7 +4832,6 @@ alter:
*/
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
}
ev_alter_on_schedule_completion
opt_ev_rename_to
@ -7664,7 +7670,6 @@ drop:
if (lex->et)
{
// ToDo Andrey : Change the error message
/*
Recursive events are not possible because recursive SPs
are not also possible. lex->sp_head is not stacked.
@ -7675,8 +7680,13 @@ drop:
if (!(lex->et= new event_timed()))
YYABORT;
lex->et->init_name(YYTHD, $4);
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;
}
@ -8068,6 +8078,15 @@ show_param:
if (prepare_schema_table(YYTHD, lex, 0, SCH_TRIGGERS))
YYABORT;
}
| opt_full EVENTS_SYM opt_db wild_and_where
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT;
lex->orig_sql_command= SQLCOM_SHOW_EVENTS;
lex->select_lex.db= $3;
if (prepare_schema_table(YYTHD, lex, 0, SCH_EVENTS))
YYABORT;
}
| TABLE_SYM STATUS_SYM opt_db wild_and_where
{
LEX *lex= Lex;

View file

@ -338,6 +338,7 @@ enum enum_schema_tables
SCH_COLUMNS,
SCH_COLUMN_PRIVILEGES,
SCH_ENGINES,
SCH_EVENTS,
SCH_KEY_COLUMN_USAGE,
SCH_OPEN_TABLES,
SCH_PARTITIONS,