Commit ef9a97e6 authored by unknown's avatar unknown

WL#3337 (Event scheduler new architecture)

Third cut to simplify parsing phase. Now DROP EVENT works.

Overloaded few functions to be able to use either sp_name or pass two LEX_STRINGs
instead of a Event_timed pointer. This is transitional and eventually the old
functions will be removed. For now DROP EVENT also works, does not need anymore
a parsing object (Event_timed) and definer initialization because everyone who
has EVENT_ACL can drop events, and this is checked on execution time in sql_parse.cc
from the security context, as it should be.


sql/event_data_objects.cc:
  overload few functions
sql/event_scheduler.cc:
  Event_scheduler::drop_event() actually does not need Event_timed object
  but just an identifier, hence pass only sp_name.
  
  Overloaded Event_scheduler::find_event() to work with sp_name object. Eventually
  the old version will be removed. This is being done as transitional step to
  be able to test frequently code.
sql/event_scheduler.h:
  Event_scheduler::drop_event() actually does not need Event_timed object
  but just an identifier, hence pass only sp_name.
  
  Overloaded Event_scheduler::find_event() to work with sp_name object. Eventually
  the old version will be removed. This is being done as transitional step to
  be able to test frequently code.
sql/events.cc:
  Change db_drop_event() not to use Event_timed, either coming from parsing
  or from Event_timed::drop, but use LEX_STRINGs. sp_name is not convinient
  because in Event_timed::drop a temporary object has to be created. Hence, 
  dereference the sp_name in Events::drop_event() and pass the LEX_STRINGs.
sql/events.h:
  Change db_drop_event() not to use Event_timed, either coming from parsing
  or from Event_timed::drop, but use LEX_STRINGs. sp_name is not convinient
  because in Event_timed::drop a temporary object has to be created. Hence, 
  dereference the sp_name in Events::drop_event() and pass the LEX_STRINGs.
sql/events_priv.h:
  Change db_drop_event() not to use Event_timed, either coming from parsing
  or from Event_timed::drop, but use LEX_STRINGs. sp_name is not convinient
  because in Event_timed::drop a temporary object has to be created. Hence, 
  dereference the sp_name in Events::drop_event() and pass the LEX_STRINGs.
sql/sql_parse.cc:
  SQLCOM_DROP_EVENT does not need lex->event_parse_data object and 
  is more like SQLCOM_SHOW_CREATE_EVENT. Therefore, move it to the block that
  handles the latter.
sql/sql_yacc.yy:
  DROP EVENT does not need a parsing object, just a name.
  Store it as lex->spname. Pretty similar handling to the one of
  SHOW CREATE EVENT.
parent d2db48c6
......@@ -1299,7 +1299,7 @@ Event_timed::drop(THD *thd)
uint tmp= 0;
DBUG_ENTER("Event_timed::drop");
DBUG_RETURN(db_drop_event(thd, this, false, &tmp));
DBUG_RETURN(db_drop_event(thd, dbname, name, false, &tmp));
}
......@@ -1903,8 +1903,62 @@ bool
event_timed_identifier_equal(Event_timed *a, Event_timed *b)
{
return event_timed_name_equal(a, &b->name) &&
event_timed_db_equal(a, &b->dbname) &&
event_timed_definer_equal(a, &b->definer);
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);
}
......
......@@ -833,12 +833,13 @@ Event_scheduler::create_event(THD *thd, Event_timed *et, bool check_existence)
*/
bool
Event_scheduler::drop_event(THD *thd, Event_timed *et)
Event_scheduler::drop_event(THD *thd, sp_name *name)
{
int res;
Event_timed *et_old;
DBUG_ENTER("Event_scheduler::drop_event");
DBUG_PRINT("enter", ("thd=%p et=%p lock=%p",thd,et,&LOCK_scheduler_data));
DBUG_PRINT("enter", ("thd=%p name=%p lock=%p", thd, name,
&LOCK_scheduler_data));
LOCK_SCHEDULER_DATA();
if (!is_running_or_suspended())
......@@ -848,7 +849,7 @@ Event_scheduler::drop_event(THD *thd, Event_timed *et)
DBUG_RETURN(OP_OK);
}
if (!(et_old= find_event(et, TRUE)))
if (!(et_old= find_event(name, TRUE)))
DBUG_PRINT("info", ("No such event found, probably DISABLED"));
UNLOCK_SCHEDULER_DATA();
......@@ -1049,6 +1050,48 @@ Event_scheduler::find_event(Event_timed *etn, bool remove_from_q)
}
/*
Searches for an event in the scheduler queue
SYNOPSIS
Event_scheduler::find_event()
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
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(sp_name *name, 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]?", name->m_db.str, name->m_name.str,
et->dbname.str, et->name.str));
if (event_timed_identifier_equal(name, et))
{
if (remove_from_q)
queue_remove(&queue, i);
DBUG_RETURN(et);
}
}
DBUG_RETURN(NULL);
}
/*
Drops all events from the in-memory queue and disk that match
certain pattern evaluated by a comparator function
......
......@@ -16,6 +16,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
class sp_name;
class Event_timed;
class THD;
......@@ -73,7 +74,7 @@ class Event_scheduler
LEX_STRING *new_name);
bool
drop_event(THD *thd, Event_timed *et);
drop_event(THD *thd, sp_name *name);
int
......@@ -136,6 +137,9 @@ class Event_scheduler
Event_timed *
find_event(Event_timed *etn, bool remove_from_q);
Event_timed *
find_event(sp_name *name, bool remove_from_q);
uint
workers_count();
......
......@@ -988,14 +988,15 @@ Events::update_event(THD *thd, Event_timed *et, Event_parse_data *parse_data,
!0 Error (my_error() called)
*/
int db_drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
uint *rows_affected)
int db_drop_event(THD *thd, LEX_STRING db, LEX_STRING name,
bool drop_if_exists, uint *rows_affected)
{
TABLE *table;
Open_tables_state backup;
int ret;
DBUG_ENTER("db_drop_event");
DBUG_PRINT("enter", ("db=%s name=%s", db.str, name.str));
ret= EVEX_OPEN_TABLE_FAILED;
thd->reset_n_backup_open_tables_state(&backup);
......@@ -1005,13 +1006,10 @@ int db_drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
goto done;
}
if (!(ret= evex_db_find_event_aux(thd, et, table)))
if (!(ret= evex_db_find_event_by_name(thd, db, name, table)))
{
if ((ret= table->file->ha_delete_row(table->record[0])))
{
my_error(ER_EVENT_CANNOT_DELETE, MYF(0));
goto done;
}
}
else if (ret == EVEX_KEY_NOT_FOUND)
{
......@@ -1019,14 +1017,12 @@ int db_drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
"Event", et->name.str);
"Event", name.str);
ret= 0;
} else
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), et->name.str);
goto done;
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str);
}
done:
/*
evex_drop_event() is used by Event_timed::drop therefore
......@@ -1044,7 +1040,7 @@ int db_drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
SYNOPSIS
Events::drop_event()
thd THD
et event's name
name event's name
drop_if_exists if set and the event not existing => warning onto the stack
rows_affected affected number of rows is returned heres
......@@ -1054,16 +1050,17 @@ int db_drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
*/
int
Events::drop_event(THD *thd, Event_timed *et, Event_parse_data *parse_data,
bool drop_if_exists, uint *rows_affected)
Events::drop_event(THD *thd, sp_name *name, bool drop_if_exists,
uint *rows_affected)
{
int ret;
DBUG_ENTER("Events::drop_event");
if (!(ret= db_drop_event(thd, et, drop_if_exists, rows_affected)))
if (!(ret= db_drop_event(thd, name->m_db, name->m_name, drop_if_exists,
rows_affected)))
{
Event_scheduler *scheduler= Event_scheduler::get_instance();
if (scheduler->initialized() && (ret= scheduler->drop_event(thd, et)))
if (scheduler->initialized() && (ret= scheduler->drop_event(thd, name)))
my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0), ret);
}
......
......@@ -16,7 +16,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
class sp_name;
class Event_timed;
class Event_parse_data;
......@@ -56,8 +56,7 @@ class Events
sp_name *new_name, uint *rows_affected);
static int
drop_event(THD *thd, Event_timed *et, Event_parse_data *parse_data,
bool drop_if_exists, uint *rows_affected);
drop_event(THD *thd, sp_name *name, bool drop_if_exists, uint *rows_affected);
static int
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
......
......@@ -25,6 +25,7 @@
#define EVEX_MAX_INTERVAL_VALUE 2147483647L
class Event_timed;
class sp_name;
int
evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
......@@ -32,7 +33,7 @@ evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
TABLE *table);
int
db_drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
db_drop_event(THD *thd, LEX_STRING db, LEX_STRING name, bool drop_if_exists,
uint *rows_affected);
int
db_find_event(THD *thd, sp_name *name, Event_timed **ett, TABLE *tbl,
......@@ -68,6 +69,20 @@ bool
event_timed_identifier_equal(Event_timed *a, Event_timed *b);
/* Compares only the name part of the identifier */
bool
event_timed_name_equal(sp_name *name, LEX_STRING *event_name);
/* 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);
bool
change_security_context(THD *thd, LEX_STRING user, LEX_STRING host,
LEX_STRING db, Security_context *s_ctx,
......
......@@ -3819,7 +3819,6 @@ mysql_execute_command(THD *thd)
}
case SQLCOM_CREATE_EVENT:
case SQLCOM_ALTER_EVENT:
case SQLCOM_DROP_EVENT:
{
uint rows_affected= 1;
DBUG_ASSERT(lex->et);
......@@ -3856,9 +3855,6 @@ mysql_execute_command(THD *thd)
res= Events::update_event(thd, lex->et, lex->event_parse_data,
lex->spname, &rows_affected);
break;
case SQLCOM_DROP_EVENT:
res= Events::drop_event(thd, lex->et, lex->event_parse_data,
lex->drop_if_exists, &rows_affected);
default:;
}
DBUG_PRINT("info", ("CREATE/ALTER/DROP returned error code=%d af_rows=%d",
......@@ -3877,6 +3873,7 @@ mysql_execute_command(THD *thd)
break;
}
case SQLCOM_DROP_EVENT:
case SQLCOM_SHOW_CREATE_EVENT:
{
DBUG_ASSERT(lex->spname);
......@@ -3893,9 +3890,24 @@ mysql_execute_command(THD *thd)
if (lex->spname->m_name.length > NAME_LEN)
{
my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
/* this jumps to the end of the function and skips own messaging */
goto error;
}
res= Events::show_create_event(thd, lex->spname);
if (lex->sql_command == SQLCOM_SHOW_CREATE_EVENT)
res= Events::show_create_event(thd, lex->spname);
else
{
uint rows_affected= 1;
if (end_active_trans(thd))
{
res= -1;
break;
}
if (!(res= Events::drop_event(thd, lex->spname, lex->drop_if_exists,
&rows_affected)))
send_ok(thd, rows_affected);
}
break;
}
#ifndef DBUG_OFF
......
......@@ -7686,33 +7686,9 @@ drop:
}
| DROP EVENT_SYM if_exists sp_name
{
if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD)))
YYABORT;
Lex->event_parse_data->identifier= $4;
LEX *lex=Lex;
if (lex->et)
{
/*
Recursive events are not possible because recursive SPs
are not also possible. lex->sp_head is not stacked.
*/
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "EVENT");
YYABORT;
}
if (!(lex->et= new (YYTHD->mem_root) Event_timed()))
YYABORT;
if (!lex->et_compile_phase)
{
lex->et->init_name(YYTHD, $4);
lex->et->init_definer(YYTHD);
}
lex->sql_command = SQLCOM_DROP_EVENT;
lex->drop_if_exists= $3;
Lex->drop_if_exists= $3;
Lex->spname= $4;
Lex->sql_command = SQLCOM_DROP_EVENT;
}
| DROP TRIGGER_SYM sp_name
{
......
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