Commit 3c793e23 authored by andrey@lmy004's avatar andrey@lmy004

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.
parent e5e8713c
...@@ -297,9 +297,9 @@ select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_comp ...@@ -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 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 events_test e_26 set @a = 5 root@localhost 2017-01-01 00:00:00 DROP
drop event e_26; 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' 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' ERROR HY000: Incorrect AT value: 'definitely not a datetime'
set names utf8; set names utf8;
create event задачка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1; create event задачка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1;
......
...@@ -255,9 +255,9 @@ create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5; ...@@ -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; select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event;
drop event e_26; drop event e_26;
--error ER_WRONG_VALUE --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 --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; set names utf8;
create event задаÑка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1; create event задаÑка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1;
......
This diff is collapsed.
...@@ -54,19 +54,9 @@ class Event_timed; ...@@ -54,19 +54,9 @@ class Event_timed;
bool bool
event_timed_db_equal(Event_timed *et, LEX_STRING *db); 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*/ /* Compares the whole identifier*/
bool 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 class Event_timed
...@@ -123,7 +113,6 @@ class Event_timed ...@@ -123,7 +113,6 @@ class Event_timed
enum enum_status status; enum enum_status status;
sp_head *sphead; sp_head *sphead;
ulong sql_mode; ulong sql_mode;
const uchar *body_begin;
bool dropped; bool dropped;
bool free_sphead_on_delete; bool free_sphead_on_delete;
...@@ -138,9 +127,6 @@ class Event_timed ...@@ -138,9 +127,6 @@ class Event_timed
DBUG_RETURN(p); 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) static void operator delete(void *ptr, size_t size)
{ {
DBUG_ENTER("Event_timed::delete(ptr,size)"); DBUG_ENTER("Event_timed::delete(ptr,size)");
...@@ -150,17 +136,6 @@ class Event_timed ...@@ -150,17 +136,6 @@ class Event_timed
DBUG_VOID_RETURN; 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();
~Event_timed(); ~Event_timed();
...@@ -171,30 +146,6 @@ class Event_timed ...@@ -171,30 +146,6 @@ class Event_timed
void void
deinit_mutexes(); 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 int
load_from_row(MEM_ROOT *mem_root, TABLE *table); load_from_row(MEM_ROOT *mem_root, TABLE *table);
...@@ -231,9 +182,6 @@ class Event_timed ...@@ -231,9 +182,6 @@ class Event_timed
void void
free_sp(); free_sp();
bool
has_equal_db(Event_timed *etn);
int int
kill_thread(THD *thd); kill_thread(THD *thd);
...@@ -268,12 +216,9 @@ class Event_parse_data : public Sql_alloc ...@@ -268,12 +216,9 @@ class Event_parse_data : public Sql_alloc
LEX_STRING dbname; LEX_STRING dbname;
LEX_STRING name; LEX_STRING name;
LEX_STRING body; LEX_STRING body;
LEX_STRING definer_user;
LEX_STRING definer_host;
LEX_STRING definer;// combination of user and host LEX_STRING definer;// combination of user and host
LEX_STRING comment; LEX_STRING comment;
Item* item_starts; Item* item_starts;
Item* item_ends; Item* item_ends;
Item* item_execute_at; Item* item_execute_at;
...@@ -316,10 +261,6 @@ class Event_parse_data : public Sql_alloc ...@@ -316,10 +261,6 @@ class Event_parse_data : public Sql_alloc
void void
init_body(THD *thd); init_body(THD *thd);
void
init_comment(THD *thd, LEX_STRING *set_comment);
}; };
......
This diff is collapsed.
...@@ -53,7 +53,8 @@ events_table_scan_all(THD *thd, TABLE *schema_table, TABLE *event_table); ...@@ -53,7 +53,8 @@ events_table_scan_all(THD *thd, TABLE *schema_table, TABLE *event_table);
int int
fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */); fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */);
class Event_timed;
class Event_parse_data;
class Event_queue_element; class Event_queue_element;
class Event_db_repository class Event_db_repository
...@@ -69,11 +70,11 @@ class Event_db_repository ...@@ -69,11 +70,11 @@ class Event_db_repository
deinit_repository(); deinit_repository();
int int
create_event(THD *thd, Event_timed *et, my_bool create_if_not, create_event(THD *thd, Event_parse_data *parse_data, my_bool create_if_not,
uint *rows_affected); uint *rows_affected);
int 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 int
drop_event(THD *thd, LEX_STRING db, LEX_STRING name, bool drop_if_exists, drop_event(THD *thd, LEX_STRING db, LEX_STRING name, bool drop_if_exists,
...@@ -86,11 +87,11 @@ class Event_db_repository ...@@ -86,11 +87,11 @@ class Event_db_repository
drop_user_events(THD *thd, LEX_STRING definer); drop_user_events(THD *thd, LEX_STRING definer);
int int
find_event(THD *thd, sp_name *name, Event_timed **ett, TABLE *tbl, find_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_timed **ett,
MEM_ROOT *root); TABLE *tbl, MEM_ROOT *root);
int 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 int
find_event_by_name(THD *thd, LEX_STRING db, LEX_STRING name, TABLE *table); find_event_by_name(THD *thd, LEX_STRING db, LEX_STRING name, TABLE *table);
......
...@@ -785,7 +785,7 @@ Event_scheduler::destroy() ...@@ -785,7 +785,7 @@ Event_scheduler::destroy()
*/ */
int 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; int res;
Event_timed *et_new; Event_timed *et_new;
...@@ -799,14 +799,15 @@ Event_scheduler::create_event(THD *thd, Event_timed *et, bool check_existence) ...@@ -799,14 +799,15 @@ Event_scheduler::create_event(THD *thd, Event_timed *et, bool check_existence)
UNLOCK_SCHEDULER_DATA(); UNLOCK_SCHEDULER_DATA();
DBUG_RETURN(OP_OK); 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; res= OP_ALREADY_EXISTS;
goto end; goto end;
} }
/* We need to load the event on scheduler_root */ /* 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); queue_insert_safe(&queue, (byte *) et_new);
DBUG_PRINT("info", ("Sending COND_new_work")); DBUG_PRINT("info", ("Sending COND_new_work"));
...@@ -850,7 +851,7 @@ Event_scheduler::drop_event(THD *thd, sp_name *name) ...@@ -850,7 +851,7 @@ Event_scheduler::drop_event(THD *thd, sp_name *name)
DBUG_RETURN(OP_OK); 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")); DBUG_PRINT("info", ("No such event found, probably DISABLED"));
UNLOCK_SCHEDULER_DATA(); UNLOCK_SCHEDULER_DATA();
...@@ -906,7 +907,7 @@ Event_scheduler::drop_event(THD *thd, sp_name *name) ...@@ -906,7 +907,7 @@ Event_scheduler::drop_event(THD *thd, sp_name *name)
*/ */
int 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_schema,
LEX_STRING *new_name) LEX_STRING *new_name)
{ {
...@@ -931,7 +932,7 @@ Event_scheduler::update_event(THD *thd, Event_timed *et, ...@@ -931,7 +932,7 @@ Event_scheduler::update_event(THD *thd, Event_timed *et,
DBUG_RETURN(OP_OK); 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", DBUG_PRINT("info", ("%s.%s not found cached, probably was DISABLED",
et->dbname.str, et->name.str)); et->dbname.str, et->name.str));
...@@ -948,7 +949,8 @@ Event_scheduler::update_event(THD *thd, Event_timed *et, ...@@ -948,7 +949,8 @@ Event_scheduler::update_event(THD *thd, Event_timed *et,
1. Error occured 1. Error occured
2. If the replace is DISABLED, we don't load it into the queue. 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); queue_insert_safe(&queue, (byte *) et_new);
DBUG_PRINT("info", ("Sending COND_new_work")); DBUG_PRINT("info", ("Sending COND_new_work"));
...@@ -1014,50 +1016,8 @@ Event_scheduler::update_event(THD *thd, Event_timed *et, ...@@ -1014,50 +1016,8 @@ Event_scheduler::update_event(THD *thd, Event_timed *et,
SYNOPSIS SYNOPSIS
Event_scheduler::find_event() Event_scheduler::find_event()
etn The event to find db The schema of 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()
name 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 remove_from_q If found whether to remove from the Q
RETURN VALUE RETURN VALUE
...@@ -1071,7 +1031,7 @@ Event_scheduler::find_event(Event_timed *etn, bool remove_from_q) ...@@ -1071,7 +1031,7 @@ Event_scheduler::find_event(Event_timed *etn, bool remove_from_q)
*/ */
Event_timed * 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; uint i;
DBUG_ENTER("Event_scheduler::find_event"); DBUG_ENTER("Event_scheduler::find_event");
...@@ -1079,9 +1039,9 @@ Event_scheduler::find_event(sp_name *name, bool remove_from_q) ...@@ -1079,9 +1039,9 @@ Event_scheduler::find_event(sp_name *name, bool remove_from_q)
for (i= 0; i < queue.elements; ++i) for (i= 0; i < queue.elements; ++i)
{ {
Event_timed *et= (Event_timed *) queue_element(&queue, 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)); 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) if (remove_from_q)
queue_remove(&queue, i); queue_remove(&queue, i);
...@@ -1624,7 +1584,7 @@ Event_scheduler::clean_queue(THD *thd) ...@@ -1624,7 +1584,7 @@ Event_scheduler::clean_queue(THD *thd)
SYNOPSIS SYNOPSIS
Event_scheduler::stop_all_running_events() Event_scheduler::stop_all_running_events()
thd Thread thd Thread
NOTE NOTE
LOCK_scheduler data must be acquired prior to call to this method LOCK_scheduler data must be acquired prior to call to this method
*/ */
...@@ -1726,7 +1686,7 @@ Event_scheduler::stop() ...@@ -1726,7 +1686,7 @@ Event_scheduler::stop()
/* /*
One situation to be here is if there was a start that forked a new 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. 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)); DBUG_PRINT("info", ("manager not running but %d. doing nothing", state));
UNLOCK_SCHEDULER_DATA(); UNLOCK_SCHEDULER_DATA();
...@@ -1841,7 +1801,7 @@ Event_scheduler::workers_count() ...@@ -1841,7 +1801,7 @@ Event_scheduler::workers_count()
} }
VOID(pthread_mutex_unlock(&LOCK_thread_count)); VOID(pthread_mutex_unlock(&LOCK_thread_count));
DBUG_PRINT("exit", ("%d", count)); DBUG_PRINT("exit", ("%d", count));
DBUG_RETURN(count); DBUG_RETURN(count);
} }
...@@ -1851,7 +1811,7 @@ Event_scheduler::workers_count() ...@@ -1851,7 +1811,7 @@ Event_scheduler::workers_count()
SYNOPSIS SYNOPSIS
Event_scheduler::check_n_suspend_if_needed() Event_scheduler::check_n_suspend_if_needed()
thd Thread thd Thread
RETURN VALUE RETURN VALUE
FALSE Not suspended, we haven't slept FALSE Not suspended, we haven't slept
TRUE We were suspended. LOCK_scheduler_data is unlocked. TRUE We were suspended. LOCK_scheduler_data is unlocked.
...@@ -1936,7 +1896,7 @@ Event_scheduler::check_n_wait_for_non_empty_queue(THD *thd) ...@@ -1936,7 +1896,7 @@ Event_scheduler::check_n_wait_for_non_empty_queue(THD *thd)
if (!queue.elements) if (!queue.elements)
thd->enter_cond(&cond_vars[COND_new_work], &LOCK_scheduler_data, 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 */ /* Wait in a loop protecting against catching spurious signals */
while (!queue.elements && state == RUNNING) while (!queue.elements && state == RUNNING)
...@@ -2079,7 +2039,7 @@ Event_scheduler::get_state() ...@@ -2079,7 +2039,7 @@ Event_scheduler::get_state()
SYNOPSIS SYNOPSIS
Event_scheduler::initialized() Event_scheduler::initialized()
RETURN VALUE RETURN VALUE
FALSE Was not initialized so far FALSE Was not initialized so far
TRUE Was initialized TRUE Was initialized
......
...@@ -57,11 +57,11 @@ class Event_scheduler ...@@ -57,11 +57,11 @@ class Event_scheduler
/* Methods for queue management follow */ /* Methods for queue management follow */
int int
create_event(THD *thd, Event_timed *et, bool check_existence); create_event(THD *thd, Event_parse_data *et, bool check_existence);
int int
update_event(THD *thd, Event_timed *et, LEX_STRING *new_schema, update_event(THD *thd, Event_parse_data *et, LEX_STRING *new_schema,
LEX_STRING *new_name); LEX_STRING *new_name);
bool bool
drop_event(THD *thd, sp_name *name); drop_event(THD *thd, sp_name *name);
...@@ -129,10 +129,7 @@ class Event_scheduler ...@@ -129,10 +129,7 @@ class Event_scheduler
private: private:
Event_timed * Event_timed *
find_event(Event_timed *etn, bool remove_from_q); find_event(LEX_STRING db, LEX_STRING name, bool remove_from_q);
Event_timed *
find_event(sp_name *name, bool remove_from_q);
uint uint
workers_count(); workers_count();
......
...@@ -186,7 +186,7 @@ Events::reconstruct_interval_expression(String *buf, interval_type interval, ...@@ -186,7 +186,7 @@ Events::reconstruct_interval_expression(String *buf, interval_type interval,
expr= tmp_expr - (tmp_expr/60)*60; expr= tmp_expr - (tmp_expr/60)*60;
/* the code after the switch will finish */ /* the code after the switch will finish */
} }
break; break;
case INTERVAL_DAY_SECOND: case INTERVAL_DAY_SECOND:
{ {
ulonglong tmp_expr= expr; ulonglong tmp_expr= expr;
...@@ -283,23 +283,19 @@ Events::open_event_table(THD *thd, enum thr_lock_type lock_type, ...@@ -283,23 +283,19 @@ Events::open_event_table(THD *thd, enum thr_lock_type lock_type,
*/ */
int int
Events::create_event(THD *thd, Event_timed *et, Event_parse_data *parse_data, Events::create_event(THD *thd, Event_parse_data *parse_data, uint create_options,
uint create_options, uint *rows_affected) uint *rows_affected)
{ {
int ret; int ret;
DBUG_ENTER("Events::create_event"); DBUG_ENTER("Events::create_event");
DBUG_PRINT("enter", ("name: %*s options:%d", et->name.length,
et->name.str, create_options));
if (!(ret= db_repository-> if (!(ret= db_repository->
create_event(thd, et, create_event(thd, parse_data,
create_options & HA_LEX_CREATE_IF_NOT_EXISTS, create_options & HA_LEX_CREATE_IF_NOT_EXISTS,
rows_affected))) rows_affected)))
{ {
Event_scheduler *scheduler= Event_scheduler::get_instance(); Event_scheduler *scheduler= Event_scheduler::get_instance();
if (scheduler->initialized() && 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); 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 */ /* 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, ...@@ -315,7 +311,7 @@ Events::create_event(THD *thd, Event_timed *et, Event_parse_data *parse_data,
Events::update_event() Events::update_event()
thd THD thd THD
et event's data et event's data
new_name set in case of RENAME TO. new_name set in case of RENAME TO.
RETURN VALUE RETURN VALUE
0 OK 0 OK
...@@ -328,25 +324,23 @@ Events::create_event(THD *thd, Event_timed *et, Event_parse_data *parse_data, ...@@ -328,25 +324,23 @@ Events::create_event(THD *thd, Event_timed *et, Event_parse_data *parse_data,
*/ */
int int
Events::update_event(THD *thd, Event_timed *et, Event_parse_data *parse_data, Events::update_event(THD *thd, Event_parse_data *parse_data, sp_name *new_name,
sp_name *new_name, uint *rows_affected) uint *rows_affected)
{ {
int ret; int ret;
DBUG_ENTER("Events::update_event"); 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 db_update_event() opens & closes the table to prevent
crash later in the code when loading and compiling the new definition. 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 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(); Event_scheduler *scheduler= Event_scheduler::get_instance();
if (scheduler->initialized() && if (scheduler->initialized() &&
(ret= scheduler->update_event(thd, et, (ret= scheduler->update_event(thd, parse_data,
new_name? &new_name->m_db: NULL, new_name? &new_name->m_db: NULL,
new_name? &new_name->m_name: NULL))) new_name? &new_name->m_name: NULL)))
my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0), ret); my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0), ret);
} }
DBUG_RETURN(ret); DBUG_RETURN(ret);
...@@ -411,7 +405,7 @@ Events::show_create_event(THD *thd, sp_name *spn) ...@@ -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)); DBUG_PRINT("enter", ("name: %*s", spn->m_name.length, spn->m_name.str));
thd->reset_n_backup_open_tables_state(&backup); 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); thd->restore_backup_open_tables_state(&backup);
if (!ret) if (!ret)
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
class sp_name; class sp_name;
class Event_timed;
class Event_parse_data; class Event_parse_data;
class Event_db_repository; class Event_db_repository;
...@@ -45,7 +44,6 @@ class Events ...@@ -45,7 +44,6 @@ class Events
Event_timed::drop() and Event_timed is fixed not do drop directly Event_timed::drop() and Event_timed is fixed not do drop directly
or other scheme will be found. or other scheme will be found.
*/ */
friend class Event_timed;
static ulong opt_event_scheduler; static ulong opt_event_scheduler;
static TYPELIB opt_typelib; static TYPELIB opt_typelib;
...@@ -66,12 +64,12 @@ class Events ...@@ -66,12 +64,12 @@ class Events
get_instance(); get_instance();
int int
create_event(THD *thd, Event_timed *et, Event_parse_data *parse_data, create_event(THD *thd, Event_parse_data *parse_data, uint create_options,
uint create_options, uint *rows_affected); uint *rows_affected);
int int
update_event(THD *thd, Event_timed *et, Event_parse_data *parse_data, update_event(THD *thd, Event_parse_data *parse_data, sp_name *new_name,
sp_name *new_name, uint *rows_affected); uint *rows_affected);
int int
drop_event(THD *thd, sp_name *name, bool drop_if_exists, uint *rows_affected); drop_event(THD *thd, sp_name *name, bool drop_if_exists, uint *rows_affected);
......
...@@ -174,11 +174,11 @@ void lex_start(THD *thd, const uchar *buf, uint length) ...@@ -174,11 +174,11 @@ void lex_start(THD *thd, const uchar *buf, uint length)
lex->sphead= NULL; lex->sphead= NULL;
lex->spcont= NULL; lex->spcont= NULL;
lex->proc_list.first= 0; lex->proc_list.first= 0;
lex->escape_used= lex->et_compile_phase= FALSE; lex->escape_used= FALSE;
lex->reset_query_tables_list(FALSE); lex->reset_query_tables_list(FALSE);
lex->name= 0; lex->name= 0;
lex->et= NULL; lex->event_parse_data= NULL;
lex->nest_level=0 ; lex->nest_level=0 ;
lex->allow_sum_func= 0; lex->allow_sum_func= 0;
......
...@@ -27,7 +27,6 @@ class sp_instr; ...@@ -27,7 +27,6 @@ class sp_instr;
class sp_pcontext; class sp_pcontext;
class st_alter_tablespace; class st_alter_tablespace;
class partition_info; class partition_info;
class Event_timed;
class Event_parse_data; class Event_parse_data;
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
...@@ -1017,9 +1016,7 @@ typedef struct st_lex : public Query_tables_list ...@@ -1017,9 +1016,7 @@ typedef struct st_lex : public Query_tables_list
st_sp_chistics sp_chistics; st_sp_chistics sp_chistics;
Event_timed *et;
Event_parse_data *event_parse_data; Event_parse_data *event_parse_data;
bool et_compile_phase;
bool only_view; /* used for SHOW CREATE TABLE/VIEW */ bool only_view; /* used for SHOW CREATE TABLE/VIEW */
/* /*
......
...@@ -3833,57 +3833,31 @@ mysql_execute_command(THD *thd) ...@@ -3833,57 +3833,31 @@ mysql_execute_command(THD *thd)
case SQLCOM_ALTER_EVENT: case SQLCOM_ALTER_EVENT:
{ {
uint rows_affected= 1; uint rows_affected= 1;
DBUG_ASSERT(lex->et); DBUG_ASSERT(lex->event_parse_data);
do { switch (lex->sql_command) {
if (! lex->et->dbname.str || case SQLCOM_CREATE_EVENT:
(lex->sql_command == SQLCOM_ALTER_EVENT && lex->spname && res= Events::get_instance()->create_event(thd, lex->event_parse_data,
!lex->spname->m_db.str)) (uint) lex->create_info.options,
{ &rows_affected);
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); break;
res= true; case SQLCOM_ALTER_EVENT:
break; res= Events::get_instance()->update_event(thd, lex->event_parse_data,
} lex->spname, &rows_affected);
break;
if (check_access(thd, EVENT_ACL, lex->et->dbname.str, 0, 0, 0, default:;
is_schema_db(lex->et->dbname.str)) || }
(lex->sql_command == SQLCOM_ALTER_EVENT && lex->spname && DBUG_PRINT("info", ("CREATE/ALTER/DROP returned error code=%d af_rows=%d",
(check_access(thd, EVENT_ACL, lex->spname->m_db.str, 0, 0, 0, res, rows_affected));
is_schema_db(lex->spname->m_db.str))))) if (!res)
break; send_ok(thd, rows_affected);
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);
/* lex->unit.cleanup() is called outside, no need to call it here */
} while (0);
if (!thd->spcont) if (!thd->spcont)
{ {
lex->et->free_sphead_on_delete= true; delete lex->sphead;
lex->et->free_sp(); lex->sphead= NULL;
lex->et->deinit_mutexes();
} }
/* lex->unit.cleanup() is called outside, no need to call it here */
break; break;
} }
case SQLCOM_DROP_EVENT: case SQLCOM_DROP_EVENT:
...@@ -3912,11 +3886,6 @@ mysql_execute_command(THD *thd) ...@@ -3912,11 +3886,6 @@ mysql_execute_command(THD *thd)
else else
{ {
uint rows_affected= 1; uint rows_affected= 1;
if (end_active_trans(thd))
{
res= -1;
break;
}
if (!(res= Events::get_instance()->drop_event(thd, lex->spname, if (!(res= Events::get_instance()->drop_event(thd, lex->spname,
lex->drop_if_exists, lex->drop_if_exists,
&rows_affected))) &rows_affected)))
...@@ -6020,14 +5989,6 @@ void mysql_parse(THD *thd, char *inBuf, uint length) ...@@ -6020,14 +5989,6 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
{ {
delete lex->sphead; delete lex->sphead;
lex->sphead= NULL; 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 else
{ {
...@@ -6064,13 +6025,6 @@ void mysql_parse(THD *thd, char *inBuf, uint length) ...@@ -6064,13 +6025,6 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
delete lex->sphead; delete lex->sphead;
lex->sphead= NULL; 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->proc_info="freeing items";
thd->end_statement(); thd->end_statement();
......
...@@ -1290,24 +1290,11 @@ event_tail: ...@@ -1290,24 +1290,11 @@ event_tail:
YYTHD->client_capabilities is set back to original value YYTHD->client_capabilities is set back to original value
*/ */
{ {
LEX *lex=Lex; Lex->create_info.options= $2;
if (lex->et)
{
/*
Recursive CREATE EVENT statement are not possible because
recursive SPs are not also possible. lex->sp_head is not stacked.
*/
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "EVENT");
YYABORT;
}
lex->create_info.options= $2;
if (!(lex->et= new(YYTHD->mem_root) Event_timed())) // implicitly calls Event_timed::init() if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD)))
YYABORT;
if (!(lex->event_parse_data= Event_parse_data::new_instance(YYTHD)))
YYABORT; YYABORT;
Lex->event_parse_data->identifier= $3;
/* /*
We have to turn of CLIENT_MULTI_QUERIES while parsing a We have to turn of CLIENT_MULTI_QUERIES while parsing a
...@@ -1316,15 +1303,6 @@ event_tail: ...@@ -1316,15 +1303,6 @@ event_tail:
*/ */
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; $<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
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 ON SCHEDULE_SYM ev_schedule_time
opt_ev_on_completion opt_ev_on_completion
...@@ -1353,52 +1331,12 @@ ev_schedule_time: EVERY_SYM expr interval ...@@ -1353,52 +1331,12 @@ ev_schedule_time: EVERY_SYM expr interval
{ {
Lex->event_parse_data->item_expression= $2; Lex->event_parse_data->item_expression= $2;
Lex->event_parse_data->interval= $3; 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_starts
ev_ends ev_ends
| AT_SYM expr | AT_SYM expr
{ {
Lex->event_parse_data->item_execute_at= $2; 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; } ...@@ -1406,18 +1344,11 @@ opt_ev_status: /* empty */ { $$= 0; }
| ENABLE_SYM | ENABLE_SYM
{ {
Lex->event_parse_data->status= Event_parse_data::ENABLED; Lex->event_parse_data->status= Event_parse_data::ENABLED;
LEX *lex=Lex;
if (!lex->et_compile_phase)
lex->et->status= Event_timed::ENABLED;
$$= 1; $$= 1;
} }
| DISABLE_SYM | DISABLE_SYM
{ {
Lex->event_parse_data->status= Event_parse_data::DISABLED; Lex->event_parse_data->status= Event_parse_data::DISABLED;
LEX *lex=Lex;
if (!lex->et_compile_phase)
lex->et->status= Event_timed::DISABLED;
$$= 1; $$= 1;
} }
; ;
...@@ -1425,32 +1356,10 @@ opt_ev_status: /* empty */ { $$= 0; } ...@@ -1425,32 +1356,10 @@ opt_ev_status: /* empty */ { $$= 0; }
ev_starts: /* empty */ ev_starts: /* empty */
{ {
Lex->event_parse_data->item_starts= new Item_func_now_local(); Lex->event_parse_data->item_starts= new Item_func_now_local();
Lex->et->init_starts(YYTHD, new Item_func_now_local());
} }
| STARTS_SYM expr | STARTS_SYM expr
{ {
Lex->event_parse_data->item_starts= $2; 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 */ ...@@ -1458,20 +1367,6 @@ ev_ends: /* empty */
| ENDS_SYM expr | ENDS_SYM expr
{ {
Lex->event_parse_data->item_ends= $2; 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: ...@@ -1484,18 +1379,12 @@ ev_on_completion:
{ {
Lex->event_parse_data->on_completion= Lex->event_parse_data->on_completion=
Event_parse_data::ON_COMPLETION_PRESERVE; Event_parse_data::ON_COMPLETION_PRESERVE;
LEX *lex=Lex;
if (!lex->et_compile_phase)
lex->et->on_completion= Event_timed::ON_COMPLETION_PRESERVE;
$$= 1; $$= 1;
} }
| ON COMPLETION_SYM NOT_SYM PRESERVE_SYM | ON COMPLETION_SYM NOT_SYM PRESERVE_SYM
{ {
Lex->event_parse_data->on_completion= Lex->event_parse_data->on_completion=
Event_parse_data::ON_COMPLETION_DROP; Event_parse_data::ON_COMPLETION_DROP;
LEX *lex=Lex;
if (!lex->et_compile_phase)
lex->et->on_completion= Event_timed::ON_COMPLETION_DROP;
$$= 1; $$= 1;
} }
; ;
...@@ -1504,20 +1393,12 @@ opt_ev_comment: /* empty */ { $$= 0; } ...@@ -1504,20 +1393,12 @@ opt_ev_comment: /* empty */ { $$= 0; }
| COMMENT_SYM TEXT_STRING_sys | COMMENT_SYM TEXT_STRING_sys
{ {
Lex->comment= Lex->event_parse_data->comment= $2; 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: ev_sql_stmt:
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_head *sp;
/* /*
This stops the following : This stops the following :
...@@ -1557,8 +1438,6 @@ ev_sql_stmt: ...@@ -1557,8 +1438,6 @@ ev_sql_stmt:
Lex->event_parse_data->body_begin= lex->ptr; Lex->event_parse_data->body_begin= lex->ptr;
if (!lex->et_compile_phase)
lex->et->body_begin= lex->ptr;
} }
ev_sql_stmt_inner ev_sql_stmt_inner
{ {
...@@ -1570,14 +1449,7 @@ ev_sql_stmt: ...@@ -1570,14 +1449,7 @@ ev_sql_stmt:
lex->sp_chistics.suid= SP_IS_SUID;//always the definer! lex->sp_chistics.suid= SP_IS_SUID;//always the definer!
lex->et->sphead= lex->sphead;
lex->sphead= NULL;
Lex->event_parse_data->init_body(YYTHD); Lex->event_parse_data->init_body(YYTHD);
if (!lex->et_compile_phase)
{
lex->et->init_body(YYTHD);
}
} }
; ;
...@@ -4753,25 +4625,12 @@ alter: ...@@ -4753,25 +4625,12 @@ alter:
YYTHD->client_capabilities is set back to original value YYTHD->client_capabilities is set back to original value
*/ */
{ {
LEX *lex=Lex; Lex->spname= NULL;
Event_timed *et;
lex->spname= NULL;
if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD))) if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD)))
YYABORT; YYABORT;
Lex->event_parse_data->identifier= $3; 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 We have to turn of CLIENT_MULTI_QUERIES while parsing a
stored procedure, otherwise yylex will chop it into pieces stored procedure, otherwise yylex will chop it into pieces
...@@ -4838,7 +4697,7 @@ opt_ev_rename_to: /* empty */ { $$= 0;} ...@@ -4838,7 +4697,7 @@ opt_ev_rename_to: /* empty */ { $$= 0;}
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->spname= $3; //use lex's spname to hold the new name 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; $$= 1;
} }
; ;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment