Commit 2d01907c authored by Alexander Barkov's avatar Alexander Barkov

MDEV-7281 EVENT: CREATE OR REPLACE

parent 77806da0
...@@ -243,3 +243,27 @@ Log_name Pos Event_type Server_id End_log_pos Info ...@@ -243,3 +243,27 @@ Log_name Pos Event_type Server_id End_log_pos Info
# # Gtid 1 # GTID #-#-# # # Gtid 1 # GTID #-#-#
# # Query 1 # use `test`; DROP USER IF EXISTS u1@localhost # # Query 1 # use `test`; DROP USER IF EXISTS u1@localhost
RESET MASTER; RESET MASTER;
SET timestamp=UNIX_TIMESTAMP('2014-11-01 10:20:30');
CREATE OR REPLACE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO DROP TABLE IF EXISTS t1;
CREATE OR REPLACE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO DROP TABLE IF EXISTS t2;
SELECT EVENT_NAME, EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
EVENT_NAME EVENT_DEFINITION
ev1 DROP TABLE IF EXISTS t2
DROP EVENT ev1;
DROP EVENT IF EXISTS ev1;
Warnings:
Note 1305 Event ev1 does not exist
SHOW BINLOG EVENTS;
Log_name Pos Event_type Server_id End_log_pos Info
# # Format_desc 1 # VER
# # Gtid_list 1 # []
# # Binlog_checkpoint 1 # master-bin.000001
# # Gtid 1 # GTID #-#-#
# # Query 1 # use `test`; CREATE OR REPLACE DEFINER=`root`@`localhost` EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO DROP TABLE IF EXISTS t1
# # Gtid 1 # GTID #-#-#
# # Query 1 # use `test`; CREATE OR REPLACE DEFINER=`root`@`localhost` EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO DROP TABLE IF EXISTS t2
# # Gtid 1 # GTID #-#-#
# # Query 1 # use `test`; DROP EVENT ev1
# # Gtid 1 # GTID #-#-#
# # Query 1 # use `test`; DROP EVENT IF EXISTS ev1
RESET MASTER;
SET timestamp=UNIX_TIMESTAMP('2014-11-01 10:20:30');
SET GLOBAL event_scheduler=off;
CREATE TABLE t1 (a INT);
CREATE OR REPLACE EVENT IF NOT EXISTS ev1 ON SCHEDULE EVERY 1 SECOND DO DROP DATABASE db1;
ERROR HY000: Incorrect usage of OR REPLACE and IF NOT EXISTS
CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (10);
SELECT EVENT_NAME, EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
EVENT_NAME EVENT_DEFINITION
ev1 INSERT INTO t1 VALUES (10)
SET GLOBAL event_scheduler=on;
SELECT DISTINCT a FROM t1;
a
10
SET GLOBAL event_scheduler=off;
DELETE FROM t1;
CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (11);
ERROR HY000: Event 'ev1' already exists
SELECT EVENT_NAME, EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
EVENT_NAME EVENT_DEFINITION
ev1 INSERT INTO t1 VALUES (10)
CREATE EVENT IF NOT EXISTS ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (12);
Warnings:
Note 1537 Event 'ev1' already exists
SELECT EVENT_NAME, EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
EVENT_NAME EVENT_DEFINITION
ev1 INSERT INTO t1 VALUES (10)
CREATE OR REPLACE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (13);
SELECT EVENT_NAME, EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
EVENT_NAME EVENT_DEFINITION
ev1 INSERT INTO t1 VALUES (13)
SET GLOBAL event_scheduler=on;
SELECT DISTINCT a FROM t1;
a
13
SET GLOBAL event_scheduler=off;
DELETE FROM t1;
DROP EVENT IF EXISTS ev1;
SELECT EVENT_NAME, EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
EVENT_NAME EVENT_DEFINITION
DROP EVENT IF EXISTS ev1;
Warnings:
Note 1305 Event ev1 does not exist
DROP EVENT ev1;
ERROR HY000: Unknown event 'ev1'
SELECT EVENT_NAME, EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
EVENT_NAME EVENT_DEFINITION
DROP TABLE t1;
SET timestamp=DEFAULT;
include/master-slave.inc
[connection master]
SET GLOBAL event_scheduler=off;
CREATE TABLE t1 (a INT);
CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (10);
CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (11);
ERROR HY000: Event 'ev1' already exists
CREATE OR REPLACE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (11);
SELECT EVENT_NAME,STATUS,EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
EVENT_NAME STATUS EVENT_DEFINITION
ev1 ENABLED INSERT INTO t1 VALUES (11)
SET GLOBAL event_scheduler=on;
SET GLOBAL event_scheduler=off;
SELECT DISTINCT a FROM t1;
a
11
DELETE FROM t1;
# Syncing slave with master
SELECT EVENT_NAME,STATUS,EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
EVENT_NAME STATUS EVENT_DEFINITION
ev1 SLAVESIDE_DISABLED INSERT INTO t1 VALUES (11)
DROP TABLE t1;
DROP EVENT ev1;
include/rpl_end.inc
--source include/master-slave.inc
connection master;
SET GLOBAL event_scheduler=off;
CREATE TABLE t1 (a INT);
CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (10);
--error ER_EVENT_ALREADY_EXISTS
CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (11);
CREATE OR REPLACE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (11);
SELECT EVENT_NAME,STATUS,EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
SET GLOBAL event_scheduler=on;
let $wait_condition= SELECT count(*)>0 FROM t1;
--source include/wait_condition.inc
SET GLOBAL event_scheduler=off;
SELECT DISTINCT a FROM t1;
DELETE FROM t1;
--echo # Syncing slave with master
sync_slave_with_master;
SELECT EVENT_NAME,STATUS,EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
connection master;
DROP TABLE t1;
DROP EVENT ev1;
sync_slave_with_master;
--source include/rpl_end.inc
...@@ -119,3 +119,15 @@ DROP USER IF EXISTS u1@localhost; ...@@ -119,3 +119,15 @@ DROP USER IF EXISTS u1@localhost;
--replace_regex /xid=[0-9]+/xid=XX/ /GTID [0-9]+-[0-9]+-[0-9]+/GTID #-#-#/ /Server.ver.*/VER/ --replace_regex /xid=[0-9]+/xid=XX/ /GTID [0-9]+-[0-9]+-[0-9]+/GTID #-#-#/ /Server.ver.*/VER/
SHOW BINLOG EVENTS; SHOW BINLOG EVENTS;
RESET MASTER; RESET MASTER;
SET timestamp=UNIX_TIMESTAMP('2014-11-01 10:20:30');
CREATE OR REPLACE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO DROP TABLE IF EXISTS t1;
CREATE OR REPLACE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO DROP TABLE IF EXISTS t2;
SELECT EVENT_NAME, EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
DROP EVENT ev1;
DROP EVENT IF EXISTS ev1;
--replace_column 1 # 2 # 5 #
--replace_regex /xid=[0-9]+/xid=XX/ /GTID [0-9]+-[0-9]+-[0-9]+/GTID #-#-#/ /Server.ver.*/VER/
SHOW BINLOG EVENTS;
RESET MASTER;
--source include/not_embedded.inc
SET timestamp=UNIX_TIMESTAMP('2014-11-01 10:20:30');
SET GLOBAL event_scheduler=off;
CREATE TABLE t1 (a INT);
--error ER_WRONG_USAGE
CREATE OR REPLACE EVENT IF NOT EXISTS ev1 ON SCHEDULE EVERY 1 SECOND DO DROP DATABASE db1;
CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (10);
SELECT EVENT_NAME, EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
SET GLOBAL event_scheduler=on;
let $wait_condition= SELECT count(*)>0 FROM t1;
--source include/wait_condition.inc
SELECT DISTINCT a FROM t1;
SET GLOBAL event_scheduler=off;
DELETE FROM t1;
--error ER_EVENT_ALREADY_EXISTS
CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (11);
SELECT EVENT_NAME, EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
CREATE EVENT IF NOT EXISTS ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (12);
SELECT EVENT_NAME, EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
CREATE OR REPLACE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (13);
SELECT EVENT_NAME, EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
SET GLOBAL event_scheduler=on;
let $wait_condition= SELECT count(*)>0 FROM t1;
--source include/wait_condition.inc
SELECT DISTINCT a FROM t1;
SET GLOBAL event_scheduler=off;
DELETE FROM t1;
DROP EVENT IF EXISTS ev1;
SELECT EVENT_NAME, EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
DROP EVENT IF EXISTS ev1;
--error ER_EVENT_DOES_NOT_EXIST
DROP EVENT ev1;
SELECT EVENT_NAME, EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
DROP TABLE t1;
SET timestamp=DEFAULT;
...@@ -654,7 +654,6 @@ Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type, ...@@ -654,7 +654,6 @@ Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type,
bool bool
Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data, Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
bool create_if_not,
bool *event_already_exists) bool *event_already_exists)
{ {
int ret= 1; int ret= 1;
...@@ -685,18 +684,29 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data, ...@@ -685,18 +684,29 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
DBUG_PRINT("info", ("check existance of an event with the same name")); DBUG_PRINT("info", ("check existance of an event with the same name"));
if (!find_named_event(parse_data->dbname, parse_data->name, table)) if (!find_named_event(parse_data->dbname, parse_data->name, table))
{ {
if (create_if_not) if (thd->lex->create_info.or_replace())
{
*event_already_exists= false; // Force the caller to update event_queue
if ((ret= table->file->ha_delete_row(table->record[0])))
{
table->file->print_error(ret, MYF(0));
goto end;
}
}
else if (thd->lex->create_info.if_not_exists())
{ {
*event_already_exists= true; *event_already_exists= true;
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_EVENT_ALREADY_EXISTS, ER(ER_EVENT_ALREADY_EXISTS), ER_EVENT_ALREADY_EXISTS, ER(ER_EVENT_ALREADY_EXISTS),
parse_data->name.str); parse_data->name.str);
ret= 0; ret= 0;
goto end;
} }
else else
{
my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), parse_data->name.str); my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), parse_data->name.str);
goto end;
goto end; }
} else } else
*event_already_exists= false; *event_already_exists= false;
......
...@@ -74,7 +74,7 @@ public: ...@@ -74,7 +74,7 @@ public:
Event_db_repository(){} Event_db_repository(){}
bool bool
create_event(THD *thd, Event_parse_data *parse_data, bool create_if_not, create_event(THD *thd, Event_parse_data *parse_data,
bool *event_already_exists); bool *event_already_exists);
bool bool
update_event(THD *thd, Event_parse_data *parse_data, LEX_STRING *new_dbname, update_event(THD *thd, Event_parse_data *parse_data, LEX_STRING *new_dbname,
......
...@@ -273,7 +273,12 @@ create_query_string(THD *thd, String *buf) ...@@ -273,7 +273,12 @@ create_query_string(THD *thd, String *buf)
{ {
buf->length(0); buf->length(0);
/* Append the "CREATE" part of the query */ /* Append the "CREATE" part of the query */
if (buf->append(STRING_WITH_LEN("CREATE "))) if (thd->lex->create_info.or_replace())
{
if (buf->append(STRING_WITH_LEN("CREATE OR REPLACE ")))
return 1;
}
else if (buf->append(STRING_WITH_LEN("CREATE ")))
return 1; return 1;
/* Append definer */ /* Append definer */
append_definer(thd, buf, &(thd->lex->definer->user), &(thd->lex->definer->host)); append_definer(thd, buf, &(thd->lex->definer->user), &(thd->lex->definer->host));
...@@ -292,8 +297,7 @@ create_query_string(THD *thd, String *buf) ...@@ -292,8 +297,7 @@ create_query_string(THD *thd, String *buf)
@param[in,out] thd THD @param[in,out] thd THD
@param[in] parse_data Event's data from parsing stage @param[in] parse_data Event's data from parsing stage
@param[in] if_not_exists Whether IF NOT EXISTS was
specified
In case there is an event with the same name (db) and In case there is an event with the same name (db) and
IF NOT EXISTS is specified, an warning is put into the stack. IF NOT EXISTS is specified, an warning is put into the stack.
@sa Events::drop_event for the notes about locking, pre-locking @sa Events::drop_event for the notes about locking, pre-locking
...@@ -304,8 +308,7 @@ create_query_string(THD *thd, String *buf) ...@@ -304,8 +308,7 @@ create_query_string(THD *thd, String *buf)
*/ */
bool bool
Events::create_event(THD *thd, Event_parse_data *parse_data, Events::create_event(THD *thd, Event_parse_data *parse_data)
bool if_not_exists)
{ {
bool ret; bool ret;
bool event_already_exists; bool event_already_exists;
...@@ -347,8 +350,11 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, ...@@ -347,8 +350,11 @@ Events::create_event(THD *thd, Event_parse_data *parse_data,
parse_data->dbname.str, parse_data->name.str)) parse_data->dbname.str, parse_data->name.str))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (thd->lex->create_info.or_replace() && event_queue)
event_queue->drop_event(thd, parse_data->dbname, parse_data->name);
/* On error conditions my_error() is called so no need to handle here */ /* On error conditions my_error() is called so no need to handle here */
if (!(ret= db_repository->create_event(thd, parse_data, if_not_exists, if (!(ret= db_repository->create_event(thd, parse_data,
&event_already_exists))) &event_already_exists)))
{ {
Event_queue_element *new_element; Event_queue_element *new_element;
......
...@@ -104,7 +104,7 @@ public: ...@@ -104,7 +104,7 @@ public:
destroy_mutexes(); destroy_mutexes();
static bool static bool
create_event(THD *thd, Event_parse_data *parse_data, bool if_exists); create_event(THD *thd, Event_parse_data *parse_data);
static bool static bool
update_event(THD *thd, Event_parse_data *parse_data, update_event(THD *thd, Event_parse_data *parse_data,
......
...@@ -4439,8 +4439,7 @@ end_with_restore_list: ...@@ -4439,8 +4439,7 @@ end_with_restore_list:
switch (lex->sql_command) { switch (lex->sql_command) {
case SQLCOM_CREATE_EVENT: case SQLCOM_CREATE_EVENT:
{ {
bool if_not_exists= lex->create_info.if_not_exists(); res= Events::create_event(thd, lex->event_parse_data);
res= Events::create_event(thd, lex->event_parse_data, if_not_exists);
break; break;
} }
case SQLCOM_ALTER_EVENT: case SQLCOM_ALTER_EVENT:
......
...@@ -2563,6 +2563,7 @@ create: ...@@ -2563,6 +2563,7 @@ create:
{ {
// TODO: remove this when "MDEV-5359 CREATE OR REPLACE..." is done // TODO: remove this when "MDEV-5359 CREATE OR REPLACE..." is done
if ($1.or_replace() && if ($1.or_replace() &&
Lex->sql_command != SQLCOM_CREATE_EVENT &&
Lex->sql_command != SQLCOM_CREATE_VIEW && Lex->sql_command != SQLCOM_CREATE_VIEW &&
Lex->sql_command != SQLCOM_CREATE_FUNCTION && Lex->sql_command != SQLCOM_CREATE_FUNCTION &&
Lex->sql_command != SQLCOM_CREATE_SPFUNCTION && Lex->sql_command != SQLCOM_CREATE_SPFUNCTION &&
...@@ -2657,7 +2658,8 @@ event_tail: ...@@ -2657,7 +2658,8 @@ event_tail:
LEX *lex=Lex; LEX *lex=Lex;
lex->stmt_definition_begin= $1; lex->stmt_definition_begin= $1;
lex->create_info.set($3); if (lex->add_create_options_with_check($3))
MYSQL_YYABORT;
if (!(lex->event_parse_data= Event_parse_data::new_instance(thd))) if (!(lex->event_parse_data= Event_parse_data::new_instance(thd)))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->event_parse_data->identifier= $4; lex->event_parse_data->identifier= $4;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment