Skip to content

Commit

Permalink
MDEV-7281 EVENT: CREATE OR REPLACE
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Barkov committed Feb 27, 2015
1 parent 77806da commit 2d01907
Show file tree
Hide file tree
Showing 12 changed files with 211 additions and 15 deletions.
24 changes: 24 additions & 0 deletions mysql-test/r/create_drop_binlog.result
Original file line number Diff line number Diff line change
Expand Up @@ -243,3 +243,27 @@ Log_name Pos Event_type Server_id End_log_pos Info
# # Gtid 1 # GTID #-#-#
# # Query 1 # use `test`; DROP USER IF EXISTS u1@localhost
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;
48 changes: 48 additions & 0 deletions mysql-test/r/create_drop_event.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
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;
24 changes: 24 additions & 0 deletions mysql-test/suite/rpl/r/rpl_create_drop_event.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
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
27 changes: 27 additions & 0 deletions mysql-test/suite/rpl/t/rpl_create_drop_event.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--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
12 changes: 12 additions & 0 deletions mysql-test/t/create_drop_binlog.test
Original file line number Diff line number Diff line change
Expand Up @@ -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/
SHOW BINLOG EVENTS;
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;
44 changes: 44 additions & 0 deletions mysql-test/t/create_drop_event.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
--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;
18 changes: 14 additions & 4 deletions sql/event_db_repository.cc
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,6 @@ Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type,

bool
Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
bool create_if_not,
bool *event_already_exists)
{
int ret= 1;
Expand Down Expand Up @@ -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"));
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;
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_EVENT_ALREADY_EXISTS, ER(ER_EVENT_ALREADY_EXISTS),
parse_data->name.str);
ret= 0;
goto end;
}
else
{
my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), parse_data->name.str);

goto end;
goto end;
}
} else
*event_already_exists= false;

Expand Down
2 changes: 1 addition & 1 deletion sql/event_db_repository.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class Event_db_repository
Event_db_repository(){}

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
update_event(THD *thd, Event_parse_data *parse_data, LEX_STRING *new_dbname,
Expand Down
18 changes: 12 additions & 6 deletions sql/events.cc
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,12 @@ create_query_string(THD *thd, String *buf)
{
buf->length(0);
/* 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;
/* Append definer */
append_definer(thd, buf, &(thd->lex->definer->user), &(thd->lex->definer->host));
Expand All @@ -292,8 +297,7 @@ create_query_string(THD *thd, String *buf)
@param[in,out] thd THD
@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
IF NOT EXISTS is specified, an warning is put into the stack.
@sa Events::drop_event for the notes about locking, pre-locking
Expand All @@ -304,8 +308,7 @@ create_query_string(THD *thd, String *buf)
*/

bool
Events::create_event(THD *thd, Event_parse_data *parse_data,
bool if_not_exists)
Events::create_event(THD *thd, Event_parse_data *parse_data)
{
bool ret;
bool event_already_exists;
Expand Down Expand Up @@ -347,8 +350,11 @@ Events::create_event(THD *thd, Event_parse_data *parse_data,
parse_data->dbname.str, parse_data->name.str))
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 */
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_queue_element *new_element;
Expand Down
2 changes: 1 addition & 1 deletion sql/events.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class Events
destroy_mutexes();

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
update_event(THD *thd, Event_parse_data *parse_data,
Expand Down
3 changes: 1 addition & 2 deletions sql/sql_parse.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4439,8 +4439,7 @@ mysql_execute_command(THD *thd)
switch (lex->sql_command) {
case SQLCOM_CREATE_EVENT:
{
bool if_not_exists= lex->create_info.if_not_exists();
res= Events::create_event(thd, lex->event_parse_data, if_not_exists);
res= Events::create_event(thd, lex->event_parse_data);
break;
}
case SQLCOM_ALTER_EVENT:
Expand Down
4 changes: 3 additions & 1 deletion sql/sql_yacc.yy
Original file line number Diff line number Diff line change
Expand Up @@ -2563,6 +2563,7 @@ create:
{
// TODO: remove this when "MDEV-5359 CREATE OR REPLACE..." is done
if ($1.or_replace() &&
Lex->sql_command != SQLCOM_CREATE_EVENT &&
Lex->sql_command != SQLCOM_CREATE_VIEW &&
Lex->sql_command != SQLCOM_CREATE_FUNCTION &&
Lex->sql_command != SQLCOM_CREATE_SPFUNCTION &&
Expand Down Expand Up @@ -2657,7 +2658,8 @@ event_tail:
LEX *lex=Lex;

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)))
MYSQL_YYABORT;
lex->event_parse_data->identifier= $4;
Expand Down

0 comments on commit 2d01907

Please sign in to comment.