diff options
-rw-r--r-- | mysql-test/r/events.result | 4 | ||||
-rw-r--r-- | mysql-test/t/events.test | 4 | ||||
-rw-r--r-- | sql/event_data_objects.cc | 551 | ||||
-rw-r--r-- | sql/event_data_objects.h | 63 | ||||
-rw-r--r-- | sql/event_db_repository.cc | 381 | ||||
-rw-r--r-- | sql/event_db_repository.h | 15 | ||||
-rw-r--r-- | sql/event_scheduler.cc | 78 | ||||
-rw-r--r-- | sql/event_scheduler.h | 11 | ||||
-rw-r--r-- | sql/events.cc | 32 | ||||
-rw-r--r-- | sql/events.h | 10 | ||||
-rw-r--r-- | sql/sql_lex.cc | 4 | ||||
-rw-r--r-- | sql/sql_lex.h | 3 | ||||
-rw-r--r-- | sql/sql_parse.cc | 88 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 151 |
14 files changed, 569 insertions, 826 deletions
diff --git a/mysql-test/r/events.result b/mysql-test/r/events.result index f95953cdc86..473acbd5984 100644 --- a/mysql-test/r/events.result +++ b/mysql-test/r/events.result @@ -297,9 +297,9 @@ select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_comp db name body definer convert_tz(execute_at, 'UTC', 'SYSTEM') on_completion events_test e_26 set @a = 5 root@localhost 2017-01-01 00:00:00 DROP drop event e_26; -create event e_26 on schedule at NULL disabled do set @a = 5; +create event e_26 on schedule at NULL disable do set @a = 5; ERROR HY000: Incorrect AT value: 'NULL' -create event e_26 on schedule at 'definitely not a datetime' disabled do set @a = 5; +create event e_26 on schedule at 'definitely not a datetime' disable do set @a = 5; ERROR HY000: Incorrect AT value: 'definitely not a datetime' set names utf8; create event задачка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1; diff --git a/mysql-test/t/events.test b/mysql-test/t/events.test index 1940016a7a1..5dff48c203b 100644 --- a/mysql-test/t/events.test +++ b/mysql-test/t/events.test @@ -255,9 +255,9 @@ create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5; select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event; drop event e_26; --error ER_WRONG_VALUE -create event e_26 on schedule at NULL disabled do set @a = 5; +create event e_26 on schedule at NULL disable do set @a = 5; --error ER_WRONG_VALUE -create event e_26 on schedule at 'definitely not a datetime' disabled do set @a = 5; +create event e_26 on schedule at 'definitely not a datetime' disable do set @a = 5; set names utf8; create event задачка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1; diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index 228f1a4ff4a..a47a3e9e936 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -35,186 +35,18 @@ Event_parse_data::new_instance(THD *thd) Event_parse_data::Event_parse_data() { item_execute_at= item_expression= item_starts= item_ends= NULL; -} - - -/* - Set body of the event - what should be executed. - - SYNOPSIS - Event_timed::init_body() - thd THD - - NOTE - The body is extracted by copying all data between the - start of the body set by another method and the current pointer in Lex. - - Some questionable removal of characters is done in here, and that part - should be refactored when the parser is smarter. -*/ - -void -Event_parse_data::init_body(THD *thd) -{ - DBUG_ENTER("Event_parse_data::init_body"); - DBUG_PRINT("info", ("body=[%s] body_begin=0x%ld end=0x%ld", body_begin, - body_begin, thd->lex->ptr)); - - body.length= thd->lex->ptr - body_begin; - const uchar *body_end= body_begin + body.length - 1; - - /* Trim nuls or close-comments ('*'+'/') or spaces at the end */ - while (body_begin < body_end) - { - - if ((*body_end == '\0') || - (my_isspace(thd->variables.character_set_client, *body_end))) - { /* consume NULs and meaningless whitespace */ - --body.length; - --body_end; - continue; - } - - /* - consume closing comments - - This is arguably wrong, but it's the best we have until the parser is - changed to be smarter. FIXME PARSER - - See also the sp_head code, where something like this is done also. - - One idea is to keep in the lexer structure the count of the number of - open-comments we've entered, and scan left-to-right looking for a - closing comment IFF the count is greater than zero. - - Another idea is to remove the closing comment-characters wholly in the - parser, since that's where it "removes" the opening characters. - */ - if ((*(body_end - 1) == '*') && (*body_end == '/')) - { - DBUG_PRINT("info", ("consumend one '*" "/' comment in the query '%s'", - body_begin)); - body.length-= 2; - body_end-= 2; - continue; - } - - break; /* none were found, so we have excised all we can. */ - } - - /* the first is always whitespace which I cannot skip in the parser */ - while (my_isspace(thd->variables.character_set_client, *body_begin)) - { - ++body_begin; - --body.length; - } - body.str= thd->strmake((char *)body_begin, body.length); - - DBUG_VOID_RETURN; -} - - -/* - Constructor - - SYNOPSIS - Event_timed::Event_timed() -*/ - -Event_timed::Event_timed():in_spawned_thread(0),locked_by_thread_id(0), - running(0), thread_id(0), status_changed(false), - last_executed_changed(false), expression(0), - created(0), modified(0), - on_completion(Event_timed::ON_COMPLETION_DROP), - status(Event_timed::ENABLED), sphead(0), - sql_mode(0), body_begin(0), dropped(false), - free_sphead_on_delete(true), flags(0) - -{ - pthread_mutex_init(&this->LOCK_running, MY_MUTEX_INIT_FAST); - pthread_cond_init(&this->COND_finished, NULL); - init(); -} - - -/* - Destructor - - SYNOPSIS - Event_timed::~Event_timed() -*/ - -Event_timed::~Event_timed() -{ - deinit_mutexes(); - - if (free_sphead_on_delete) - free_sp(); -} - - -/* - Destructor - - SYNOPSIS - Event_timed::~deinit_mutexes() -*/ - -void -Event_timed::deinit_mutexes() -{ - pthread_mutex_destroy(&this->LOCK_running); - pthread_cond_destroy(&this->COND_finished); -} - - -/* - Checks whether the event is running - - SYNOPSIS - Event_timed::is_running() -*/ - -bool -Event_timed::is_running() -{ - bool ret; - - VOID(pthread_mutex_lock(&this->LOCK_running)); - ret= running; - VOID(pthread_mutex_unlock(&this->LOCK_running)); - - return ret; -} - - -/* - Init all member variables - - SYNOPSIS - Event_timed::init() -*/ - -void -Event_timed::init() -{ - DBUG_ENTER("Event_timed::init"); - - dbname.str= name.str= body.str= comment.str= 0; - dbname.length= name.length= body.length= comment.length= 0; + status= ENABLED; + on_completion= ON_COMPLETION_DROP; + expression= 0; + /* Actually in the parser STARTS is always set */ set_zero_time(&starts, MYSQL_TIMESTAMP_DATETIME); set_zero_time(&ends, MYSQL_TIMESTAMP_DATETIME); set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME); - set_zero_time(&last_executed, MYSQL_TIMESTAMP_DATETIME); starts_null= ends_null= execute_at_null= TRUE; - definer_user.str= definer_host.str= 0; - definer_user.length= definer_host.length= 0; - - sql_mode= 0; - - DBUG_VOID_RETURN; + body.str= comment.str= 0; + body.length= comment.length= 0; } @@ -222,37 +54,25 @@ Event_timed::init() Set a name of the event SYNOPSIS - Event_timed::init_name() + Event_parse_data::init_name() thd THD spn the name extracted in the parser */ void -Event_timed::init_name(THD *thd, sp_name *spn) +Event_parse_data::init_name(THD *thd, sp_name *spn) { - DBUG_ENTER("Event_timed::init_name"); - /* During parsing, we must use thd->mem_root */ - MEM_ROOT *root= thd->mem_root; + DBUG_ENTER("Event_parse_data::init_name"); /* We have to copy strings to get them into the right memroot */ - if (spn) - { - dbname.length= spn->m_db.length; - if (spn->m_db.length == 0) - dbname.str= NULL; - else - dbname.str= strmake_root(root, spn->m_db.str, spn->m_db.length); - name.length= spn->m_name.length; - name.str= strmake_root(root, spn->m_name.str, spn->m_name.length); - - if (spn->m_qname.length == 0) - spn->init_qname(thd); - } - else if (thd->db) - { - dbname.length= thd->db_length; - dbname.str= strmake_root(root, thd->db, dbname.length); - } + DBUG_ASSERT(spn); + dbname.length= spn->m_db.length; + if (spn->m_db.length == 0) + dbname.str= NULL; + else + dbname.str= thd->strmake(spn->m_db.str, spn->m_db.length); + name.length= spn->m_name.length; + name.str= thd->strmake(spn->m_name.str, spn->m_name.length); DBUG_PRINT("dbname", ("len=%d db=%s",dbname.length, dbname.str)); DBUG_PRINT("name", ("len=%d name=%s",name.length, name.str)); @@ -265,7 +85,7 @@ Event_timed::init_name(THD *thd, sp_name *spn) Set body of the event - what should be executed. SYNOPSIS - Event_timed::init_body() + Event_parse_data::init_body() thd THD NOTE @@ -277,9 +97,9 @@ Event_timed::init_name(THD *thd, sp_name *spn) */ void -Event_timed::init_body(THD *thd) +Event_parse_data::init_body(THD *thd) { - DBUG_ENTER("Event_timed::init_body"); + DBUG_ENTER("Event_parse_data::init_body"); DBUG_PRINT("info", ("body=[%s] body_begin=0x%ld end=0x%ld", body_begin, body_begin, thd->lex->ptr)); @@ -331,17 +151,60 @@ Event_timed::init_body(THD *thd) ++body_begin; --body.length; } - body.str= strmake_root(thd->mem_root, (char *)body_begin, body.length); + body.str= thd->strmake((char *)body_begin, body.length); DBUG_VOID_RETURN; } /* + Inits definer (definer_user and definer_host) during parsing. + + SYNOPSIS + Event_parse_data::init_definer() + + RETURN VALUE + 0 OK +*/ + +int +Event_parse_data::init_definer(THD *thd) +{ + int definer_user_len; + int definer_host_len; + DBUG_ENTER("Event_parse_data::init_definer"); + + DBUG_PRINT("info",("init definer_user thd->mem_root=0x%lx " + "thd->sec_ctx->priv_user=0x%lx", thd->mem_root, + thd->security_ctx->priv_user)); + + definer_user_len= strlen(thd->security_ctx->priv_user); + definer_host_len= strlen(thd->security_ctx->priv_host); + + /* + 1 for @ */ + DBUG_PRINT("info",("init definer as whole")); + definer.length= definer_user_len + definer_host_len + 1; + definer.str= thd->alloc(definer.length + 1); + + DBUG_PRINT("info",("copy the user")); + memcpy(definer.str, thd->security_ctx->priv_user, definer_user_len); + definer.str[definer_user_len]= '@'; + + DBUG_PRINT("info",("copy the host")); + memcpy(definer.str + definer_user_len + 1, thd->security_ctx->priv_host, + definer_host_len); + definer.str[definer.length]= '\0'; + DBUG_PRINT("info",("definer [%s] initted", definer.str)); + + DBUG_RETURN(0); +} + + +/* Set time for execution for one time events. SYNOPSIS - Event_timed::init_execute_at() + Event_parse_data::init_execute_at() expr when (datetime) RETURN VALUE @@ -352,14 +215,14 @@ Event_timed::init_body(THD *thd) */ int -Event_timed::init_execute_at(THD *thd, Item *expr) +Event_parse_data::init_execute_at(THD *thd, Item *expr) { my_bool not_used; TIME ltime; my_time_t t; TIME time_tmp; - DBUG_ENTER("Event_timed::init_execute_at"); + DBUG_ENTER("Event_parse_data::init_execute_at"); if (expr->fix_fields(thd, &expr)) DBUG_RETURN(EVEX_PARSE_ERROR); @@ -368,7 +231,7 @@ Event_timed::init_execute_at(THD *thd, Item *expr) DBUG_PRINT("info", ("starts_null && ends_null should be 1 is %d", (starts_null && ends_null))); DBUG_ASSERT(starts_null && ends_null); - + /* let's check whether time is in the past */ thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, (my_time_t) thd->query_start()); @@ -403,7 +266,7 @@ Event_timed::init_execute_at(THD *thd, Item *expr) Set time for execution for transient events. SYNOPSIS - Event_timed::init_interval() + Event_parse_data::init_interval() expr how much? new_interval what is the interval @@ -415,12 +278,12 @@ Event_timed::init_execute_at(THD *thd, Item *expr) */ int -Event_timed::init_interval(THD *thd, Item *expr, interval_type new_interval) +Event_parse_data::init_interval(THD *thd, Item *expr, interval_type new_interval) { String value; INTERVAL interval_tmp; - DBUG_ENTER("Event_timed::init_interval"); + DBUG_ENTER("Event_parse_data::init_interval"); if (expr->fix_fields(thd, &expr)) DBUG_RETURN(EVEX_PARSE_ERROR); @@ -504,9 +367,9 @@ Event_timed::init_interval(THD *thd, Item *expr, interval_type new_interval) Set activation time. SYNOPSIS - Event_timed::init_starts() - expr how much? - interval what is the interval + Event_parse_data::init_starts() + expr how much? + interval what is the interval NOTES Note that activation time is not execution time. @@ -523,13 +386,13 @@ Event_timed::init_interval(THD *thd, Item *expr, interval_type new_interval) */ int -Event_timed::init_starts(THD *thd, Item *new_starts) +Event_parse_data::init_starts(THD *thd, Item *new_starts) { my_bool not_used; TIME ltime, time_tmp; my_time_t t; - DBUG_ENTER("Event_timed::init_starts"); + DBUG_ENTER("Event_parse_data::init_starts"); if (new_starts->fix_fields(thd, &new_starts)) DBUG_RETURN(EVEX_PARSE_ERROR); @@ -570,7 +433,7 @@ Event_timed::init_starts(THD *thd, Item *new_starts) Set deactivation time. SYNOPSIS - Event_timed::init_ends() + Event_parse_data::init_ends() thd THD new_ends when? @@ -590,13 +453,13 @@ Event_timed::init_starts(THD *thd, Item *new_starts) */ int -Event_timed::init_ends(THD *thd, Item *new_ends) +Event_parse_data::init_ends(THD *thd, Item *new_ends) { TIME ltime, ltime_now; my_bool not_used; my_time_t t; - DBUG_ENTER("Event_timed::init_ends"); + DBUG_ENTER("Event_parse_data::init_ends"); if (new_ends->fix_fields(thd, &new_ends)) DBUG_RETURN(EVEX_PARSE_ERROR); @@ -641,67 +504,106 @@ Event_timed::init_ends(THD *thd, Item *new_ends) /* - Sets comment. + Constructor SYNOPSIS - Event_timed::init_comment() - thd THD - used for memory allocation - comment the string. + Event_timed::Event_timed() */ -void -Event_timed::init_comment(THD *thd, LEX_STRING *set_comment) +Event_timed::Event_timed():in_spawned_thread(0),locked_by_thread_id(0), + running(0), thread_id(0), status_changed(false), + last_executed_changed(false), expression(0), + created(0), modified(0), + on_completion(Event_timed::ON_COMPLETION_DROP), + status(Event_timed::ENABLED), sphead(0), + sql_mode(0), dropped(false), + free_sphead_on_delete(true), flags(0) + { - DBUG_ENTER("Event_timed::init_comment"); + pthread_mutex_init(&this->LOCK_running, MY_MUTEX_INIT_FAST); + pthread_cond_init(&this->COND_finished, NULL); + init(); +} - comment.str= strmake_root(thd->mem_root, set_comment->str, - comment.length= set_comment->length); - DBUG_VOID_RETURN; +/* + Destructor + + SYNOPSIS + Event_timed::~Event_timed() +*/ + +Event_timed::~Event_timed() +{ + deinit_mutexes(); + + if (free_sphead_on_delete) + free_sp(); } /* - Inits definer (definer_user and definer_host) during parsing. + Destructor SYNOPSIS - Event_timed::init_definer() - - RETURN VALUE - 0 OK + Event_timed::deinit_mutexes() */ -int -Event_timed::init_definer(THD *thd) +void +Event_timed::deinit_mutexes() { - DBUG_ENTER("Event_timed::init_definer"); + pthread_mutex_destroy(&this->LOCK_running); + pthread_cond_destroy(&this->COND_finished); +} - DBUG_PRINT("info",("init definer_user thd->mem_root=0x%lx " - "thd->sec_ctx->priv_user=0x%lx", thd->mem_root, - thd->security_ctx->priv_user)); - definer_user.str= strdup_root(thd->mem_root, thd->security_ctx->priv_user); - definer_user.length= strlen(thd->security_ctx->priv_user); - DBUG_PRINT("info",("init definer_host thd->s_c->priv_host=0x%lx", - thd->security_ctx->priv_host)); - definer_host.str= strdup_root(thd->mem_root, thd->security_ctx->priv_host); - definer_host.length= strlen(thd->security_ctx->priv_host); +/* + Checks whether the event is running - DBUG_PRINT("info",("init definer as whole")); - definer.length= definer_user.length + definer_host.length + 1; - definer.str= alloc_root(thd->mem_root, definer.length + 1); + SYNOPSIS + Event_timed::is_running() +*/ - DBUG_PRINT("info",("copy the user")); - memcpy(definer.str, definer_user.str, definer_user.length); - definer.str[definer_user.length]= '@'; +bool +Event_timed::is_running() +{ + bool ret; - DBUG_PRINT("info",("copy the host")); - memcpy(definer.str + definer_user.length + 1, definer_host.str, - definer_host.length); - definer.str[definer.length]= '\0'; - DBUG_PRINT("info",("definer initted")); + VOID(pthread_mutex_lock(&this->LOCK_running)); + ret= running; + VOID(pthread_mutex_unlock(&this->LOCK_running)); - DBUG_RETURN(0); + return ret; +} + + +/* + Init all member variables + + SYNOPSIS + Event_timed::init() +*/ + +void +Event_timed::init() +{ + DBUG_ENTER("Event_timed::init"); + + dbname.str= name.str= body.str= comment.str= 0; + dbname.length= name.length= body.length= comment.length= 0; + + set_zero_time(&starts, MYSQL_TIMESTAMP_DATETIME); + set_zero_time(&ends, MYSQL_TIMESTAMP_DATETIME); + set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME); + set_zero_time(&last_executed, MYSQL_TIMESTAMP_DATETIME); + starts_null= ends_null= execute_at_null= TRUE; + + definer_user.str= definer_host.str= 0; + definer_user.length= definer_host.length= 0; + + sql_mode= 0; + + DBUG_VOID_RETURN; } @@ -739,20 +641,17 @@ Event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table) if (table->s->fields != ET_FIELD_COUNT) goto error; - if ((et->dbname.str= get_field(mem_root, - table->field[ET_FIELD_DB])) == NULL) + if ((et->dbname.str= get_field(mem_root, table->field[ET_FIELD_DB])) == NULL) goto error; et->dbname.length= strlen(et->dbname.str); - if ((et->name.str= get_field(mem_root, - table->field[ET_FIELD_NAME])) == NULL) + if ((et->name.str= get_field(mem_root, table->field[ET_FIELD_NAME])) == NULL) goto error; et->name.length= strlen(et->name.str); - if ((et->body.str= get_field(mem_root, - table->field[ET_FIELD_BODY])) == NULL) + if ((et->body.str= get_field(mem_root, table->field[ET_FIELD_BODY])) == NULL) goto error; et->body.length= strlen(et->body.str); @@ -837,7 +736,6 @@ Event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table) et->comment.length= strlen(et->comment.str); else et->comment.length= 0; - et->sql_mode= (ulong) table->field[ET_FIELD_SQL_MODE]->val_int(); @@ -858,7 +756,7 @@ error: time_now current time i_value quantity of time type interval to add i_type type of interval to add (SECOND, MINUTE, HOUR, WEEK ...) - + RETURN VALUE 0 OK 1 Error @@ -1639,7 +1537,6 @@ Event_timed::compile(THD *thd, MEM_ROOT *mem_root) &security_ctx, &save_ctx); thd->lex= &lex; lex_start(thd, (uchar*)thd->query, thd->query_length); - lex.et_compile_phase= TRUE; if (MYSQLparse((void *)thd) || thd->is_fatal_error) { DBUG_PRINT("error", ("error during compile or thd->is_fatal_error=%d", @@ -1662,7 +1559,7 @@ Event_timed::compile(THD *thd, MEM_ROOT *mem_root) } DBUG_PRINT("note", ("success compiling %s.%s", dbname.str, name.str)); - sphead= lex.et->sphead; + sphead= lex.sphead; sphead->m_db= dbname; sphead->set_definer(definer.str, definer.length); @@ -1670,8 +1567,6 @@ Event_timed::compile(THD *thd, MEM_ROOT *mem_root) sphead->optimize(); ret= 0; done: - lex.et->free_sphead_on_delete= false; - lex.et->deinit_mutexes(); lex_end(&lex); thd->restore_security_context(save_ctx); @@ -1709,7 +1604,7 @@ extern pthread_attr_t connection_attrib; int Event_timed::spawn_now(void * (*thread_func)(void*), void *arg) -{ +{ THD *thd= current_thd; int ret= EVENT_EXEC_STARTED; DBUG_ENTER("Event_timed::spawn_now"); @@ -1875,7 +1770,6 @@ event_timed_db_equal(Event_timed *et, LEX_STRING *db) } - /* Checks whether two events are equal by identifiers @@ -1888,121 +1782,8 @@ event_timed_db_equal(Event_timed *et, LEX_STRING *db) */ bool -event_timed_identifier_equal(Event_timed *a, Event_timed *b) +event_timed_identifier_equal(LEX_STRING db, LEX_STRING name, Event_timed *b) { - return event_timed_name_equal(a, &b->name) && - event_timed_db_equal(a, &b->dbname); -} - - -/* - Checks whether two events have the same name - - SYNOPSIS - event_timed_name_equal() - - RETURN VALUE - TRUE names are equal - FALSE names are not equal -*/ - -bool -event_timed_name_equal(sp_name *name, LEX_STRING *event_name) -{ - return !sortcmp_lex_string(name->m_name, *event_name, system_charset_info); -} - - -/* - Checks whether two events are in the same schema - - SYNOPSIS - event_timed_db_equal() - - RETURN VALUE - TRUE schemas are equal - FALSE schemas are not equal -*/ - -bool -event_timed_db_equal(sp_name *name, LEX_STRING *db) -{ - return !sortcmp_lex_string(name->m_db, *db, system_charset_info); -} - - -/* - Checks whether two events are equal by identifiers - - SYNOPSIS - event_timed_identifier_equal() - - RETURN VALUE - TRUE equal - FALSE not equal -*/ - -bool -event_timed_identifier_equal(sp_name *a, Event_timed *b) -{ - return event_timed_name_equal(a, &b->name) && - event_timed_db_equal(a, &b->dbname); -} - - -/* - Switches the security context - SYNOPSIS - change_security_context() - thd Thread - user The user - host The host of the user - db The schema for which the security_ctx will be loaded - s_ctx Security context to load state into - backup Where to store the old context - - RETURN VALUE - 0 - OK - 1 - Error (generates error too) -*/ - -bool -change_security_context(THD *thd, LEX_STRING user, LEX_STRING host, - LEX_STRING db, Security_context *s_ctx, - Security_context **backup) -{ - DBUG_ENTER("change_security_context"); - DBUG_PRINT("info",("%s@%s@%s", user.str, host.str, db.str)); -#ifndef NO_EMBEDDED_ACCESS_CHECKS - s_ctx->init(); - *backup= 0; - if (acl_getroot_no_password(s_ctx, user.str, host.str, host.str, db.str)) - { - my_error(ER_NO_SUCH_USER, MYF(0), user.str, host.str); - DBUG_RETURN(TRUE); - } - *backup= thd->security_ctx; - thd->security_ctx= s_ctx; -#endif - DBUG_RETURN(FALSE); -} - - -/* - Restores the security context - SYNOPSIS - restore_security_context() - thd - thread - backup - switch to this context -*/ - -void -restore_security_context(THD *thd, Security_context *backup) -{ - DBUG_ENTER("restore_security_context"); -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (backup) - thd->security_ctx= backup; -#endif - DBUG_VOID_RETURN; + return !sortcmp_lex_string(name, b->name, system_charset_info) && + !sortcmp_lex_string(db, b->dbname, system_charset_info); } diff --git a/sql/event_data_objects.h b/sql/event_data_objects.h index ff547cebd5b..d8df8dd1e6c 100644 --- a/sql/event_data_objects.h +++ b/sql/event_data_objects.h @@ -54,19 +54,9 @@ class Event_timed; bool event_timed_db_equal(Event_timed *et, LEX_STRING *db); - -/* Compares the whole identifier*/ -bool -event_timed_identifier_equal(Event_timed *a, Event_timed *b); - -/* Compares only the schema part of the identifier */ -bool -event_timed_db_equal(sp_name *name, LEX_STRING *db); - - /* Compares the whole identifier*/ bool -event_timed_identifier_equal(sp_name *a, Event_timed *b); +event_timed_identifier_equal(LEX_STRING db, LEX_STRING name, Event_timed *b); class Event_timed @@ -123,7 +113,6 @@ public: enum enum_status status; sp_head *sphead; ulong sql_mode; - const uchar *body_begin; bool dropped; bool free_sphead_on_delete; @@ -138,9 +127,6 @@ public: DBUG_RETURN(p); } - static void *operator new(size_t size, MEM_ROOT *mem_root) - { return (void*) alloc_root(mem_root, (uint) size); } - static void operator delete(void *ptr, size_t size) { DBUG_ENTER("Event_timed::delete(ptr,size)"); @@ -150,17 +136,6 @@ public: DBUG_VOID_RETURN; } - static void operator delete(void *ptr, MEM_ROOT *mem_root) - { - /* - Don't free the memory it will be done by the mem_root but - we need to call the destructor because we free other resources - which are not allocated on the root but on the heap, or we - deinit mutexes. - */ - DBUG_ASSERT(0); - } - Event_timed(); ~Event_timed(); @@ -172,30 +147,6 @@ public: deinit_mutexes(); int - init_definer(THD *thd); - - int - init_execute_at(THD *thd, Item *expr); - - int - init_interval(THD *thd, Item *expr, interval_type new_interval); - - void - init_name(THD *thd, sp_name *spn); - - int - init_starts(THD *thd, Item *starts); - - int - init_ends(THD *thd, Item *ends); - - void - init_body(THD *thd); - - void - init_comment(THD *thd, LEX_STRING *set_comment); - - int load_from_row(MEM_ROOT *mem_root, TABLE *table); bool @@ -231,9 +182,6 @@ public: void free_sp(); - bool - has_equal_db(Event_timed *etn); - int kill_thread(THD *thd); @@ -268,12 +216,9 @@ public: LEX_STRING dbname; LEX_STRING name; LEX_STRING body; - - LEX_STRING definer_user; - LEX_STRING definer_host; LEX_STRING definer;// combination of user and host - LEX_STRING comment; + Item* item_starts; Item* item_ends; Item* item_execute_at; @@ -316,10 +261,6 @@ public: void init_body(THD *thd); - - void - init_comment(THD *thd, LEX_STRING *set_comment); - }; diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index fc771b6bac3..68d8234cc90 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -34,7 +34,7 @@ TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] = { {(char *) STRING_WITH_LEN("db")}, {(char *) STRING_WITH_LEN("char(64)")}, {(char *) STRING_WITH_LEN("utf8")} - }, + }, { {(char *) STRING_WITH_LEN("name")}, {(char *) STRING_WITH_LEN("char(64)")}, @@ -44,7 +44,7 @@ TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] = { {(char *) STRING_WITH_LEN("body")}, {(char *) STRING_WITH_LEN("longblob")}, {NULL, 0} - }, + }, { {(char *) STRING_WITH_LEN("definer")}, {(char *) STRING_WITH_LEN("char(77)")}, @@ -54,7 +54,7 @@ TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] = { {(char *) STRING_WITH_LEN("execute_at")}, {(char *) STRING_WITH_LEN("datetime")}, {NULL, 0} - }, + }, { {(char *) STRING_WITH_LEN("interval_value")}, {(char *) STRING_WITH_LEN("int(11)")}, @@ -68,7 +68,7 @@ TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] = { "'DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND'," "'SECOND_MICROSECOND')")}, {NULL, 0} - }, + }, { {(char *) STRING_WITH_LEN("created")}, {(char *) STRING_WITH_LEN("timestamp")}, @@ -78,7 +78,7 @@ TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] = { {(char *) STRING_WITH_LEN("modified")}, {(char *) STRING_WITH_LEN("timestamp")}, {NULL, 0} - }, + }, { {(char *) STRING_WITH_LEN("last_executed")}, {(char *) STRING_WITH_LEN("datetime")}, @@ -88,7 +88,7 @@ TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] = { {(char *) STRING_WITH_LEN("starts")}, {(char *) STRING_WITH_LEN("datetime")}, {NULL, 0} - }, + }, { {(char *) STRING_WITH_LEN("ends")}, {(char *) STRING_WITH_LEN("datetime")}, @@ -98,7 +98,7 @@ TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] = { {(char *) STRING_WITH_LEN("status")}, {(char *) STRING_WITH_LEN("enum('ENABLED','DISABLED')")}, {NULL, 0} - }, + }, { {(char *) STRING_WITH_LEN("on_completion")}, {(char *) STRING_WITH_LEN("enum('DROP','PRESERVE')")}, @@ -206,6 +206,133 @@ evex_fill_row(THD *thd, TABLE *table, Event_timed *et, my_bool is_update) table->field[ET_FIELD_STARTS]->set_notnull(); table->field[ET_FIELD_STARTS]-> store_time(&et->starts, MYSQL_TIMESTAMP_DATETIME); + } + + if (!et->ends_null) + { + table->field[ET_FIELD_ENDS]->set_notnull(); + table->field[ET_FIELD_ENDS]-> + store_time(&et->ends, MYSQL_TIMESTAMP_DATETIME); + } + } + else if (et->execute_at.year) + { + table->field[ET_FIELD_INTERVAL_EXPR]->set_null(); + table->field[ET_FIELD_TRANSIENT_INTERVAL]->set_null(); + table->field[ET_FIELD_STARTS]->set_null(); + table->field[ET_FIELD_ENDS]->set_null(); + + table->field[ET_FIELD_EXECUTE_AT]->set_notnull(); + table->field[ET_FIELD_EXECUTE_AT]-> + store_time(&et->execute_at, MYSQL_TIMESTAMP_DATETIME); + } + else + { + DBUG_ASSERT(is_update); + /* + it is normal to be here when the action is update + this is an error if the action is create. something is borked + */ + } + + ((Field_timestamp *)table->field[ET_FIELD_MODIFIED])->set_time(); + + if (et->comment.str) + { + if (table->field[field_num= ET_FIELD_COMMENT]-> + store(et->comment.str, et->comment.length, scs)) + goto err_truncate; + } + + DBUG_RETURN(0); +err_truncate: + my_error(ER_EVENT_DATA_TOO_LONG, MYF(0), table->field[field_num]->field_name); + DBUG_RETURN(EVEX_GENERAL_ERROR); +} + + +/* + Puts some data common to CREATE and ALTER EVENT into a row. + + SYNOPSIS + evex_fill_row() + thd THD + table the row to fill out + et Event's data + + RETURN VALUE + 0 - OK + EVEX_GENERAL_ERROR - bad data + EVEX_GET_FIELD_FAILED - field count does not match. table corrupted? + + DESCRIPTION + Used both when an event is created and when it is altered. +*/ + +static int +evex_fill_row(THD *thd, TABLE *table, Event_parse_data *et, my_bool is_update) +{ + CHARSET_INFO *scs= system_charset_info; + enum enum_events_table_field field_num; + + DBUG_ENTER("evex_fill_row"); + + DBUG_PRINT("info", ("dbname=[%s]", et->dbname.str)); + DBUG_PRINT("info", ("name =[%s]", et->name.str)); + DBUG_PRINT("info", ("body =[%s]", et->body.str)); + + if (table->field[field_num= ET_FIELD_DEFINER]-> + store(et->definer.str, et->definer.length, scs)) + goto err_truncate; + + if (table->field[field_num= ET_FIELD_DB]-> + store(et->dbname.str, et->dbname.length, scs)) + goto err_truncate; + + if (table->field[field_num= ET_FIELD_NAME]-> + store(et->name.str, et->name.length, scs)) + goto err_truncate; + + /* both ON_COMPLETION and STATUS are NOT NULL thus not calling set_notnull()*/ + table->field[ET_FIELD_ON_COMPLETION]-> + store((longlong)et->on_completion, true); + + table->field[ET_FIELD_STATUS]->store((longlong)et->status, true); + + /* + Change the SQL_MODE only if body was present in an ALTER EVENT and of course + always during CREATE EVENT. + */ + if (et->body.str) + { + table->field[ET_FIELD_SQL_MODE]-> + store((longlong)thd->variables.sql_mode, true); + + if (table->field[field_num= ET_FIELD_BODY]-> + store(et->body.str, et->body.length, scs)) + goto err_truncate; + } + + if (et->expression) + { + table->field[ET_FIELD_INTERVAL_EXPR]->set_notnull(); + table->field[ET_FIELD_INTERVAL_EXPR]->store((longlong)et->expression, true); + + table->field[ET_FIELD_TRANSIENT_INTERVAL]->set_notnull(); + /* + In the enum (C) intervals start from 0 but in mysql enum valid values start + from 1. Thus +1 offset is needed! + */ + table->field[ET_FIELD_TRANSIENT_INTERVAL]-> + store((longlong)et->interval+1, true); + + table->field[ET_FIELD_EXECUTE_AT]->set_null(); + + if (!et->starts_null) + { + table->field[ET_FIELD_STARTS]->set_notnull(); + table->field[ET_FIELD_STARTS]-> + store_time(&et->starts, MYSQL_TIMESTAMP_DATETIME); } if (!et->ends_null) @@ -462,14 +589,15 @@ Event_db_repository::fill_schema_events(THD *thd, TABLE_LIST *tables, char *db) */ int -Event_db_repository::find_event(THD *thd, sp_name *name, Event_timed **ett, +Event_db_repository::find_event(THD *thd, LEX_STRING dbname, LEX_STRING name, + Event_timed **ett, TABLE *tbl, MEM_ROOT *root) { TABLE *table; int ret; Event_timed *et= NULL; DBUG_ENTER("db_find_event"); - DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str)); + DBUG_PRINT("enter", ("name: %*s", name.length, name.str)); if (tbl) table= tbl; @@ -480,22 +608,22 @@ Event_db_repository::find_event(THD *thd, sp_name *name, Event_timed **ett, goto done; } - if ((ret= evex_db_find_event_by_name(thd, name->m_db, name->m_name, table))) + if ((ret= evex_db_find_event_by_name(thd, dbname, name, table))) { - my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name->m_name.str); - goto done; + my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str); + goto done; } et= new Event_timed; - + /* - 1)The table should not be closed beforehand. ::load_from_row() only loads + 1)The table should not be closed beforehand. ::load_from_row() only loads and does not compile 2)::load_from_row() is silent on error therefore we emit error msg here */ if ((ret= et->load_from_row(root, table))) { - my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0)); + my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), "event"); goto done; } @@ -557,7 +685,7 @@ Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type, if (simple_open_n_lock_tables(thd, &tables)) DBUG_RETURN(1); - + if (table_check_intact(tables.table, ET_FIELD_COUNT, event_table_fields, &mysql_event_last_create_time, @@ -573,6 +701,118 @@ Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type, /* + Checks parameters which we got from the parsing phase. + + SYNOPSIS + evex_check_params() + thd THD + et event's data + + RETURNS + 0 OK + EVEX_BAD_PARAMS Error + + REMARKS + Issues error messages +*/ + +int +evex_check_params(THD *thd, Event_parse_data *parse_data) +{ + const char *pos= NULL; + Item *bad_item; + + DBUG_ENTER("evex_check_timing_params"); + DBUG_PRINT("info", ("execute_at=0x%d expr=0x%d starts=0x%d ends=0x%d", + parse_data->item_execute_at, + parse_data->item_expression, + parse_data->item_starts, + parse_data->item_ends)); + + parse_data->init_name(thd, parse_data->identifier); + parse_data->init_definer(thd); + + if (!parse_data->dbname.str || + (thd->lex->sql_command == SQLCOM_ALTER_EVENT && thd->lex->spname && + !thd->lex->spname->m_db.str)) + { + my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); + DBUG_RETURN(EVEX_BAD_PARAMS); + } + + if (check_access(thd, EVENT_ACL, parse_data->dbname.str, 0, 0, 0, + is_schema_db(parse_data->dbname.str)) || + (thd->lex->sql_command == SQLCOM_ALTER_EVENT && thd->lex->spname && + (check_access(thd, EVENT_ACL, thd->lex->spname->m_db.str, 0, 0, 0, + is_schema_db(thd->lex->spname->m_db.str))))) + DBUG_RETURN(EVEX_BAD_PARAMS); + + if (parse_data->item_execute_at) + { + DBUG_PRINT("info", ("ONE TIME")); + if (parse_data->init_execute_at(thd, parse_data->item_execute_at)) + { + pos= "AT"; + bad_item= parse_data->item_execute_at; + goto wrong_value; + } + } + else + { + int res; + DBUG_PRINT("info", ("RECURRING")); + + if (parse_data->item_expression && + (res= parse_data->init_interval(thd, parse_data->item_expression, + parse_data->interval))) + { + switch (res) { + case EVEX_BAD_PARAMS: + my_error(ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG, MYF(0)); + break; + case EVEX_MICROSECOND_UNSUP: + my_error(ER_NOT_SUPPORTED_YET, MYF(0), "MICROSECOND"); + break; + default: + pos= "INTERVAL"; + bad_item= parse_data->item_expression; + goto wrong_value; + } + DBUG_RETURN(EVEX_BAD_PARAMS); + } + + if (parse_data->item_starts && + parse_data->init_starts(thd, parse_data->item_starts)) + { + pos= "STARTS"; + bad_item= parse_data->item_starts; + goto wrong_value; + } + + if (parse_data->item_ends && + parse_data->init_ends(thd, parse_data->item_ends)) + { + /* + despite the error name the value is + eng "ENDS is either invalid or before STARTS" + */ + my_error(ER_EVENT_ENDS_BEFORE_STARTS, MYF(0)); + DBUG_RETURN(EVEX_BAD_PARAMS); + } + } + DBUG_RETURN(0); +wrong_value: + { + char buff[120]; + String str(buff,(uint32) sizeof(buff), system_charset_info); + String *str2= bad_item->fixed? bad_item->val_str(&str):NULL; + my_error(ER_WRONG_VALUE, MYF(0), pos, str2? str2->c_ptr():"NULL"); + DBUG_RETURN(EVEX_BAD_PARAMS); + } +} + + +/* Creates an event in mysql.event SYNOPSIS @@ -592,7 +832,7 @@ Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type, */ int -Event_db_repository::create_event(THD *thd, Event_timed *et, +Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data, my_bool create_if_not, uint *rows_affected) { int ret= 0; @@ -601,7 +841,6 @@ Event_db_repository::create_event(THD *thd, Event_timed *et, char olddb[128]; bool dbchanged= false; DBUG_ENTER("Event_db_repository::create_event"); - DBUG_PRINT("enter", ("name: %.*s", et->name.length, et->name.str)); *rows_affected= 0; DBUG_PRINT("info", ("open mysql.event for update")); @@ -611,22 +850,28 @@ Event_db_repository::create_event(THD *thd, Event_timed *et, goto err; } + if (evex_check_params(thd, parse_data)) + goto err; + + DBUG_PRINT("info", ("name: %.*s", parse_data->name.length, + parse_data->name.str)); + DBUG_PRINT("info", ("check existance of an event with the same name")); - if (!evex_db_find_event_by_name(thd, et->dbname, et->name, table)) + if (!evex_db_find_event_by_name(thd, parse_data->dbname, parse_data->name, table)) { if (create_if_not) { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_EVENT_ALREADY_EXISTS, ER(ER_EVENT_ALREADY_EXISTS), - et->name.str); + parse_data->name.str); goto ok; } - my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), et->name.str); + my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), parse_data->name.str); goto err; } DBUG_PRINT("info", ("non-existant, go forward")); - if ((ret= sp_use_new_db(thd, et->dbname.str,olddb, sizeof(olddb),0, + if ((ret= sp_use_new_db(thd, parse_data->dbname.str, olddb, sizeof(olddb), 0, &dbchanged))) { my_error(ER_BAD_DB_ERROR, MYF(0)); @@ -635,28 +880,30 @@ Event_db_repository::create_event(THD *thd, Event_timed *et, restore_record(table, s->default_values); // Get default values for fields - if (system_charset_info->cset->numchars(system_charset_info, et->dbname.str, - et->dbname.str + et->dbname.length) - > EVEX_DB_FIELD_LEN) + if (system_charset_info->cset-> + numchars(system_charset_info, parse_data->dbname.str, + parse_data->dbname.str + + parse_data->dbname.length) > EVEX_DB_FIELD_LEN) { - my_error(ER_TOO_LONG_IDENT, MYF(0), et->dbname.str); + my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->dbname.str); goto err; } - if (system_charset_info->cset->numchars(system_charset_info, et->name.str, - et->name.str + et->name.length) - > EVEX_DB_FIELD_LEN) + if (system_charset_info->cset-> + numchars(system_charset_info, parse_data->name.str, + parse_data->name.str + + parse_data->name.length) > EVEX_DB_FIELD_LEN) { - my_error(ER_TOO_LONG_IDENT, MYF(0), et->name.str); + my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->name.str); goto err; } - if (et->body.length > table->field[ET_FIELD_BODY]->field_length) + if (parse_data->body.length > table->field[ET_FIELD_BODY]->field_length) { - my_error(ER_TOO_LONG_BODY, MYF(0), et->name.str); + my_error(ER_TOO_LONG_BODY, MYF(0), parse_data->name.str); goto err; } - if (!(et->expression) && !(et->execute_at.year)) + if (!(parse_data->expression) && !(parse_data->execute_at.year)) { DBUG_PRINT("error", ("neither expression nor execute_at are set!")); my_error(ER_EVENT_NEITHER_M_EXPR_NOR_M_AT, MYF(0)); @@ -669,12 +916,16 @@ Event_db_repository::create_event(THD *thd, Event_timed *et, evex_fill_row() calls my_error() in case of error so no need to handle it here */ - if ((ret= evex_fill_row(thd, table, et, false))) + if ((ret= evex_fill_row(thd, table, parse_data, false))) goto err; + /* Close active transaction only if We are going to modify disk */ + if (end_active_trans(thd)) + goto err; + if (table->file->ha_write_row(table->record[0])) { - my_error(ER_EVENT_STORE_FAILED, MYF(0), et->name.str, ret); + my_error(ER_EVENT_STORE_FAILED, MYF(0), parse_data->name.str, ret); goto err; } @@ -724,40 +975,44 @@ err: */ int -Event_db_repository::update_event(THD *thd, Event_timed *et, sp_name *new_name) +Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data, + sp_name *new_name) { CHARSET_INFO *scs= system_charset_info; TABLE *table; int ret= EVEX_OPEN_TABLE_FAILED; DBUG_ENTER("Event_db_repository::update_event"); - DBUG_PRINT("enter", ("dbname: %.*s", et->dbname.length, et->dbname.str)); - DBUG_PRINT("enter", ("name: %.*s", et->name.length, et->name.str)); - DBUG_PRINT("enter", ("user: %.*s", et->definer.length, et->definer.str)); - if (new_name) - DBUG_PRINT("enter", ("rename to: %.*s", new_name->m_name.length, - new_name->m_name.str)); if (open_event_table(thd, TL_WRITE, &table)) { my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0)); goto err; } - + + if (evex_check_params(thd, parse_data)) + goto err; + + DBUG_PRINT("info", ("dbname: %s", parse_data->dbname.str)); + DBUG_PRINT("info", ("name: %s", parse_data->name.str)); + DBUG_PRINT("info", ("user: %s", parse_data->definer.str)); + if (new_name) + DBUG_PRINT("info", ("rename to: %s", new_name->m_name.str)); + /* first look whether we overwrite */ if (new_name) { - if (!sortcmp_lex_string(et->name, new_name->m_name, scs) && - !sortcmp_lex_string(et->dbname, new_name->m_db, scs)) + if (!sortcmp_lex_string(parse_data->name, new_name->m_name, scs) && + !sortcmp_lex_string(parse_data->dbname, new_name->m_db, scs)) { - my_error(ER_EVENT_SAME_NAME, MYF(0), et->name.str); - goto err; + my_error(ER_EVENT_SAME_NAME, MYF(0), parse_data->name.str); + goto err; } - + if (!evex_db_find_event_by_name(thd,new_name->m_db,new_name->m_name,table)) { my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), new_name->m_name.str); goto err; - } + } } /* ...and then if there is such an event. Don't exchange the blocks @@ -765,9 +1020,10 @@ Event_db_repository::update_event(THD *thd, Event_timed *et, sp_name *new_name) overwrite the key and SE will tell us that it cannot find the already found row (copied into record[1] later */ - if (EVEX_KEY_NOT_FOUND == find_event_by_name(thd, et->dbname, et->name, table)) + if (EVEX_KEY_NOT_FOUND == find_event_by_name(thd, parse_data->dbname, + parse_data->name, table)) { - my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), et->name.str); + my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), parse_data->name.str); goto err; } @@ -780,20 +1036,24 @@ Event_db_repository::update_event(THD *thd, Event_timed *et, sp_name *new_name) evex_fill_row() calls my_error() in case of error so no need to handle it here */ - if ((ret= evex_fill_row(thd, table, et, true))) + if ((ret= evex_fill_row(thd, table, parse_data, true))) goto err; if (new_name) - { + { table->field[ET_FIELD_DB]-> store(new_name->m_db.str, new_name->m_db.length, scs); table->field[ET_FIELD_NAME]-> store(new_name->m_name.str, new_name->m_name.length, scs); } + /* Close active transaction only if We are going to modify disk */ + if (end_active_trans(thd)) + goto err; + if ((ret= table->file->ha_update_row(table->record[1], table->record[0]))) { - my_error(ER_EVENT_STORE_FAILED, MYF(0), et->name.str, ret); + my_error(ER_EVENT_STORE_FAILED, MYF(0), parse_data->name.str, ret); goto err; } @@ -845,6 +1105,10 @@ Event_db_repository::drop_event(THD *thd, LEX_STRING db, LEX_STRING name, if (!(ret= evex_db_find_event_by_name(thd, db, name, table))) { + /* Close active transaction only if We are going to modify disk */ + if ((ret= end_active_trans(thd))) + goto done; + if ((ret= table->file->ha_delete_row(table->record[0]))) my_error(ER_EVENT_CANNOT_DELETE, MYF(0)); } @@ -998,7 +1262,7 @@ Event_db_repository::drop_events_by_field(THD *thd, */ int -Event_db_repository::load_named_event(THD *thd, Event_timed *etn, +Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_timed **etn_new) { int ret= 0; @@ -1007,14 +1271,11 @@ Event_db_repository::load_named_event(THD *thd, Event_timed *etn, Open_tables_state backup; DBUG_ENTER("Event_scheduler::load_and_compile_event"); - DBUG_PRINT("enter",("thd=%p name:%*s",thd, etn->name.length, etn->name.str)); + DBUG_PRINT("enter",("thd=%p name:%*s",thd, name.length, name.str)); thd->reset_n_backup_open_tables_state(&backup); /* No need to use my_error() here because db_find_event() has done it */ - { - sp_name spn(etn->dbname, etn->name); - ret= find_event(thd, &spn, &et_loaded, NULL, &repo_root); - } + ret= find_event(thd, dbname, name, &et_loaded, NULL, &repo_root); thd->restore_backup_open_tables_state(&backup); /* In this case no memory was allocated so we don't need to clean */ if (ret) diff --git a/sql/event_db_repository.h b/sql/event_db_repository.h index 1cbee96b68f..625d5bfb993 100644 --- a/sql/event_db_repository.h +++ b/sql/event_db_repository.h @@ -53,7 +53,8 @@ events_table_scan_all(THD *thd, TABLE *schema_table, TABLE *event_table); int fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */); - +class Event_timed; +class Event_parse_data; class Event_queue_element; class Event_db_repository @@ -69,11 +70,11 @@ public: deinit_repository(); int - create_event(THD *thd, Event_timed *et, my_bool create_if_not, - uint *rows_affected); + create_event(THD *thd, Event_parse_data *parse_data, my_bool create_if_not, + uint *rows_affected); int - update_event(THD *thd, Event_timed *et, sp_name *new_name); + update_event(THD *thd, Event_parse_data *parse_data, sp_name *new_name); int drop_event(THD *thd, LEX_STRING db, LEX_STRING name, bool drop_if_exists, @@ -86,11 +87,11 @@ public: drop_user_events(THD *thd, LEX_STRING definer); int - find_event(THD *thd, sp_name *name, Event_timed **ett, TABLE *tbl, - MEM_ROOT *root); + find_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_timed **ett, + TABLE *tbl, MEM_ROOT *root); int - load_named_event(THD *thd, Event_timed *etn, Event_timed **etn_new); + load_named_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_timed **etn_new); int find_event_by_name(THD *thd, LEX_STRING db, LEX_STRING name, TABLE *table); diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index cb500de53b9..35c30e5fc5a 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -785,7 +785,7 @@ Event_scheduler::destroy() */ int -Event_scheduler::create_event(THD *thd, Event_timed *et, bool check_existence) +Event_scheduler::create_event(THD *thd, Event_parse_data *et, bool check_existence) { int res; Event_timed *et_new; @@ -799,14 +799,15 @@ Event_scheduler::create_event(THD *thd, Event_timed *et, bool check_existence) UNLOCK_SCHEDULER_DATA(); DBUG_RETURN(OP_OK); } - if (check_existence && find_event(et, FALSE)) + if (check_existence && find_event(et->dbname, et->name, FALSE)) { res= OP_ALREADY_EXISTS; goto end; } /* We need to load the event on scheduler_root */ - if (!(res= db_repository->load_named_event(thd, et, &et_new))) + if (!(res= db_repository-> + load_named_event(thd, et->dbname, et->name, &et_new))) { queue_insert_safe(&queue, (byte *) et_new); DBUG_PRINT("info", ("Sending COND_new_work")); @@ -850,7 +851,7 @@ Event_scheduler::drop_event(THD *thd, sp_name *name) DBUG_RETURN(OP_OK); } - if (!(et_old= find_event(name, TRUE))) + if (!(et_old= find_event(name->m_db, name->m_name, TRUE))) DBUG_PRINT("info", ("No such event found, probably DISABLED")); UNLOCK_SCHEDULER_DATA(); @@ -906,7 +907,7 @@ Event_scheduler::drop_event(THD *thd, sp_name *name) */ int -Event_scheduler::update_event(THD *thd, Event_timed *et, +Event_scheduler::update_event(THD *thd, Event_parse_data *et, LEX_STRING *new_schema, LEX_STRING *new_name) { @@ -931,7 +932,7 @@ Event_scheduler::update_event(THD *thd, Event_timed *et, DBUG_RETURN(OP_OK); } - if (!(et_old= find_event(et, TRUE))) + if (!(et_old= find_event(et->dbname, et->name, TRUE))) DBUG_PRINT("info", ("%s.%s not found cached, probably was DISABLED", et->dbname.str, et->name.str)); @@ -948,7 +949,8 @@ Event_scheduler::update_event(THD *thd, Event_timed *et, 1. Error occured 2. If the replace is DISABLED, we don't load it into the queue. */ - if (!(res= db_repository->load_named_event(thd, et, &et_new))) + if (!(res= db_repository-> + load_named_event(thd, et->dbname, et->name, &et_new))) { queue_insert_safe(&queue, (byte *) et_new); DBUG_PRINT("info", ("Sending COND_new_work")); @@ -1014,50 +1016,8 @@ Event_scheduler::update_event(THD *thd, Event_timed *et, SYNOPSIS Event_scheduler::find_event() - etn The event to find - comparator The function to use for comparing - remove_from_q If found whether to remove from the Q - - RETURN VALUE - NULL Not found - otherwise Address - - NOTE - The caller should do the locking also the caller is responsible for - actual signalling in case an event is removed from the queue - (signalling COND_new_work for instance). -*/ - -Event_timed * -Event_scheduler::find_event(Event_timed *etn, bool remove_from_q) -{ - uint i; - DBUG_ENTER("Event_scheduler::find_event"); - - for (i= 0; i < queue.elements; ++i) - { - Event_timed *et= (Event_timed *) queue_element(&queue, i); - DBUG_PRINT("info", ("[%s.%s]==[%s.%s]?", etn->dbname.str, etn->name.str, - et->dbname.str, et->name.str)); - if (event_timed_identifier_equal(etn, et)) - { - if (remove_from_q) - queue_remove(&queue, i); - DBUG_RETURN(et); - } - } - - DBUG_RETURN(NULL); -} - - -/* - Searches for an event in the scheduler queue - - SYNOPSIS - Event_scheduler::find_event() + db The schema of the event to find name The event to find - comparator The function to use for comparing remove_from_q If found whether to remove from the Q RETURN VALUE @@ -1071,7 +1031,7 @@ Event_scheduler::find_event(Event_timed *etn, bool remove_from_q) */ Event_timed * -Event_scheduler::find_event(sp_name *name, bool remove_from_q) +Event_scheduler::find_event(LEX_STRING db, LEX_STRING name, bool remove_from_q) { uint i; DBUG_ENTER("Event_scheduler::find_event"); @@ -1079,9 +1039,9 @@ Event_scheduler::find_event(sp_name *name, bool remove_from_q) for (i= 0; i < queue.elements; ++i) { Event_timed *et= (Event_timed *) queue_element(&queue, i); - DBUG_PRINT("info", ("[%s.%s]==[%s.%s]?", name->m_db.str, name->m_name.str, + DBUG_PRINT("info", ("[%s.%s]==[%s.%s]?", db.str, name.str, et->dbname.str, et->name.str)); - if (event_timed_identifier_equal(name, et)) + if (event_timed_identifier_equal(db, name, et)) { if (remove_from_q) queue_remove(&queue, i); @@ -1624,7 +1584,7 @@ Event_scheduler::clean_queue(THD *thd) SYNOPSIS Event_scheduler::stop_all_running_events() thd Thread - + NOTE LOCK_scheduler data must be acquired prior to call to this method */ @@ -1726,7 +1686,7 @@ Event_scheduler::stop() /* One situation to be here is if there was a start that forked a new thread but the new thread did not acquire yet LOCK_scheduler_data. - Hence, in this case return an error. + Hence, in this case return an error. */ DBUG_PRINT("info", ("manager not running but %d. doing nothing", state)); UNLOCK_SCHEDULER_DATA(); @@ -1841,7 +1801,7 @@ Event_scheduler::workers_count() } VOID(pthread_mutex_unlock(&LOCK_thread_count)); DBUG_PRINT("exit", ("%d", count)); - DBUG_RETURN(count); + DBUG_RETURN(count); } @@ -1851,7 +1811,7 @@ Event_scheduler::workers_count() SYNOPSIS Event_scheduler::check_n_suspend_if_needed() thd Thread - + RETURN VALUE FALSE Not suspended, we haven't slept TRUE We were suspended. LOCK_scheduler_data is unlocked. @@ -1936,7 +1896,7 @@ Event_scheduler::check_n_wait_for_non_empty_queue(THD *thd) if (!queue.elements) thd->enter_cond(&cond_vars[COND_new_work], &LOCK_scheduler_data, - "Empty queue, sleeping"); + "Empty queue, sleeping"); /* Wait in a loop protecting against catching spurious signals */ while (!queue.elements && state == RUNNING) @@ -2079,7 +2039,7 @@ Event_scheduler::get_state() SYNOPSIS Event_scheduler::initialized() - + RETURN VALUE FALSE Was not initialized so far TRUE Was initialized diff --git a/sql/event_scheduler.h b/sql/event_scheduler.h index bd099d10839..a274636b38b 100644 --- a/sql/event_scheduler.h +++ b/sql/event_scheduler.h @@ -57,11 +57,11 @@ public: /* Methods for queue management follow */ int - create_event(THD *thd, Event_timed *et, bool check_existence); + create_event(THD *thd, Event_parse_data *et, bool check_existence); int - update_event(THD *thd, Event_timed *et, LEX_STRING *new_schema, - LEX_STRING *new_name); + update_event(THD *thd, Event_parse_data *et, LEX_STRING *new_schema, + LEX_STRING *new_name); bool drop_event(THD *thd, sp_name *name); @@ -129,10 +129,7 @@ public: private: Event_timed * - find_event(Event_timed *etn, bool remove_from_q); - - Event_timed * - find_event(sp_name *name, bool remove_from_q); + find_event(LEX_STRING db, LEX_STRING name, bool remove_from_q); uint workers_count(); diff --git a/sql/events.cc b/sql/events.cc index 5fe5f019c87..28c57d6b493 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -186,7 +186,7 @@ common_1_lev_code: expr= tmp_expr - (tmp_expr/60)*60; /* the code after the switch will finish */ } - break; + break; case INTERVAL_DAY_SECOND: { ulonglong tmp_expr= expr; @@ -283,23 +283,19 @@ Events::open_event_table(THD *thd, enum thr_lock_type lock_type, */ int -Events::create_event(THD *thd, Event_timed *et, Event_parse_data *parse_data, - uint create_options, uint *rows_affected) +Events::create_event(THD *thd, Event_parse_data *parse_data, uint create_options, + uint *rows_affected) { int ret; - DBUG_ENTER("Events::create_event"); - DBUG_PRINT("enter", ("name: %*s options:%d", et->name.length, - et->name.str, create_options)); - if (!(ret= db_repository-> - create_event(thd, et, + create_event(thd, parse_data, create_options & HA_LEX_CREATE_IF_NOT_EXISTS, rows_affected))) { Event_scheduler *scheduler= Event_scheduler::get_instance(); if (scheduler->initialized() && - (ret= scheduler->create_event(thd, et, true))) + (ret= scheduler->create_event(thd, parse_data, true))) my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0), ret); } /* No need to close the table, it will be closed in sql_parse::do_command */ @@ -315,7 +311,7 @@ Events::create_event(THD *thd, Event_timed *et, Event_parse_data *parse_data, Events::update_event() thd THD et event's data - new_name set in case of RENAME TO. + new_name set in case of RENAME TO. RETURN VALUE 0 OK @@ -328,25 +324,23 @@ Events::create_event(THD *thd, Event_timed *et, Event_parse_data *parse_data, */ int -Events::update_event(THD *thd, Event_timed *et, Event_parse_data *parse_data, - sp_name *new_name, uint *rows_affected) +Events::update_event(THD *thd, Event_parse_data *parse_data, sp_name *new_name, + uint *rows_affected) { int ret; - DBUG_ENTER("Events::update_event"); - DBUG_PRINT("enter", ("name: %*s", et->name.length, et->name.str)); /* db_update_event() opens & closes the table to prevent crash later in the code when loading and compiling the new definition. Also on error conditions my_error() is called so no need to handle here */ - if (!(ret= db_repository->update_event(thd, et, new_name))) + if (!(ret= db_repository->update_event(thd, parse_data, new_name))) { Event_scheduler *scheduler= Event_scheduler::get_instance(); if (scheduler->initialized() && - (ret= scheduler->update_event(thd, et, - new_name? &new_name->m_db: NULL, - new_name? &new_name->m_name: NULL))) + (ret= scheduler->update_event(thd, parse_data, + new_name? &new_name->m_db: NULL, + new_name? &new_name->m_name: NULL))) my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0), ret); } DBUG_RETURN(ret); @@ -411,7 +405,7 @@ Events::show_create_event(THD *thd, sp_name *spn) DBUG_PRINT("enter", ("name: %*s", spn->m_name.length, spn->m_name.str)); thd->reset_n_backup_open_tables_state(&backup); - ret= db_repository->find_event(thd, spn, &et, NULL, thd->mem_root); + ret= db_repository->find_event(thd, spn->m_db, spn->m_name, &et, NULL, thd->mem_root); thd->restore_backup_open_tables_state(&backup); if (!ret) diff --git a/sql/events.h b/sql/events.h index 45a0db13980..1239cf58c7d 100644 --- a/sql/events.h +++ b/sql/events.h @@ -17,7 +17,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ class sp_name; -class Event_timed; class Event_parse_data; class Event_db_repository; @@ -45,7 +44,6 @@ public: Event_timed::drop() and Event_timed is fixed not do drop directly or other scheme will be found. */ - friend class Event_timed; static ulong opt_event_scheduler; static TYPELIB opt_typelib; @@ -66,12 +64,12 @@ public: get_instance(); int - create_event(THD *thd, Event_timed *et, Event_parse_data *parse_data, - uint create_options, uint *rows_affected); + create_event(THD *thd, Event_parse_data *parse_data, uint create_options, + uint *rows_affected); int - update_event(THD *thd, Event_timed *et, Event_parse_data *parse_data, - sp_name *new_name, uint *rows_affected); + update_event(THD *thd, Event_parse_data *parse_data, sp_name *new_name, + uint *rows_affected); int drop_event(THD *thd, sp_name *name, bool drop_if_exists, uint *rows_affected); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index f6031a1f2fd..386dece8813 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -174,11 +174,11 @@ void lex_start(THD *thd, const uchar *buf, uint length) lex->sphead= NULL; lex->spcont= NULL; lex->proc_list.first= 0; - lex->escape_used= lex->et_compile_phase= FALSE; + lex->escape_used= FALSE; lex->reset_query_tables_list(FALSE); lex->name= 0; - lex->et= NULL; + lex->event_parse_data= NULL; lex->nest_level=0 ; lex->allow_sum_func= 0; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index e2cf213cd17..0558d60bc28 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -27,7 +27,6 @@ class sp_instr; class sp_pcontext; class st_alter_tablespace; class partition_info; -class Event_timed; class Event_parse_data; #ifdef MYSQL_SERVER @@ -1017,9 +1016,7 @@ typedef struct st_lex : public Query_tables_list st_sp_chistics sp_chistics; - Event_timed *et; Event_parse_data *event_parse_data; - bool et_compile_phase; bool only_view; /* used for SHOW CREATE TABLE/VIEW */ /* diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 5ec4e7b3b68..80e5fff5a58 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3833,57 +3833,31 @@ end_with_restore_list: case SQLCOM_ALTER_EVENT: { uint rows_affected= 1; - DBUG_ASSERT(lex->et); - do { - if (! lex->et->dbname.str || - (lex->sql_command == SQLCOM_ALTER_EVENT && lex->spname && - !lex->spname->m_db.str)) - { - my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); - res= true; - break; - } - - if (check_access(thd, EVENT_ACL, lex->et->dbname.str, 0, 0, 0, - is_schema_db(lex->et->dbname.str)) || - (lex->sql_command == SQLCOM_ALTER_EVENT && lex->spname && - (check_access(thd, EVENT_ACL, lex->spname->m_db.str, 0, 0, 0, - is_schema_db(lex->spname->m_db.str))))) - break; - - if (end_active_trans(thd)) - { - res= -1; - break; - } - - switch (lex->sql_command) { - case SQLCOM_CREATE_EVENT: - res= Events::get_instance()-> - create_event(thd, lex->et, lex->event_parse_data, - (uint) lex->create_info.options, &rows_affected); - break; - case SQLCOM_ALTER_EVENT: - res= Events::get_instance()-> - update_event(thd, lex->et, lex->event_parse_data, - lex->spname, &rows_affected); - break; - default:; - } - DBUG_PRINT("info", ("CREATE/ALTER/DROP returned error code=%d af_rows=%d", - res, rows_affected)); - if (!res) - send_ok(thd, rows_affected); + DBUG_ASSERT(lex->event_parse_data); + switch (lex->sql_command) { + case SQLCOM_CREATE_EVENT: + res= Events::get_instance()->create_event(thd, lex->event_parse_data, + (uint) lex->create_info.options, + &rows_affected); + break; + case SQLCOM_ALTER_EVENT: + res= Events::get_instance()->update_event(thd, lex->event_parse_data, + lex->spname, &rows_affected); + break; + default:; + } + DBUG_PRINT("info", ("CREATE/ALTER/DROP returned error code=%d af_rows=%d", + res, rows_affected)); + if (!res) + send_ok(thd, rows_affected); - /* lex->unit.cleanup() is called outside, no need to call it here */ - } while (0); if (!thd->spcont) { - lex->et->free_sphead_on_delete= true; - lex->et->free_sp(); - lex->et->deinit_mutexes(); + delete lex->sphead; + lex->sphead= NULL; } - + + /* lex->unit.cleanup() is called outside, no need to call it here */ break; } case SQLCOM_DROP_EVENT: @@ -3912,11 +3886,6 @@ end_with_restore_list: else { uint rows_affected= 1; - if (end_active_trans(thd)) - { - res= -1; - break; - } if (!(res= Events::get_instance()->drop_event(thd, lex->spname, lex->drop_if_exists, &rows_affected))) @@ -6020,14 +5989,6 @@ void mysql_parse(THD *thd, char *inBuf, uint length) { delete lex->sphead; lex->sphead= NULL; - if (lex->et) - { - lex->et->free_sphead_on_delete= true; - /* alloced on thd->mem_root so no real memory free but dtor call */ - lex->et->free_sp(); - lex->et->deinit_mutexes(); - lex->et= NULL; - } } else { @@ -6064,13 +6025,6 @@ void mysql_parse(THD *thd, char *inBuf, uint length) delete lex->sphead; lex->sphead= NULL; } - if (lex->et) - { - lex->et->free_sphead_on_delete= true; - lex->et->free_sp(); - lex->et->deinit_mutexes(); - lex->et= NULL; - } } thd->proc_info="freeing items"; thd->end_statement(); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index bda51faeeb8..453e3634ef4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1290,24 +1290,11 @@ event_tail: 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; + 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))) + if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD))) YYABORT; + Lex->event_parse_data->identifier= $3; /* We have to turn of CLIENT_MULTI_QUERIES while parsing a @@ -1316,15 +1303,6 @@ event_tail: */ $<ulong_num>$= 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 @@ -1353,52 +1331,12 @@ ev_schedule_time: EVERY_SYM expr interval { Lex->event_parse_data->item_expression= $2; Lex->event_parse_data->interval= $3; - LEX *lex=Lex; - if (!lex->et_compile_phase) - { - switch (lex->et->init_interval(YYTHD , $2, $3)) { - case EVEX_PARSE_ERROR: - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; - break; - case EVEX_BAD_PARAMS: - my_error(ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG, MYF(0)); - case EVEX_MICROSECOND_UNSUP: - my_error(ER_NOT_SUPPORTED_YET, MYF(0), "MICROSECOND"); - YYABORT; - break; - } - } } ev_starts ev_ends | AT_SYM expr { Lex->event_parse_data->item_execute_at= $2; - LEX *lex=Lex; - if (!lex->et_compile_phase) - { - switch (lex->et->init_execute_at(YYTHD, $2)) { - case EVEX_PARSE_ERROR: - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; - break; - case ER_WRONG_VALUE: - { - char buff[120]; - String str(buff,(uint32) sizeof(buff), system_charset_info); - String *str2= $2->val_str(&str); - my_error(ER_WRONG_VALUE, MYF(0), "AT", - str2? str2->c_ptr_safe():"NULL"); - YYABORT; - break; - } - case EVEX_BAD_PARAMS: - my_error(ER_EVENT_EXEC_TIME_IN_THE_PAST, MYF(0)); - YYABORT; - break; - } - } } ; @@ -1406,18 +1344,11 @@ opt_ev_status: /* empty */ { $$= 0; } | ENABLE_SYM { Lex->event_parse_data->status= Event_parse_data::ENABLED; - LEX *lex=Lex; - if (!lex->et_compile_phase) - lex->et->status= Event_timed::ENABLED; $$= 1; } | DISABLE_SYM { Lex->event_parse_data->status= Event_parse_data::DISABLED; - LEX *lex=Lex; - - if (!lex->et_compile_phase) - lex->et->status= Event_timed::DISABLED; $$= 1; } ; @@ -1425,32 +1356,10 @@ opt_ev_status: /* empty */ { $$= 0; } ev_starts: /* empty */ { Lex->event_parse_data->item_starts= new Item_func_now_local(); - Lex->et->init_starts(YYTHD, new Item_func_now_local()); } | STARTS_SYM expr { Lex->event_parse_data->item_starts= $2; - LEX *lex= Lex; - if (!lex->et_compile_phase) - { - - switch (lex->et->init_starts(YYTHD, $2)) { - case EVEX_PARSE_ERROR: - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; - break; - case EVEX_BAD_PARAMS: - { - char buff[20]; - String str(buff,(uint32) sizeof(buff), system_charset_info); - String *str2= $2->val_str(&str); - my_error(ER_WRONG_VALUE, MYF(0), "STARTS", - str2 ? str2->c_ptr_safe() : NULL); - YYABORT; - break; - } - } - } } ; @@ -1458,20 +1367,6 @@ ev_ends: /* empty */ | ENDS_SYM expr { Lex->event_parse_data->item_ends= $2; - LEX *lex= Lex; - if (!lex->et_compile_phase) - { - switch (lex->et->init_ends(YYTHD, $2)) { - case EVEX_PARSE_ERROR: - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; - break; - case EVEX_BAD_PARAMS: - my_error(ER_EVENT_ENDS_BEFORE_STARTS, MYF(0)); - YYABORT; - break; - } - } } ; @@ -1484,18 +1379,12 @@ ev_on_completion: { Lex->event_parse_data->on_completion= Event_parse_data::ON_COMPLETION_PRESERVE; - LEX *lex=Lex; - if (!lex->et_compile_phase) - lex->et->on_completion= Event_timed::ON_COMPLETION_PRESERVE; $$= 1; } | ON COMPLETION_SYM NOT_SYM PRESERVE_SYM { Lex->event_parse_data->on_completion= Event_parse_data::ON_COMPLETION_DROP; - LEX *lex=Lex; - if (!lex->et_compile_phase) - lex->et->on_completion= Event_timed::ON_COMPLETION_DROP; $$= 1; } ; @@ -1504,20 +1393,12 @@ opt_ev_comment: /* empty */ { $$= 0; } | COMMENT_SYM TEXT_STRING_sys { Lex->comment= Lex->event_parse_data->comment= $2; - LEX *lex= Lex; - if (!lex->et_compile_phase) - { - lex->comment= $2; - lex->et->init_comment(YYTHD, &$2); - } - $$= 1; } ; ev_sql_stmt: { LEX *lex= Lex; - sp_head *sp; /* This stops the following : @@ -1557,8 +1438,6 @@ ev_sql_stmt: Lex->event_parse_data->body_begin= lex->ptr; - if (!lex->et_compile_phase) - lex->et->body_begin= lex->ptr; } ev_sql_stmt_inner { @@ -1570,14 +1449,7 @@ ev_sql_stmt: lex->sp_chistics.suid= SP_IS_SUID;//always the definer! - lex->et->sphead= lex->sphead; - lex->sphead= NULL; - Lex->event_parse_data->init_body(YYTHD); - if (!lex->et_compile_phase) - { - lex->et->init_body(YYTHD); - } } ; @@ -4753,25 +4625,12 @@ alter: YYTHD->client_capabilities is set back to original value */ { - LEX *lex=Lex; - Event_timed *et; - - lex->spname= NULL; + Lex->spname= NULL; if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD))) YYABORT; Lex->event_parse_data->identifier= $3; - if (!(et= new (YYTHD->mem_root) Event_timed()))// implicitly calls Event_timed::init() - YYABORT; - lex->et = et; - - if (!lex->et_compile_phase) - { - et->init_definer(YYTHD); - et->init_name(YYTHD, $3); - } - /* We have to turn of CLIENT_MULTI_QUERIES while parsing a stored procedure, otherwise yylex will chop it into pieces @@ -4838,7 +4697,7 @@ opt_ev_rename_to: /* empty */ { $$= 0;} { LEX *lex=Lex; lex->spname= $3; //use lex's spname to hold the new name - //the original name is in the Event_timed object + //the original name is in the Event_parse_data object $$= 1; } ; |