From: Dmitry Shulga Date: May 27 2011 10:36am Subject: bzr commit into mysql-trunk branch (Dmitry.Shulga:3122) Bug#12546938 List-Archive: http://lists.mysql.com/commits/138309 X-Bug: 12546938 Message-Id: <201105271037.p4RAb5Kb030806@acsmt357.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============7172727522613085362==" --===============7172727522613085362== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///Users/shulga/projects/mysql/mysql-trunk/ based on revid:tatjana.nuernberg@stripped 3122 Dmitry Shulga 2011-05-27 [merge] Auto-merge of patch for bug#12546938 from mysql-5.5->mysql-trunk. modified: mysql-test/r/events_bugs.result mysql-test/t/events_bugs.test sql/event_db_repository.cc sql/event_db_repository.h sql/events.cc === modified file 'mysql-test/r/events_bugs.result' --- a/mysql-test/r/events_bugs.result 2011-03-28 15:38:16 +0000 +++ b/mysql-test/r/events_bugs.result 2011-05-27 10:31:48 +0000 @@ -535,6 +535,7 @@ DROP EVENT e3; DROP EVENT e2; DROP EVENT e1; SET TIME_ZONE=@save_time_zone; +SET TIMESTAMP=DEFAULT; drop event if exists new_event; CREATE EVENT new_event ON SCHEDULE EVERY 0 SECOND DO SELECT 1; ERROR HY000: INTERVAL is either not positive or too big @@ -756,6 +757,45 @@ SHOW EVENTS; Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation DROP DATABASE event_test1; DROP DATABASE event_test12; +# +# Bug#12546938 (formerly known as bug#61005): +# CREATE IF NOT EXIST EVENT WILL CREATE MULTIPLE RUNNING EVENTS +# +USE events_test; +SET GLOBAL event_scheduler = ON; +DROP TABLE IF EXISTS table_bug12546938; +DROP EVENT IF EXISTS event_Bug12546938; +CREATE TABLE table_bug12546938 (i INT); +# Create an event which will be executed with a small delay +# and won't be automatically dropped after that. +CREATE EVENT event_Bug12546938 +ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 SECOND ON COMPLETION PRESERVE +ENABLE DO +BEGIN +INSERT INTO table_bug12546938 VALUES(1); +END +| +# Now try to create the same event using CREATE EVENT IF NOT EXISTS. +# A warning should be emitted. A new event should not be created nor +# the old event should be re-executed. +CREATE EVENT IF NOT EXISTS event_bug12546938 +ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 SECOND ON COMPLETION PRESERVE +ENABLE DO +BEGIN +INSERT INTO table_bug12546938 VALUES (1); +END +| +Warnings: +Note 1537 Event 'event_bug12546938' already exists +# Wait until at least one instance of event is executed. +# Check that only one instance of our event was executed. +SELECT COUNT(*) FROM table_bug12546938; +COUNT(*) +1 +# Clean-up. +DROP EVENT IF EXISTS event_Bug12546938; +DROP TABLE table_bug12546938; +SET GLOBAL EVENT_SCHEDULER = OFF; DROP DATABASE events_test; SET GLOBAL event_scheduler= 'ON'; SET @@global.concurrent_insert= @concurrent_insert; === modified file 'mysql-test/t/events_bugs.test' --- a/mysql-test/t/events_bugs.test 2011-03-28 15:38:16 +0000 +++ b/mysql-test/t/events_bugs.test 2011-05-27 10:31:48 +0000 @@ -857,6 +857,7 @@ DROP EVENT e2; DROP EVENT e1; SET TIME_ZONE=@save_time_zone; +SET TIMESTAMP=DEFAULT; # # START - BUG#28666 CREATE EVENT ... EVERY 0 SECOND let server crash @@ -1235,6 +1236,55 @@ SHOW EVENTS; DROP DATABASE event_test1; DROP DATABASE event_test12; +--echo # +--echo # Bug#12546938 (formerly known as bug#61005): +--echo # CREATE IF NOT EXIST EVENT WILL CREATE MULTIPLE RUNNING EVENTS +--echo # +USE events_test; +SET GLOBAL event_scheduler = ON; + +--disable_warnings +DROP TABLE IF EXISTS table_bug12546938; +DROP EVENT IF EXISTS event_Bug12546938; +--enable_warnings +CREATE TABLE table_bug12546938 (i INT); + +delimiter |; + +--echo # Create an event which will be executed with a small delay +--echo # and won't be automatically dropped after that. +CREATE EVENT event_Bug12546938 +ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 SECOND ON COMPLETION PRESERVE +ENABLE DO +BEGIN + INSERT INTO table_bug12546938 VALUES(1); +END +| + +--echo # Now try to create the same event using CREATE EVENT IF NOT EXISTS. +--echo # A warning should be emitted. A new event should not be created nor +--echo # the old event should be re-executed. +CREATE EVENT IF NOT EXISTS event_bug12546938 +ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 SECOND ON COMPLETION PRESERVE +ENABLE DO +BEGIN + INSERT INTO table_bug12546938 VALUES (1); +END +| + +delimiter ;| + +--echo # Wait until at least one instance of event is executed. +let $wait_condition= SELECT COUNT(*) FROM table_bug12546938; +--source include/wait_condition.inc + +--echo # Check that only one instance of our event was executed. +SELECT COUNT(*) FROM table_bug12546938; + +--echo # Clean-up. +DROP EVENT IF EXISTS event_Bug12546938; +DROP TABLE table_bug12546938; +SET GLOBAL EVENT_SCHEDULER = OFF; ########################################################################### # === modified file 'sql/event_db_repository.cc' --- a/sql/event_db_repository.cc 2011-05-04 13:49:13 +0000 +++ b/sql/event_db_repository.cc 2011-05-27 10:36:24 +0000 @@ -621,18 +621,21 @@ Event_db_repository::open_event_table(TH only creates a record on disk. @pre The thread handle has no open tables. - @param[in,out] thd THD - @param[in] parse_data Parsed event definition - @param[in] create_if_not TRUE if IF NOT EXISTS clause was provided - to CREATE EVENT statement - + @param[in,out] thd THD + @param[in] parse_data Parsed event definition + @param[in] create_if_not TRUE if IF NOT EXISTS clause was provided + to CREATE EVENT statement + @param[out] event_already_exists When method is completed successfully + set to true if event already exists else + set to false @retval FALSE success @retval TRUE error */ bool Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data, - my_bool create_if_not) + bool create_if_not, + bool *event_already_exists) { int ret= 1; TABLE *table= NULL; @@ -664,6 +667,7 @@ Event_db_repository::create_event(THD *t { if (create_if_not) { + *event_already_exists= true; push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_EVENT_ALREADY_EXISTS, ER(ER_EVENT_ALREADY_EXISTS), parse_data->name.str); @@ -671,8 +675,10 @@ Event_db_repository::create_event(THD *t } else my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), parse_data->name.str); + goto end; - } + } else + *event_already_exists= false; DBUG_PRINT("info", ("non-existent, go forward")); === modified file 'sql/event_db_repository.h' --- a/sql/event_db_repository.h 2010-11-18 16:34:56 +0000 +++ b/sql/event_db_repository.h 2011-05-27 10:36:24 +0000 @@ -73,7 +73,8 @@ public: Event_db_repository(){} bool - create_event(THD *thd, Event_parse_data *parse_data, my_bool create_if_not); + create_event(THD *thd, Event_parse_data *parse_data, bool create_if_not, + bool *event_already_exists); bool update_event(THD *thd, Event_parse_data *parse_data, LEX_STRING *new_dbname, === modified file 'sql/events.cc' --- a/sql/events.cc 2011-05-21 08:25:33 +0000 +++ b/sql/events.cc 2011-05-27 10:36:24 +0000 @@ -284,6 +284,7 @@ create_query_string(THD *thd, String *bu return 0; } + /** Create a new event. @@ -304,8 +305,8 @@ bool Events::create_event(THD *thd, Event_parse_data *parse_data, bool if_not_exists) { - int ret; - bool save_binlog_row_based; + bool ret; + bool save_binlog_row_based, event_already_exists; DBUG_ENTER("Events::create_event"); if (check_if_system_tables_error()) @@ -345,28 +346,32 @@ Events::create_event(THD *thd, Event_par DBUG_RETURN(TRUE); /* 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, if_not_exists, + &event_already_exists))) { Event_queue_element *new_element; bool dropped= 0; - if (!(new_element= new Event_queue_element())) - ret= TRUE; // OOM - else if ((ret= db_repository->load_named_event(thd, parse_data->dbname, - parse_data->name, - new_element))) + if (!event_already_exists) { - if (!db_repository->drop_event(thd, parse_data->dbname, parse_data->name, - TRUE)) - dropped= 1; - delete new_element; - } - else - { - /* TODO: do not ignore the out parameter and a possible OOM error! */ - bool created; - if (event_queue) - event_queue->create_event(thd, new_element, &created); + if (!(new_element= new Event_queue_element())) + ret= TRUE; // OOM + else if ((ret= db_repository->load_named_event(thd, parse_data->dbname, + parse_data->name, + new_element))) + { + if (!db_repository->drop_event(thd, parse_data->dbname, parse_data->name, + TRUE)) + dropped= 1; + delete new_element; + } + else + { + /* TODO: do not ignore the out parameter and a possible OOM error! */ + bool created; + if (event_queue) + event_queue->create_event(thd, new_element, &created); + } } /* binlog the create event unless it's been successfully dropped @@ -380,14 +385,14 @@ Events::create_event(THD *thd, Event_par { sql_print_error("Event Error: An error occurred while creating query string, " "before writing it into binary log."); - ret= TRUE; + ret= true; } else - { - /* If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER - will be written into the binary log as the definer for the SQL thread. */ + /* + If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER + will be written into the binary log as the definer for the SQL thread. + */ ret= write_bin_log(thd, TRUE, log_query.c_ptr(), log_query.length()); - } } } /* Restore the state of binlog format */ --===============7172727522613085362== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/dmitry.shulga@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: dmitry.shulga@stripped\ # 8pykcce6836i82uw # target_branch: file:///Users/shulga/projects/mysql/mysql-trunk/ # testament_sha1: dd53e8e213db3427637f3d1be8529ef0e7392d67 # timestamp: 2011-05-27 17:37:01 +0700 # source_branch: file:///Users/shulga/projects/mysql/mysql-5.5/ # base_revision_id: tatjana.nuernberg@stripped\ # 9dsjc3mr69nx97r8 # # Begin bundle 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 Liof/i7kinChISZ1RYo= --===============7172727522613085362==--