Commit 9fa9378b authored by unknown's avatar unknown

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
parent 739ea377
......@@ -297,9 +297,9 @@ select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_comp
db name body definer convert_tz(execute_at, 'UTC', 'SYSTEM') on_completion
events_test e_26 set @a = 5 root@localhost 2017-01-01 00:00:00 DROP
drop event e_26;
create event e_26 on schedule at NULL disabled do set @a = 5;
create event e_26 on schedule at NULL disable do set @a = 5;
ERROR HY000: Incorrect AT value: 'NULL'
create event e_26 on schedule at 'definitely not a datetime' disabled do set @a = 5;
create event e_26 on schedule at 'definitely not a datetime' disable do set @a = 5;
ERROR HY000: Incorrect AT value: 'definitely not a datetime'
set names utf8;
create event задачка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1;
......
......@@ -255,9 +255,9 @@ create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5;
select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event;
drop event e_26;
--error ER_WRONG_VALUE
create event e_26 on schedule at NULL disabled do set @a = 5;
create event e_26 on schedule at NULL disable do set @a = 5;
--error ER_WRONG_VALUE
create event e_26 on schedule at 'definitely not a datetime' disabled do set @a = 5;
create event e_26 on schedule at 'definitely not a datetime' disable do set @a = 5;
set names utf8;
create event задаÑка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1;
......
This diff is collapsed.
......@@ -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 @@ class Event_timed
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 @@ class Event_timed
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 @@ class Event_timed
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();
......@@ -171,30 +146,6 @@ class Event_timed
void
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);
......@@ -231,9 +182,6 @@ class Event_timed
void
free_sp();
bool
has_equal_db(Event_timed *etn);
int
kill_thread(THD *thd);
......@@ -268,12 +216,9 @@ class Event_parse_data : public Sql_alloc
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 @@ class Event_parse_data : public Sql_alloc
void
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);
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 @@ class Event_db_repository
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 @@ class Event_db_repository
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);
......
......@@ -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
......
......@@ -57,11 +57,11 @@ class Event_scheduler
/* 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 @@ class Event_scheduler
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();
......
......@@ -186,7 +186,7 @@ Events::reconstruct_interval_expression(String *buf, interval_type interval,
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)
......
......@@ -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 @@ class Events
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 @@ class Events
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);
......
......@@ -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;
......
......@@ -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 */
/*
......
......@@ -3833,57 +3833,31 @@ mysql_execute_command(THD *thd)
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 @@ mysql_execute_command(THD *thd)
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();
......
......@@ -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;
}
;
......
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