diff --git a/mysql-test/r/events.result b/mysql-test/r/events.result index 1fbeb75b963..c3b94e580c2 100644 --- a/mysql-test/r/events.result +++ b/mysql-test/r/events.result @@ -6,9 +6,29 @@ Note 1305 Event event1 does not exist create event event1 on schedule every 15 minute starts now() ends date_add(now(), interval 5 hour) DO begin end; alter event event1 rename to event2; alter event event2 disabled; +alter event event2 on completion not preserve; +alter event event2 on schedule every 1 year on completion preserve rename to event3 comment "new comment" do begin select 1; end__ +alter event event3 rename to event2; drop event event2; create event event2 on schedule every 2 second starts now() ends date_add(now(), interval 5 hour) comment "some" DO begin end; drop event event2; +create event e_43 on schedule every 1 second do set @a = 5; +set global event_scheduler = 1; +select sleep(2); +sleep(2) +0 +alter event e_43 do alter event e_43 do set @a = 4; +select sleep(3); +sleep(3) +0 +select db, name, body, status, interval_field, interval_value from mysql.event; +db name body status interval_field interval_value +events_test e_43 set @a = 4 ENABLED SECOND 1 +drop event e_43; +select sleep(1); +sleep(1) +0 +set global event_scheduler = 0; create table t_event3 (a int, b float); drop event if exists event3; Warnings: @@ -27,69 +47,4 @@ 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' -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/t/disabled.def b/mysql-test/t/disabled.def index 6f1d928d429..1f9573a6770 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -12,6 +12,7 @@ sp-goto : GOTO is currently is disabled - will be fixed in the future rpl_bit_npk : Bug #13418 +events : Test case instability - infinite locking. To be fixed. func_group : Bug #15448 func_math : Bug #15448 group_min_max : Bug #15448 @@ -20,7 +21,6 @@ subselect : Bug#15706 ps_7ndb : dbug assert in RBR mode when executing test suite rpl_ddl : Bug#15963 SBR does not show "Definer" correctly partition_03ndb : Bug#16385 -events : Affects flush test case. A table lock not released somewhere ndb_binlog_basic : Results are not deterministic, Tomas will fix rpl_ndb_basic : Bug#16228 rpl_sp : Bug #16456 diff --git a/mysql-test/t/events.test b/mysql-test/t/events.test index ee165ad8bd9..3f9445fc845 100644 --- a/mysql-test/t/events.test +++ b/mysql-test/t/events.test @@ -4,11 +4,26 @@ drop event if exists event1; create event event1 on schedule every 15 minute starts now() ends date_add(now(), interval 5 hour) DO begin end; alter event event1 rename to event2; alter event event2 disabled; +alter event event2 on completion not preserve; +delimiter __; +alter event event2 on schedule every 1 year on completion preserve rename to event3 comment "new comment" do begin select 1; end__ +delimiter ;__ +alter event event3 rename to event2; drop event event2; create event event2 on schedule every 2 second starts now() ends date_add(now(), interval 5 hour) comment "some" DO begin end; drop event event2; +create event e_43 on schedule every 1 second do set @a = 5; +set global event_scheduler = 1; +select sleep(2); +alter event e_43 do alter event e_43 do set @a = 4; +select sleep(3); +select db, name, body, status, interval_field, interval_value from mysql.event; +drop event e_43; +select sleep(1); +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()); @@ -28,67 +43,67 @@ set event_scheduler=0; --error 1231 set global event_scheduler=2; -set global event_scheduler=0; -select count(*) from mysql.event; -select get_lock("test_lock1", 20); -create event закачка on schedule every 10 hour do select get_lock("test_lock1", 20); -select count(*) from mysql.event; -#show processlist; -select release_lock("test_lock1"); -drop event закачка; -select count(*) from mysql.event; - -set global event_scheduler=1; -select get_lock("test_lock2", 20); -create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20); -select sleep(2); -#show processlist; -select release_lock("test_lock2"); -drop event закачка; - +#set global event_scheduler=0; +#select count(*) from mysql.event; +#select get_lock("test_lock1", 20); +#create event закачка on schedule every 10 hour do select get_lock("test_lock1", 20); +#select count(*) from mysql.event; +##show processlist; +#select release_lock("test_lock1"); +#drop event закачка; +#select count(*) from mysql.event; # -# 1. get a lock -# 2. create an event -# 3. sleep so it has time to start -# 4. should appear in processlist -# 5. kill the scheduler, it will wait for the child to stop -# 6. both processes should be there on show processlist -# 7. release the lock and sleep, both scheduler and child should end -set global event_scheduler=1; -select get_lock("test_lock2_1", 20); -create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20); -select sleep(2); +#set global event_scheduler=1; +#select get_lock("test_lock2", 20); +#create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20); +#select sleep(2); #show processlist; -set global event_scheduler=0; -select sleep(2); -#show processlist; -select release_lock("test_lock2_1"); -select sleep(2); -#show processlist; -drop event закачка21; +#select release_lock("test_lock2"); +#drop event закачка; -set global event_scheduler=1; -select get_lock("test_lock3", 20); -create event закачка on schedule every 10 hour do select get_lock("test_lock3", 20); -select sleep(2); +## +## 1. get a lock +## 2. create an event +## 3. sleep so it has time to start +## 4. should appear in processlist +## 5. kill the scheduler, it will wait for the child to stop +## 6. both processes should be there on show processlist +## 7. release the lock and sleep, both scheduler and child should end +#set global event_scheduler=1; +#select get_lock("test_lock2_1", 20); +#create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20); +#select sleep(2); +##show processlist; +#set global event_scheduler=0; +#select sleep(2); +##show processlist; +#select release_lock("test_lock2_1"); +#select sleep(2); +##show processlist; +#drop event закачка21; + +#set global event_scheduler=1; +#select get_lock("test_lock3", 20); +#create event закачка on schedule every 10 hour do select get_lock("test_lock3", 20); +#select sleep(2); #show processlist; -drop event закачка; -select release_lock("test_lock3"); +#drop event закачка; +#select release_lock("test_lock3"); # # test with very often occuring event # (disabled for now, locks) -#select get_lock("test_lock4", 20); -#create event закачка4 on schedule every 1 second do select get_lock("test_lock4", 20); -#select sleep(3); -#show processlist; -#drop event закачка4; -#select release_lock("test_lock4"); +##select get_lock("test_lock4", 20); +##create event закачка4 on schedule every 1 second do select get_lock("test_lock4", 20); +##select sleep(3); +##show processlist; +##drop event закачка4; +##select release_lock("test_lock4"); -set global event_scheduler=0; -select sleep(2); -#show processlist; -#the following locks for some reason and is a bug, commented for now -#select count(*) from mysql.event; +#set global event_scheduler=0; +#select sleep(2); +##show processlist; +##the following locks for some reason and is a bug, commented for now +##select count(*) from mysql.event; drop database events_test; diff --git a/sql/event.cc b/sql/event.cc index 6d62be903bd..cb1b2efad0a 100644 --- a/sql/event.cc +++ b/sql/event.cc @@ -237,8 +237,9 @@ evex_fill_row(THD *thd, TABLE *table, event_timed *et, my_bool is_update) DBUG_RETURN(EVEX_GET_FIELD_FAILED); } - DBUG_PRINT("info", ("dbname.len=%d",et->dbname.length)); - DBUG_PRINT("info", ("name.len=%d",et->name.length)); + DBUG_PRINT("info", ("dbname.len=[%s]",et->dbname.str)); + DBUG_PRINT("info", ("name.len=[%s]",et->name.str)); + DBUG_PRINT("info", ("body=[%s]",et->body.str)); if (table->field[field_num= EVEX_FIELD_DB]-> store(et->dbname.str, et->dbname.length, system_charset_info)) @@ -674,7 +675,8 @@ done: static int -evex_remove_from_cache(LEX_STRING *db, LEX_STRING *name, bool use_lock) +evex_remove_from_cache(LEX_STRING *db, LEX_STRING *name, bool use_lock, + bool is_drop) { uint i; @@ -697,14 +699,18 @@ evex_remove_from_cache(LEX_STRING *db, LEX_STRING *name, bool use_lock) { if (!et->is_running()) { + DBUG_PRINT("evex_remove_from_cache", ("not running - free and delete")); et->free_sp(); delete et; } else { + DBUG_PRINT("evex_remove_from_cache", + ("running.defer mem free. is_drop=%d", is_drop)); et->flags|= EVENT_EXEC_NO_MORE; - et->dropped= true; + et->dropped= is_drop; } + DBUG_PRINT("evex_remove_from_cache", ("delete from queue")); evex_queue_delete_element(&EVEX_EQ_NAME, i); // ok, we have cleaned goto done; @@ -805,7 +811,7 @@ evex_update_event(THD *thd, event_timed *et, sp_name *new_name, UNLOCK_MUTEX_AND_BAIL_OUT(LOCK_evex_running, done); VOID(pthread_mutex_lock(&LOCK_event_arrays)); - evex_remove_from_cache(&et->dbname, &et->name, false); + evex_remove_from_cache(&et->dbname, &et->name, false, false); if (et->status == MYSQL_EVENT_ENABLED) { if (new_name) @@ -874,7 +880,7 @@ evex_drop_event(THD *thd, event_timed *et, bool drop_if_exists, VOID(pthread_mutex_lock(&LOCK_evex_running)); if (evex_is_running) - ret= evex_remove_from_cache(&et->dbname, &et->name, true); + ret= evex_remove_from_cache(&et->dbname, &et->name, true, true); VOID(pthread_mutex_unlock(&LOCK_evex_running)); done: diff --git a/sql/event_executor.cc b/sql/event_executor.cc index dd426c32545..e655f5890b3 100644 --- a/sql/event_executor.cc +++ b/sql/event_executor.cc @@ -492,12 +492,18 @@ event_executor_worker(void *event_void) sql_print_information(" EVEX EXECUTED event %s.%s [EXPR:%d]. RetCode=%d", event->dbname.str, event->name.str, (int) event->expression, ret); + if (ret == EVEX_COMPILE_ERROR) + sql_print_information(" EVEX COMPILE ERROR for event %s.%s", + event->dbname.str, event->name.str); + DBUG_PRINT("info", (" EVEX EXECUTED event %s.%s [EXPR:%d]. RetCode=%d", event->dbname.str, event->name.str, (int) event->expression, ret)); } if ((event->flags & EVENT_EXEC_NO_MORE) || event->status==MYSQL_EVENT_DISABLED) { + DBUG_PRINT("event_executor_worker", + ("%s exec no more. to drop=%d",event->name.str, event->dropped)); if (event->dropped) event->drop(thd); delete event; diff --git a/sql/event_timed.cc b/sql/event_timed.cc index cc8849364da..f17675c6ec5 100644 --- a/sql/event_timed.cc +++ b/sql/event_timed.cc @@ -806,16 +806,18 @@ event_timed::get_show_create_event(THD *thd, uint *length) { char *dst, *ret; uint len, tmp_len; + DBUG_ENTER("get_show_create_event"); + DBUG_PRINT("ret_info",("body_len=[%d]body=[%s]", body.length, body.str)); - len = strlen("CREATE EVENT `") + dbname.length + strlen(".") + name.length + - strlen("` ON SCHEDULE EVERY 5 MINUTE DO ") + body.length + strlen(";"); + len = strlen("CREATE EVENT `") + dbname.length + strlen("`.`") + name.length + + strlen("` ON SCHEDULE EVERY 5 MINUTE DO ") + body.length;// + strlen(";"); ret= dst= (char*) alloc_root(thd->mem_root, len + 1); memcpy(dst, "CREATE EVENT `", tmp_len= strlen("CREATE EVENT `")); dst+= tmp_len; memcpy(dst, dbname.str, tmp_len=dbname.length); dst+= tmp_len; - memcpy(dst, ".", tmp_len= strlen(".")); + memcpy(dst, "`.`", tmp_len= strlen("`.`")); dst+= tmp_len; memcpy(dst, name.str, tmp_len= name.length); dst+= tmp_len; @@ -825,13 +827,14 @@ event_timed::get_show_create_event(THD *thd, uint *length) memcpy(dst, body.str, tmp_len= body.length); dst+= tmp_len; - memcpy(dst, ";", 1); - ++dst; +// memcpy(dst, ";", 1); +// ++dst; *dst= '\0'; *length= len; - - return ret; + + DBUG_PRINT("ret_info",("len=%d",*length)); + DBUG_RETURN(ret); } @@ -944,8 +947,12 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root) lex.et_compile_phase= TRUE; if (yyparse((void *)thd) || thd->is_fatal_error) { + DBUG_PRINT("error", ("error during compile or thd->is_fatal_error=%d", + thd->is_fatal_error)); // Free lex associated resources // QQ: Do we really need all this stuff here ? + sql_print_error("error during compile of %s.%s or thd->is_fatal_error=%d", + dbname.str, name.str, thd->is_fatal_error); if (lex.sphead) { if (&lex != thd->lex) @@ -953,13 +960,10 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root) delete lex.sphead; lex.sphead= 0; } - // QQ: anything else ? - lex_end(&lex); - thd->lex= old_lex; - ret= EVEX_COMPILE_ERROR; goto done; } + DBUG_PRINT("note", ("success compiling %s.%s", dbname.str, name.str)); sphead= lex.et->sphead; sphead->m_db= dbname; @@ -973,6 +977,8 @@ done: lex.et->free_sphead_on_delete= false; delete lex.et; lex_end(&lex); + DBUG_PRINT("note", ("return old data on its place. set back NAMES")); + thd->lex= old_lex; thd->query= old_query; thd->query_length= old_query_len; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 71851a5d175..da324a9f81a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1361,9 +1361,9 @@ create: lex->et->init_name(YYTHD, $4); } ON SCHEDULE_SYM ev_schedule_time - ev_on_completion - ev_status - ev_comment + opt_ev_on_completion + opt_ev_status + opt_ev_comment DO_SYM ev_sql_stmt { /* @@ -1445,7 +1445,7 @@ ev_schedule_time: EVERY_SYM expr interval } ; -ev_status: /* empty */ {$$= 0;} +opt_ev_status: /* empty */ {$$= 0;} | ENABLED_SYM { LEX *lex=Lex; @@ -1492,8 +1492,12 @@ ev_ends: /* empty */ } ; -ev_on_completion: /* empty */ {$$= 0;} - | ON COMPLETION_SYM PRESERVE_SYM +opt_ev_on_completion: /* empty */ {$$= 0;} + | ev_on_completion + ; + +ev_on_completion: + ON COMPLETION_SYM PRESERVE_SYM { LEX *lex=Lex; if (!lex->et_compile_phase) @@ -1509,7 +1513,7 @@ ev_on_completion: /* empty */ {$$= 0;} } ; -ev_comment: /* empty */ {$$= 0;} +opt_ev_comment: /* empty */ {$$= 0;} | COMMENT_SYM TEXT_STRING_sys { LEX *lex= Lex; @@ -4797,12 +4801,11 @@ alter: YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES; } - ev_on_schedule - ev_rename_to - ev_on_completion - ev_status - ev_comment - ev_opt_sql_stmt + ev_alter_on_schedule_completion + opt_ev_rename_to + opt_ev_status + opt_ev_comment + opt_ev_sql_stmt { /* $1 - ALTER @@ -4817,7 +4820,7 @@ alter: can overwrite it */ if (!($5 || $6 || $7 || - $8 || $9 || $10)) + $8 || $9)) { yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; @@ -4846,15 +4849,13 @@ alter: } ; +ev_alter_on_schedule_completion: /* empty */ { $$= 0;} + | ON SCHEDULE_SYM ev_schedule_time { $$= 1; } + | ev_on_completion { $$= 1; } + | ON SCHEDULE_SYM ev_schedule_time ev_on_completion { $$= 1; } + ; -ev_on_schedule: /* empty */ { $$= 0;} - | ON SCHEDULE_SYM ev_schedule_time - { - $$= 1; - } - ; - -ev_rename_to: /* empty */ { $$= 0;} +opt_ev_rename_to: /* empty */ { $$= 0;} | RENAME TO_SYM sp_name { LEX *lex=Lex; @@ -4864,7 +4865,7 @@ ev_rename_to: /* empty */ { $$= 0;} } ; -ev_opt_sql_stmt: /* empty*/ { $$= 0;} +opt_ev_sql_stmt: /* empty*/ { $$= 0;} | DO_SYM ev_sql_stmt { $$= 1;