summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <andrey@lmy004.>2006-01-30 14:28:48 +0100
committerunknown <andrey@lmy004.>2006-01-30 14:28:48 +0100
commit2272e140fd1490772fa9660ece4ea91eed26cee7 (patch)
tree8ef0243df685fd27f6f69d8bcff5e5743c6a0648
parent799129e254fca5df0fddc910c371acce7fb666dc (diff)
parentc3542cebf9c775241652ef8f0a4ed7dd788683d7 (diff)
downloadmariadb-git-2272e140fd1490772fa9660ece4ea91eed26cee7.tar.gz
post-commit merge
mysql-test/lib/init_db.sql: Auto merged scripts/mysql_create_system_tables.sh: Auto merged scripts/mysql_fix_privilege_tables.sql: Auto merged sql/event.cc: Auto merged sql/event.h: Auto merged sql/event_executor.cc: Auto merged sql/event_priv.h: Auto merged sql/event_timed.cc: Auto merged sql/mysqld.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_yacc.yy: Auto merged mysql-test/r/events.result: manual merge mysql-test/r/system_mysql_db.result: manual merge mysql-test/t/events.test: manual merge
-rw-r--r--mysql-test/lib/init_db.sql2
-rw-r--r--mysql-test/r/events.result161
-rw-r--r--mysql-test/r/information_schema.result13
-rw-r--r--mysql-test/r/information_schema_db.result1
-rw-r--r--mysql-test/t/events.test76
-rw-r--r--scripts/mysql_create_system_tables.sh2
-rw-r--r--scripts/mysql_fix_privilege_tables.sql2
-rw-r--r--sql/event.cc63
-rw-r--r--sql/event.h33
-rw-r--r--sql/event_executor.cc5
-rw-r--r--sql/event_priv.h27
-rw-r--r--sql/event_timed.cc27
-rw-r--r--sql/mysqld.cc1
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_parse.cc7
-rw-r--r--sql/sql_show.cc292
-rw-r--r--sql/sql_yacc.yy31
-rw-r--r--sql/table.h1
18 files changed, 674 insertions, 72 deletions
diff --git a/mysql-test/lib/init_db.sql b/mysql-test/lib/init_db.sql
index b07af136c23..0c287aa092a 100644
--- a/mysql-test/lib/init_db.sql
+++ b/mysql-test/lib/init_db.sql
@@ -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;
diff --git a/mysql-test/r/events.result b/mysql-test/r/events.result
index 38c2d902ec1..df03cd4ec84 100644
--- a/mysql-test/r/events.result
+++ b/mysql-test/r/events.result
@@ -57,4 +57,165 @@ set event_scheduler=0;
ERROR HY000: Variable 'event_scheduler' is a GLOBAL variable and should be set with SET GLOBAL
set global event_scheduler=2;
ERROR 42000: Variable 'event_scheduler' can't be set to the value of '2'
+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'
+select "Here comes an error:";
+Here comes an error:
+Here comes an error:
+SHOW EVENTS;
+ERROR 42000: Access denied for user 'ev_test'@'localhost' to database 'events_test2'
+USE events_test;
+select "Now the list should be empty:";
+Now the list should be empty:
+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;
+select "Now we should see 3 events:";
+Now we should see 3 events:
+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
+select "This should show us only 3 events:";
+This should show us only 3 events:
+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
+select "This should show us only 2 events:";
+This should show us only 2 events:
+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
+select "This should show us no events:";
+This should show us no events:
+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;
+select "should see 1 event:";
+should see 1 event:
+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
+select "we should see 4 events now:";
+we should see 4 events now:
+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;
+set global event_scheduler=0;
+select count(*) from mysql.event;
+count(*)
+0
+select get_lock("test_lock1", 20);
+get_lock("test_lock1", 20)
+1
+create event закачка on schedule every 10 hour do select get_lock("test_lock1", 20);
+select count(*) from mysql.event;
+count(*)
+1
+select release_lock("test_lock1");
+release_lock("test_lock1")
+1
+drop event закачка;
+select count(*) from mysql.event;
+count(*)
+0
+set global event_scheduler=1;
+select get_lock("test_lock2", 20);
+get_lock("test_lock2", 20)
+1
+create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20);
+select sleep(2);
+sleep(2)
+0
+select release_lock("test_lock2");
+release_lock("test_lock2")
+1
+drop event закачка;
+set global event_scheduler=1;
+select get_lock("test_lock2_1", 20);
+get_lock("test_lock2_1", 20)
+1
+create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20);
+select sleep(2);
+sleep(2)
+0
+set global event_scheduler=0;
+select sleep(2);
+sleep(2)
+0
+select release_lock("test_lock2_1");
+release_lock("test_lock2_1")
+1
+select sleep(2);
+sleep(2)
+0
+drop event закачка21;
+set global event_scheduler=1;
+select get_lock("test_lock3", 20);
+get_lock("test_lock3", 20)
+1
+create event закачка on schedule every 10 hour do select get_lock("test_lock3", 20);
+select sleep(2);
+sleep(2)
+0
+drop event закачка;
+select release_lock("test_lock3");
+release_lock("test_lock3")
+1
+set global event_scheduler=0;
+select sleep(2);
+sleep(2)
+0
drop database events_test;
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
index 8778ded244f..40706fd9c55 100644
--- a/mysql-test/r/information_schema.result
+++ b/mysql-test/r/information_schema.result
@@ -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
diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result
index 7832e34dfd1..1ad996dedd5 100644
--- a/mysql-test/r/information_schema_db.result
+++ b/mysql-test/r/information_schema_db.result
@@ -7,6 +7,7 @@ COLLATION_CHARACTER_SET_APPLICABILITY
COLUMNS
COLUMN_PRIVILEGES
ENGINES
+EVENTS
KEY_COLUMN_USAGE
PARTITIONS
PLUGINS
diff --git a/mysql-test/t/events.test b/mysql-test/t/events.test
index c92e247ef7f..54dec5429b0 100644
--- a/mysql-test/t/events.test
+++ b/mysql-test/t/events.test
@@ -33,6 +33,82 @@ 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;
+
+select "Here comes an error:";
+#NO EVENT_ACL on events_test2
+--error 1044
+SHOW EVENTS;
+USE events_test;
+
+select "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;
+
+select "Now we should see 3 events:";
+--replace_column 8 # 9 #
+SHOW EVENTS;
+
+select "This should show us only 3 events:";
+--replace_column 8 # 9 #
+SHOW FULL EVENTS;
+
+select "This should show us only 2 events:";
+--replace_column 8 # 9 #
+SHOW FULL EVENTS LIKE 't%event';
+
+select "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;
+
+select "should see 1 event:";
+--replace_column 8 # 9 #
+SHOW EVENTS;
+
+select "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;
diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh
index 2822cef18ac..385e04a4cc2 100644
--- a/scripts/mysql_create_system_tables.sh
+++ b/scripts/mysql_create_system_tables.sh
@@ -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
diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql
index 360e8534773..c8014127085 100644
--- a/scripts/mysql_fix_privilege_tables.sql
+++ b/scripts/mysql_fix_privilege_tables.sql
@@ -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);
diff --git a/sql/event.cc b/sql/event.cc
index 4a6fff581a3..abca622835a 100644
--- a/sql/event.cc
+++ b/sql/event.cc
@@ -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])))
{
diff --git a/sql/event.h b/sql/event.h
index 80629fa0a70..6ee9cea25ac 100644
--- a/sql/event.h
+++ b/sql/event.h
@@ -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';
*/
diff --git a/sql/event_executor.cc b/sql/event_executor.cc
index 4eb92f9e430..dbbff2a8c58 100644
--- a/sql/event_executor.cc
+++ b/sql/event_executor.cc
@@ -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;
diff --git a/sql/event_priv.h b/sql/event_priv.h
index 42c60dd391d..7d1cdbcd264 100644
--- a/sql/event_priv.h
+++ b/sql/event_priv.h
@@ -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);
diff --git a/sql/event_timed.cc b/sql/event_timed.cc
index 4d3dea42e34..deab6e84c4f 100644
--- a/sql/event_timed.cc
+++ b/sql/event_timed.cc
@@ -413,6 +413,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 +496,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 +551,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 +689,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 +705,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 +881,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 +917,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)
{
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 50617521e72..f5b93e6a5e5 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -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},
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 67dc903b04b..07a42f7af2c 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -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 !!! */
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 98ed9353f80..ed7e7dfb684 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -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,
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 672f7fe8abe..58f94887ef6 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -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,
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index c5f4b81fa72..a86eccb493f 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -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;
diff --git a/sql/table.h b/sql/table.h
index eb0c0cf98d3..213310a51dc 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -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,