diff --git a/mysql-test/r/events.result b/mysql-test/r/events.result index e115e077535..f95953cdc86 100644 --- a/mysql-test/r/events.result +++ b/mysql-test/r/events.result @@ -85,13 +85,25 @@ SHOW EVENTS; Db Name Definer Type Execute at Interval value Interval field Starts Ends Status events_test event_starts_test root@localhost RECURRING NULL 20 SECOND # # ENABLED DROP EVENT event_starts_test; +create table test_nested(a int); create event e_43 on schedule every 1 second do set @a = 5; set global event_scheduler = 1; alter event e_43 do alter event e_43 do set @a = 4; +ERROR HY000: Recursivity of EVENT DDL statements is forbidden when body is present +alter event e_43 do +begin +alter event e_43 on schedule every 5 minute; +insert into test_nested values(1); +end| +set global event_scheduler = 1; 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 +events_test e_43 begin +alter event e_43 on schedule every 5 minute; +insert into test_nested values(1); +end ENABLED MINUTE 5 drop event e_43; +drop table test_nested; "Let's check whether we can use non-qualified names" create table non_qualif(a int); create event non_qualif_ev on schedule every 10 minute do insert into non_qualif values (800219); @@ -358,7 +370,7 @@ root localhost events_test Connect User lock select get_lock("test_lock2_1", 20) drop event закачка21; create table t_16 (s1 int); create trigger t_16_bi before insert on t_16 for each row create event e_16 on schedule every 1 second do set @a=5; -ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +ERROR HY000: Recursivity of EVENT DDL statements is forbidden when body is present drop table t_16; create event white_space on schedule every 10 hour diff --git a/mysql-test/r/events_bugs.result b/mysql-test/r/events_bugs.result index a7c2964a253..e1f8551c2fd 100644 --- a/mysql-test/r/events_bugs.result +++ b/mysql-test/r/events_bugs.result @@ -17,18 +17,7 @@ DROP EVENT ДОЛЕН_регистър_утф8; SET NAMES latin1; set @a=3; CREATE PROCEDURE p_16 () CREATE EVENT e_16 ON SCHEDULE EVERY @a SECOND DO SET @a=5; -call p_16(); -"Here we used to crash!" -call p_16(); -ERROR HY000: Event 'e_16' already exists -call p_16(); -ERROR HY000: Event 'e_16' already exists -DROP EVENT e_16; -CALL p_16(); -CALL p_16(); -ERROR HY000: Event 'e_16' already exists -DROP PROCEDURE p_16; -DROP EVENT e_16; +ERROR HY000: Recursivity of EVENT DDL statements is forbidden when body is present create event e_55 on schedule at 99990101000000 do drop table t; ERROR HY000: Incorrect AT value: '99990101000000' create event e_55 on schedule every 10 hour starts 99990101000000 do drop table t; diff --git a/mysql-test/t/events.test b/mysql-test/t/events.test index aac13a55dd3..1940016a7a1 100644 --- a/mysql-test/t/events.test +++ b/mysql-test/t/events.test @@ -81,14 +81,23 @@ SHOW EVENTS; DROP EVENT event_starts_test; # # +create table test_nested(a int); create event e_43 on schedule every 1 second do set @a = 5; set global event_scheduler = 1; ---sleep 2 +--error 1562 alter event e_43 do alter event e_43 do set @a = 4; ---sleep 2 +delimiter |; +alter event e_43 do +begin + alter event e_43 on schedule every 5 minute; + insert into test_nested values(1); +end| +delimiter ;| +set global event_scheduler = 1; +--sleep 1 select db, name, body, status, interval_field, interval_value from mysql.event; drop event e_43; ---sleep 1 +drop table test_nested; --echo "Let's check whether we can use non-qualified names" create table non_qualif(a int); @@ -315,7 +324,7 @@ drop event закачка21; # Bug #16410 Events: CREATE EVENT is legal in a CREATE TRIGGER statement # create table t_16 (s1 int); ---error 1422 +--error 1562 create trigger t_16_bi before insert on t_16 for each row create event e_16 on schedule every 1 second do set @a=5; drop table t_16; # diff --git a/mysql-test/t/events_bugs.test b/mysql-test/t/events_bugs.test index 9434de7be7d..e07707e7734 100644 --- a/mysql-test/t/events_bugs.test +++ b/mysql-test/t/events_bugs.test @@ -30,19 +30,8 @@ SET NAMES latin1; # START - BUG#16408: Events: crash for an event in a procedure # set @a=3; +--error 1562 CREATE PROCEDURE p_16 () CREATE EVENT e_16 ON SCHEDULE EVERY @a SECOND DO SET @a=5; -call p_16(); ---echo "Here we used to crash!" ---error ER_EVENT_ALREADY_EXISTS -call p_16(); ---error ER_EVENT_ALREADY_EXISTS -call p_16(); -DROP EVENT e_16; -CALL p_16(); ---error ER_EVENT_ALREADY_EXISTS -CALL p_16(); -DROP PROCEDURE p_16; -DROP EVENT e_16; # # END - BUG#16408: Events: crash for an event in a procedure # diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 476bc2f2f02..ac4f2dd9237 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5839,3 +5839,6 @@ ER_CANT_ACTIVATE_LOG eng "Cannot activate '%-.64s' log." ER_RBR_NOT_AVAILABLE eng "The server was not built with row-based replication" +ER_EVENT_RECURSIVITY_FORBIDDEN + eng "Recursivity of EVENT DDL statements is forbidden when body is present" + diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 4dfabbf0c27..23201a81f88 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -880,7 +880,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa load_data opt_field_or_var_spec fields_or_vars opt_load_data_set_spec definer view_replace_or_algorithm view_replace view_algorithm_opt - view_algorithm view_or_trigger_or_sp view_or_trigger_or_sp_tail + view_algorithm view_or_trigger_or_sp_or_event + view_or_trigger_or_sp_or_event_tail view_suid view_tail view_list_opt view_list view_select view_check_option trigger_tail sp_tail install uninstall partition_entry binlog_base64_event @@ -1257,78 +1258,13 @@ create: lex->name=$4.str; lex->create_info.options=$3; } - | CREATE EVENT_SYM opt_if_not_exists sp_name - /* - BE CAREFUL when you add a new rule to update the block where - YYTHD->client_capabilities is set back to original value - */ - { - LEX *lex=Lex; - - if (lex->et) - { - /* - Recursive events are not possible because recursive SPs - are not also possible. lex->sp_head is not stacked. - */ - // ToDo Andrey : Change the error message - my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "EVENT"); - YYABORT; - } - - lex->create_info.options= $3; - - if (!(lex->et= new(YYTHD->mem_root) Event_timed())) // implicitly calls Event_timed::init() - YYABORT; - if (!(lex->event_parse_data= Event_parse_data::new_instance(YYTHD))) - YYABORT; - - /* - We have to turn of CLIENT_MULTI_QUERIES while parsing a - stored procedure, otherwise yylex will chop it into pieces - at each ';'. - */ - $$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; - YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES); - - - lex->event_parse_data->identifier= $4; - - 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 - opt_ev_status - opt_ev_comment - DO_SYM ev_sql_stmt - { - /* - Restore flag if it was cleared above - $1 - CREATE - $2 - EVENT_SYM - $3 - opt_if_not_exists - $4 - sp_name - $5 - the block above - */ - YYTHD->client_capabilities |= $5; - - /* - sql_command is set here because some rules in ev_sql_stmt - can overwrite it - */ - Lex->sql_command= SQLCOM_CREATE_EVENT; - } | CREATE { Lex->create_view_mode= VIEW_CREATE_NEW; Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; Lex->create_view_suid= TRUE; } - view_or_trigger_or_sp + view_or_trigger_or_sp_or_event {} | CREATE USER clear_privileges grant_list { @@ -1347,6 +1283,72 @@ create: ; +event_tail: + EVENT_SYM opt_if_not_exists sp_name + /* + BE CAREFUL when you add a new rule to update the block where + YYTHD->client_capabilities is set back to original value + */ + { + LEX *lex=Lex; + + if (lex->et) + { + /* + Recursive CREATE EVENT statement are not possible because + recursive SPs are not also possible. lex->sp_head is not stacked. + */ + my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "EVENT"); + YYABORT; + } + + lex->create_info.options= $2; + + if (!(lex->et= new(YYTHD->mem_root) Event_timed())) // implicitly calls Event_timed::init() + YYABORT; + if (!(lex->event_parse_data= Event_parse_data::new_instance(YYTHD))) + YYABORT; + + /* + We have to turn of CLIENT_MULTI_QUERIES while parsing a + stored procedure, otherwise yylex will chop it into pieces + at each ';'. + */ + $$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; + YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES); + + + lex->event_parse_data->identifier= $3; + + if (!lex->et_compile_phase) + { + lex->et->init_name(YYTHD, $3); + lex->et->init_definer(YYTHD); + } + } + ON SCHEDULE_SYM ev_schedule_time + opt_ev_on_completion + opt_ev_status + opt_ev_comment + DO_SYM ev_sql_stmt + { + /* + Restore flag if it was cleared above + $1 - EVENT_SYM + $2 - opt_if_not_exists + $3 - sp_name + $4 - the block above + */ + YYTHD->client_capabilities |= $4; + + /* + sql_command is set here because some rules in ev_sql_stmt + can overwrite it + */ + Lex->sql_command= SQLCOM_CREATE_EVENT; + } + + ev_schedule_time: EVERY_SYM expr interval { Lex->event_parse_data->item_expression= $2; @@ -1517,25 +1519,41 @@ ev_sql_stmt: LEX *lex= Lex; sp_head *sp; - $$= lex->sphead; - - if (!lex->sphead) + /* + This stops the following : + - CREATE EVENT ... DO CREATE EVENT ...; + - ALTER EVENT ... DO CREATE EVENT ...; + - CREATE EVENT ... DO ALTER EVENT DO ....; + - CREATE PROCEDURE ... BEGIN CREATE EVENT ... END| + This allows: + - CREATE EVENT ... DO DROP EVENT yyy; + - CREATE EVENT ... DO ALTER EVENT yyy; + (the nested ALTER EVENT can have anything but DO clause) + - ALTER EVENT ... DO ALTER EVENT yyy; + (the nested ALTER EVENT can have anything but DO clause) + - ALTER EVENT ... DO DROP EVENT yyy; + - CREATE PROCEDURE ... BEGIN ALTER EVENT ... END| + (the nested ALTER EVENT can have anything but DO clause) + - CREATE PROCEDURE ... BEGIN DROP EVENT ... END| + */ + if (lex->sphead) { - if (!(sp= new sp_head())) - YYABORT; - - sp->reset_thd_mem_root(YYTHD); - sp->init(lex); - - sp->m_type= TYPE_ENUM_PROCEDURE; - - lex->sphead= sp; - - bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); - lex->sphead->m_chistics= &lex->sp_chistics; - - lex->sphead->m_body_begin= lex->ptr; + my_error(ER_EVENT_RECURSIVITY_FORBIDDEN, MYF(0)); + YYABORT; } + + if (!(lex->sphead= new sp_head())) + YYABORT; + + lex->sphead->reset_thd_mem_root(YYTHD); + lex->sphead->init(lex); + + lex->sphead->m_type= TYPE_ENUM_PROCEDURE; + + bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); + lex->sphead->m_chistics= &lex->sp_chistics; + + lex->sphead->m_body_begin= lex->ptr; Lex->event_parse_data->body_begin= lex->ptr; @@ -1546,18 +1564,15 @@ ev_sql_stmt: { LEX *lex=Lex; - if (!$1) - { - sp_head *sp= lex->sphead; - // return back to the original memory root ASAP - sp->init_strings(YYTHD, lex, NULL); - sp->restore_thd_mem_root(YYTHD); + // return back to the original memory root ASAP + lex->sphead->init_strings(YYTHD, lex, NULL); + lex->sphead->restore_thd_mem_root(YYTHD); - lex->sp_chistics.suid= SP_IS_SUID;//always the definer! + lex->sp_chistics.suid= SP_IS_SUID;//always the definer! + + lex->et->sphead= lex->sphead; + lex->sphead= NULL; - lex->et->sphead= lex->sphead; - lex->sphead= NULL; - } Lex->event_parse_data->init_body(YYTHD); if (!lex->et_compile_phase) { @@ -4738,16 +4753,7 @@ alter: LEX *lex=Lex; Event_timed *et; - if (lex->et) - { - /* - Recursive events are not possible because recursive SPs - are not also possible. lex->sp_head is not stacked. - */ - my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "EVENT"); - YYABORT; - } - lex->spname= 0;//defensive programming + lex->spname= NULL; if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD))) YYABORT; @@ -10767,20 +10773,22 @@ subselect_end: **************************************************************************/ -view_or_trigger_or_sp: - definer view_or_trigger_or_sp_tail +view_or_trigger_or_sp_or_event: + definer view_or_trigger_or_sp_or_event_tail {} | view_replace_or_algorithm definer view_tail {} ; -view_or_trigger_or_sp_tail: +view_or_trigger_or_sp_or_event_tail: view_tail {} | trigger_tail {} | sp_tail {} + | event_tail + {} ; /**************************************************************************