diff options
author | unknown <andrey@lmy004.> | 2006-06-29 00:42:25 +0200 |
---|---|---|
committer | unknown <andrey@lmy004.> | 2006-06-29 00:42:25 +0200 |
commit | 9fa9378b2e5713250e1262879c7bc4d999e1bb40 (patch) | |
tree | 068608d07a92fd7d98e1c7f13c7b9dc9a3167f37 /sql | |
parent | 739ea377bd702a6438d1491222e8ec671ad0fbf3 (diff) | |
download | mariadb-git-9fa9378b2e5713250e1262879c7bc4d999e1bb40.tar.gz |
WL#3337 (Events new architecture)
This cut No 7 should finish the part of fixing the parsing of the events :
- Event_timed is no more used during parsing. Less problems because it has
a mutex. Event_parse_data class is used during parsing. It is suited only
for this purpose. It's pretty lightweight
- Late checking of data from parsing is being performed. This should solve
the problems of nested events in SP or other events (for the situation
of no nested bodies). Before if an ALTER EVENT was in a SP, then when the
SP was compiled, and not executed, the actual init_xxx methods of Event_timed
were called, which is wrong.
- It could be a side effect of using a specialized class, but test events_stress is
now 25% quicker.
Cut No8 will start splitting Event_scheduler into 2 parts, the QUEUE will be moved
to Event_queue.
mysql-test/r/events.result:
update result
mysql-test/t/events.test:
disabled is actually wrong, should be disable, but because of the early
checking it was never parsed.
sql/event_data_objects.cc:
move add init_xxx methods from Event_timed to Event_parse_data
Event_parse data does not need definer_user and definer_host
in Event_timed::compile() do not use lex.et, well there is no more lex.et :)
sql/event_data_objects.h:
move parsing responsibilities from Event_timed to Event_parse_data
sql/event_db_repository.cc:
No more Event_timed comes from parsing but Event_parse_data
The initialization of Item*-s from parsing is done late, and not
during the actual parsing. This is the right way to go because
if an ALTER EVENT is inside a SP or CREATE EVENT it should not be
executed (initialized) during parsing, as it was done.
sql/event_db_repository.h:
No more Event_timed comes from parsing but Event_parse_data
The initialization of Item*-s from parsing is done late, and not
during the actual parsing. This is the right way to go because
if an ALTER EVENT is inside a SP or CREATE EVENT it should not be
executed (initialized) during parsing, as it was done.
sql/event_scheduler.cc:
No more Event_timed comes from parsing but Event_parse_data
The initialization of Item*-s from parsing is done late, and not
during the actual parsing. This is the right way to go because
if an ALTER EVENT is inside a SP or CREATE EVENT it should not be
executed (initialized) during parsing, as it was done.
sql/event_scheduler.h:
No more Event_timed comes from parsing but Event_parse_data
The initialization of Item*-s from parsing is done late, and not
during the actual parsing. This is the right way to go because
if an ALTER EVENT is inside a SP or CREATE EVENT it should not be
executed (initialized) during parsing, as it was done.
sql/events.cc:
No more Event_timed comes from parsing but Event_parse_data
The initialization of Item*-s from parsing is done late, and not
during the actual parsing. This is the right way to go because
if an ALTER EVENT is inside a SP or CREATE EVENT it should not be
executed (initialized) during parsing, as it was done.
sql/events.h:
No more Event_timed comes from parsing but Event_parse_data
The initialization of Item*-s from parsing is done late, and not
during the actual parsing. This is the right way to go because
if an ALTER EVENT is inside a SP or CREATE EVENT it should not be
executed (initialized) during parsing, as it was done.
sql/sql_lex.cc:
lex->et_compile_phase and lex->et are no more.
Use lex->event_parse_data
sql/sql_lex.h:
lex->et_compile_phase and lex->et are no more.
Use lex->event_parse_data
sql/sql_parse.cc:
lex->et_compile_phase and lex->et are no more.
Use lex->event_parse_data
ACL checks were moved inside the Events subsystem.
Also ending of the transaction is performed only just
before doing disk operation. Therefore only when needed.
sql/sql_yacc.yy:
lex->et and lex->et_parse_phase are no more
Use the specialized for parsing Event_parse_data
Diffstat (limited to 'sql')
-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 |
12 files changed, 565 insertions, 822 deletions
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; } ; |