Commit acefb78b authored by unknown's avatar unknown

WL#3337 (Events new architecture)

5th cut, moved DB related code to Event_db_repository and
updated accordingly the remanining code.
Moved change/restore_security_context() to class THD
Removed events_priv.h
Next step is to reorganize create/update_event() and parsing for them.
But probably some other refactoring could be done in the meanwhile.
The changes so far pass the test suite.


BitKeeper/deleted/.del-events_priv.h~2e8bce2cf35997df:
  Delete: sql/events_priv.h
sql/Makefile.am:
  events_priv.h is no more
sql/event_data_objects.cc:
  reorganize events code
sql/event_data_objects.h:
  reorganize events code
sql/event_db_repository.cc:
  reorganize events code
sql/event_db_repository.h:
  reorganize events code
sql/event_scheduler.cc:
  reorganize events code
sql/event_scheduler.h:
  reorganize events code
sql/events.cc:
  reorganize events code
sql/events.h:
  reorganize events code
sql/mysqld.cc:
  reorganize events code
sql/set_var.cc:
  reorganize events code
sql/sql_class.cc:
  add ::change_security_context() and restore_security_context()
sql/sql_class.h:
  add ::change_security_context() and restore_security_context()
sql/sql_db.cc:
  reorganize Events code
sql/sql_parse.cc:
  reorganize Events code
sql/sql_show.cc:
  reorganize Events code
parent cace147c
......@@ -64,7 +64,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
tztime.h my_decimal.h\
sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \
parse_file.h sql_view.h sql_trigger.h \
sql_array.h sql_cursor.h events.h events_priv.h \
sql_array.h sql_cursor.h events.h \
sql_plugin.h authors.h sql_partition.h event_data_objects.h \
event_queue.h event_db_repository.h \
partition_info.h partition_element.h event_scheduler.h \
......
......@@ -16,12 +16,15 @@
#define MYSQL_LEX 1
#include "mysql_priv.h"
#include "events_priv.h"
#include "events.h"
#include "event_data_objects.h"
#include "event_db_repository.h"
#include "sp_head.h"
#define EVEX_MAX_INTERVAL_VALUE 2147483647L
Event_parse_data *
Event_parse_data::new_instance(THD *thd)
{
......@@ -733,29 +736,29 @@ Event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table)
et= this;
if (table->s->fields != Events::FIELD_COUNT)
if (table->s->fields != ET_FIELD_COUNT)
goto error;
if ((et->dbname.str= get_field(mem_root,
table->field[Events::FIELD_DB])) == NULL)
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[Events::FIELD_NAME])) == NULL)
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[Events::FIELD_BODY])) == NULL)
table->field[ET_FIELD_BODY])) == NULL)
goto error;
et->body.length= strlen(et->body.str);
if ((et->definer.str= get_field(mem_root,
table->field[Events::FIELD_DEFINER])) == NullS)
table->field[ET_FIELD_DEFINER])) == NullS)
goto error;
et->definer.length= strlen(et->definer.str);
......@@ -772,27 +775,27 @@ Event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table)
et->definer_host.str= strmake_root(mem_root, ptr + 1, len);/* 1:because of @*/
et->definer_host.length= len;
et->starts_null= table->field[Events::FIELD_STARTS]->is_null();
res1= table->field[Events::FIELD_STARTS]->
et->starts_null= table->field[ET_FIELD_STARTS]->is_null();
res1= table->field[ET_FIELD_STARTS]->
get_date(&et->starts,TIME_NO_ZERO_DATE);
et->ends_null= table->field[Events::FIELD_ENDS]->is_null();
res2= table->field[Events::FIELD_ENDS]->get_date(&et->ends, TIME_NO_ZERO_DATE);
et->ends_null= table->field[ET_FIELD_ENDS]->is_null();
res2= table->field[ET_FIELD_ENDS]->get_date(&et->ends, TIME_NO_ZERO_DATE);
if (!table->field[Events::FIELD_INTERVAL_EXPR]->is_null())
et->expression= table->field[Events::FIELD_INTERVAL_EXPR]->val_int();
if (!table->field[ET_FIELD_INTERVAL_EXPR]->is_null())
et->expression= table->field[ET_FIELD_INTERVAL_EXPR]->val_int();
else
et->expression= 0;
/*
If res1 and res2 are true then both fields are empty.
Hence if Events::FIELD_EXECUTE_AT is empty there is an error.
Hence if ET_FIELD_EXECUTE_AT is empty there is an error.
*/
et->execute_at_null=
table->field[Events::FIELD_EXECUTE_AT]->is_null();
table->field[ET_FIELD_EXECUTE_AT]->is_null();
DBUG_ASSERT(!(et->starts_null && et->ends_null && !et->expression &&
et->execute_at_null));
if (!et->expression &&
table->field[Events::FIELD_EXECUTE_AT]-> get_date(&et->execute_at,
table->field[ET_FIELD_EXECUTE_AT]-> get_date(&et->execute_at,
TIME_NO_ZERO_DATE))
goto error;
......@@ -800,22 +803,22 @@ Event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table)
In DB the values start from 1 but enum interval_type starts
from 0
*/
if (!table->field[Events::FIELD_TRANSIENT_INTERVAL]->is_null())
if (!table->field[ET_FIELD_TRANSIENT_INTERVAL]->is_null())
et->interval= (interval_type) ((ulonglong)
table->field[Events::FIELD_TRANSIENT_INTERVAL]->val_int() - 1);
table->field[ET_FIELD_TRANSIENT_INTERVAL]->val_int() - 1);
else
et->interval= (interval_type) 0;
et->created= table->field[Events::FIELD_CREATED]->val_int();
et->modified= table->field[Events::FIELD_MODIFIED]->val_int();
et->created= table->field[ET_FIELD_CREATED]->val_int();
et->modified= table->field[ET_FIELD_MODIFIED]->val_int();
table->field[Events::FIELD_LAST_EXECUTED]->
table->field[ET_FIELD_LAST_EXECUTED]->
get_date(&et->last_executed, TIME_NO_ZERO_DATE);
last_executed_changed= false;
/* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */
if ((ptr= get_field(mem_root, table->field[Events::FIELD_STATUS])) == NullS)
if ((ptr= get_field(mem_root, table->field[ET_FIELD_STATUS])) == NullS)
goto error;
DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", et->name.str, ptr));
......@@ -823,20 +826,20 @@ Event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table)
/* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */
if ((ptr= get_field(mem_root,
table->field[Events::FIELD_ON_COMPLETION])) == NullS)
table->field[ET_FIELD_ON_COMPLETION])) == NullS)
goto error;
et->on_completion= (ptr[0]=='D'? Event_timed::ON_COMPLETION_DROP:
Event_timed::ON_COMPLETION_PRESERVE);
et->comment.str= get_field(mem_root, table->field[Events::FIELD_COMMENT]);
et->comment.str= get_field(mem_root, table->field[ET_FIELD_COMMENT]);
if (et->comment.str != NullS)
et->comment.length= strlen(et->comment.str);
else
et->comment.length= 0;
et->sql_mode= (ulong) table->field[Events::FIELD_SQL_MODE]->val_int();
et->sql_mode= (ulong) table->field[ET_FIELD_SQL_MODE]->val_int();
DBUG_RETURN(0);
error:
......@@ -1277,6 +1280,7 @@ Event_timed::mark_last_executed(THD *thd)
}
/*
Drops the event
......@@ -1299,7 +1303,8 @@ Event_timed::drop(THD *thd)
uint tmp= 0;
DBUG_ENTER("Event_timed::drop");
DBUG_RETURN(db_drop_event(thd, dbname, name, false, &tmp));
DBUG_RETURN(Events::get_instance()->
db_repository.drop_event(thd, dbname, name, false, &tmp));
}
......@@ -1336,7 +1341,7 @@ Event_timed::update_fields(THD *thd)
thd->reset_n_backup_open_tables_state(&backup);
if (Events::open_event_table(thd, TL_WRITE, &table))
if (Events::get_instance()->open_event_table(thd, TL_WRITE, &table))
{
ret= EVEX_OPEN_TABLE_FAILED;
goto done;
......@@ -1352,15 +1357,15 @@ Event_timed::update_fields(THD *thd)
if (last_executed_changed)
{
table->field[Events::FIELD_LAST_EXECUTED]->set_notnull();
table->field[Events::FIELD_LAST_EXECUTED]->store_time(&last_executed,
table->field[ET_FIELD_LAST_EXECUTED]->set_notnull();
table->field[ET_FIELD_LAST_EXECUTED]->store_time(&last_executed,
MYSQL_TIMESTAMP_DATETIME);
last_executed_changed= false;
}
if (status_changed)
{
table->field[Events::FIELD_STATUS]->set_notnull();
table->field[Events::FIELD_STATUS]->store((longlong)status, true);
table->field[ET_FIELD_STATUS]->set_notnull();
table->field[ET_FIELD_STATUS]->store((longlong)status, true);
status_changed= false;
}
......@@ -1630,8 +1635,8 @@ Event_timed::compile(THD *thd, MEM_ROOT *mem_root)
thd->query_length= show_create.length();
DBUG_PRINT("info", ("query:%s",thd->query));
change_security_context(thd, definer_user, definer_host, dbname,
&security_ctx, &save_ctx);
thd->change_security_context(definer_user, definer_host, dbname,
&security_ctx, &save_ctx);
thd->lex= &lex;
lex_start(thd, (uchar*)thd->query, thd->query_length);
lex.et_compile_phase= TRUE;
......@@ -1669,7 +1674,7 @@ done:
lex.et->deinit_mutexes();
lex_end(&lex);
restore_security_context(thd, save_ctx);
thd->restore_security_context(save_ctx);
DBUG_PRINT("note", ("return old data on its place. set back NAMES"));
thd->lex= old_lex;
......@@ -1870,23 +1875,6 @@ event_timed_db_equal(Event_timed *et, LEX_STRING *db)
}
/*
Checks whether two events have the same definer
SYNOPSIS
event_timed_definer_equal()
Returns
TRUE definers are equal
FALSE definers are not equal
*/
bool
event_timed_definer_equal(Event_timed *et, LEX_STRING *definer)
{
return !sortcmp_lex_string(et->definer, *definer, system_charset_info);
}
/*
Checks whether two events are equal by identifiers
......
......@@ -40,9 +40,35 @@
#define EVENT_FREE_WHEN_FINISHED (1L << 2)
#define EVENT_EXEC_STARTED 0
#define EVENT_EXEC_ALREADY_EXEC 1
#define EVENT_EXEC_CANT_FORK 2
class sp_head;
class Sql_alloc;
class Event_timed;
/* Compares only the schema part of the identifier */
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);
class Event_timed
{
Event_timed(const Event_timed &); /* Prevent use of these */
......@@ -296,4 +322,10 @@ public:
};
class Event_queue_element : public Event_timed
{
};
#endif /* _EVENT_DATA_OBJECTS_H_ */
This diff is collapsed.
......@@ -16,5 +16,87 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
enum enum_events_table_field
{
ET_FIELD_DB = 0,
ET_FIELD_NAME,
ET_FIELD_BODY,
ET_FIELD_DEFINER,
ET_FIELD_EXECUTE_AT,
ET_FIELD_INTERVAL_EXPR,
ET_FIELD_TRANSIENT_INTERVAL,
ET_FIELD_CREATED,
ET_FIELD_MODIFIED,
ET_FIELD_LAST_EXECUTED,
ET_FIELD_STARTS,
ET_FIELD_ENDS,
ET_FIELD_STATUS,
ET_FIELD_ON_COMPLETION,
ET_FIELD_SQL_MODE,
ET_FIELD_COMMENT,
ET_FIELD_COUNT /* a cool trick to count the number of fields :) */
};
int
evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
const LEX_STRING ev_name,
TABLE *table);
class Event_queue_element;
class Event_db_repository
{
public:
Event_db_repository(){}
~Event_db_repository(){}
int
init_repository();
void
deinit_repository();
int
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
int
create_event(THD *thd, Event_timed *et, my_bool create_if_not,
uint *rows_affected);
int
update_event(THD *thd, Event_timed *et, sp_name *new_name);
int
drop_event(THD *thd, LEX_STRING db, LEX_STRING name, bool drop_if_exists,
uint *rows_affected);
int
drop_schema_events(THD *thd, LEX_STRING schema);
int
drop_user_events(THD *thd, LEX_STRING definer);
int
find_event(THD *thd, sp_name *name, Event_timed **ett, TABLE *tbl,
MEM_ROOT *root);
int
load_named_event(THD *thd, Event_timed *etn, Event_timed **etn_new);
int
find_event_by_name(THD *thd, LEX_STRING db, LEX_STRING name, TABLE *table);
private:
int
drop_events_by_field(THD *thd, enum enum_events_table_field field,
LEX_STRING field_value);
MEM_ROOT repo_root;
/* Prevent use of these */
Event_db_repository(const Event_db_repository &);
void operator=(Event_db_repository &);
};
#endif /* _EVENT_DB_REPOSITORY_H_ */
......@@ -15,10 +15,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysql_priv.h"
#include "events_priv.h"
#include "events.h"
#include "event_data_objects.h"
#include "event_scheduler.h"
#include "event_db_repository.h"
#include "sp_head.h"
/*
......@@ -574,8 +574,8 @@ event_worker_thread(void *arg)
to change the context before sending the signal. We are under
LOCK_scheduler_data being held by Event_scheduler::run() -> ::execute_top().
*/
change_security_context(thd, event->definer_user, event->definer_host,
event->dbname, &security_ctx, &save_ctx);
thd->change_security_context(event->definer_user, event->definer_host,
event->dbname, &security_ctx, &save_ctx);
DBUG_PRINT("info", ("master_access=%d db_access=%d",
thd->security_ctx->master_access, thd->security_ctx->db_access));
......@@ -687,7 +687,7 @@ Event_scheduler::get_instance()
*/
bool
Event_scheduler::init()
Event_scheduler::init(Event_db_repository *db_repo)
{
int i= 0;
bool ret= FALSE;
......@@ -695,6 +695,7 @@ Event_scheduler::init()
DBUG_PRINT("enter", ("this=%p", this));
LOCK_SCHEDULER_DATA();
db_repository= db_repo;
for (;i < COND_LAST; i++)
if (pthread_cond_init(&cond_vars[i], NULL))
{
......@@ -783,10 +784,10 @@ Event_scheduler::destroy()
OP_LOAD_ERROR Error during loading from disk
*/
enum Event_scheduler::enum_error_code
int
Event_scheduler::create_event(THD *thd, Event_timed *et, bool check_existence)
{
enum enum_error_code res;
int res;
Event_timed *et_new;
DBUG_ENTER("Event_scheduler::create_event");
DBUG_PRINT("enter", ("thd=%p et=%p lock=%p",thd,et,&LOCK_scheduler_data));
......@@ -805,7 +806,7 @@ Event_scheduler::create_event(THD *thd, Event_timed *et, bool check_existence)
}
/* We need to load the event on scheduler_root */
if (!(res= load_named_event(thd, et, &et_new)))
if (!(res= db_repository->load_named_event(thd, et, &et_new)))
{
queue_insert_safe(&queue, (byte *) et_new);
DBUG_PRINT("info", ("Sending COND_new_work"));
......@@ -904,12 +905,12 @@ Event_scheduler::drop_event(THD *thd, sp_name *name)
OP_ALREADY_EXISTS Event already in the queue
*/
enum Event_scheduler::enum_error_code
int
Event_scheduler::update_event(THD *thd, Event_timed *et,
LEX_STRING *new_schema,
LEX_STRING *new_name)
{
enum enum_error_code res;
int res= OP_OK;
Event_timed *et_old, *et_new= NULL;
LEX_STRING old_schema, old_name;
......@@ -947,7 +948,7 @@ 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= load_named_event(thd, et, &et_new)))
if (!(res= db_repository->load_named_event(thd, et, &et_new)))
{
queue_insert_safe(&queue, (byte *) et_new);
DBUG_PRINT("info", ("Sending COND_new_work"));
......@@ -961,7 +962,7 @@ Event_scheduler::update_event(THD *thd, Event_timed *et,
et->dbname= old_schema;
et->name= old_name;
}
DBUG_PRINT("info", ("res=%d", res));
UNLOCK_SCHEDULER_DATA();
/*
Andrey: Is this comment still truthful ???
......@@ -1111,11 +1112,11 @@ Event_scheduler::find_event(sp_name *name, bool remove_from_q)
*/
void
Event_scheduler::drop_matching_events(THD *thd, LEX_STRING *pattern,
Event_scheduler::drop_matching_events(THD *thd, LEX_STRING pattern,
bool (*comparator)(Event_timed *,LEX_STRING *))
{
DBUG_ENTER("Event_scheduler::drop_matching_events");
DBUG_PRINT("enter", ("pattern=%*s state=%d", pattern->length, pattern->str,
DBUG_PRINT("enter", ("pattern=%*s state=%d", pattern.length, pattern.str,
state));
if (is_running_or_suspended())
{
......@@ -1124,7 +1125,7 @@ Event_scheduler::drop_matching_events(THD *thd, LEX_STRING *pattern,
{
Event_timed *et= (Event_timed *) queue_element(&queue, i);
DBUG_PRINT("info", ("[%s.%s]?", et->dbname.str, et->name.str));
if (comparator(et, pattern))
if (comparator(et, &pattern))
{
/*
The queue is ordered. If we remove an element, then all elements after
......@@ -1179,7 +1180,7 @@ Event_scheduler::drop_matching_events(THD *thd, LEX_STRING *pattern,
*/
int
Event_scheduler::drop_schema_events(THD *thd, LEX_STRING *schema)
Event_scheduler::drop_schema_events(THD *thd, LEX_STRING schema)
{
int ret;
DBUG_ENTER("Event_scheduler::drop_schema_events");
......@@ -1187,7 +1188,6 @@ Event_scheduler::drop_schema_events(THD *thd, LEX_STRING *schema)
if (is_running_or_suspended())
drop_matching_events(thd, schema, event_timed_db_equal);
ret= db_drop_events_from_table(thd, schema);
UNLOCK_SCHEDULER_DATA();
DBUG_RETURN(ret);
......@@ -1713,7 +1713,7 @@ Event_scheduler::stop_all_running_events(THD *thd)
The caller must have acquited LOCK_scheduler_data.
*/
enum Event_scheduler::enum_error_code
int
Event_scheduler::stop()
{
THD *thd= current_thd;
......@@ -1778,7 +1778,7 @@ Event_scheduler::stop()
OP_OK OK
*/
enum Event_scheduler::enum_error_code
int
Event_scheduler::suspend_or_resume(
enum Event_scheduler::enum_suspend_or_resume action)
{
......@@ -2116,59 +2116,6 @@ Event_scheduler::events_count()
}
/*
Looks for a named event in mysql.event and then loads it from
the table, compiles and inserts it into the cache.
SYNOPSIS
Event_scheduler::load_named_event()
thd THD
etn The name of the event to load and compile on scheduler's root
etn_new The loaded event
RETURN VALUE
NULL Error during compile or the event is non-enabled.
otherwise Address
*/
enum Event_scheduler::enum_error_code
Event_scheduler::load_named_event(THD *thd, Event_timed *etn, Event_timed **etn_new)
{
int ret= 0;
MEM_ROOT *tmp_mem_root;
Event_timed *et_loaded= NULL;
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));
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= db_find_event(thd, &spn, &et_loaded, NULL, &scheduler_root);
}
thd->restore_backup_open_tables_state(&backup);
/* In this case no memory was allocated so we don't need to clean */
if (ret)
DBUG_RETURN(OP_LOAD_ERROR);
if (et_loaded->status != Event_timed::ENABLED)
{
/*
We don't load non-enabled events.
In db_find_event() `et_new` was allocated on the heap and not on
scheduler_root therefore we delete it here.
*/
delete et_loaded;
DBUG_RETURN(OP_DISABLED_EVENT);
}
et_loaded->compute_next_execution_time();
*etn_new= et_loaded;
DBUG_RETURN(OP_OK);
}
/*
......@@ -2212,7 +2159,7 @@ Event_scheduler::load_events_from_db(THD *thd)
DBUG_RETURN(EVEX_GENERAL_ERROR);
}
if ((ret= Events::open_event_table(thd, TL_READ, &table)))
if ((ret= Events::get_instance()->open_event_table(thd, TL_READ, &table)))
{
sql_print_error("SCHEDULER: Table mysql.event is damaged. Can not open.");
DBUG_RETURN(EVEX_OPEN_TABLE_FAILED);
......
......@@ -18,6 +18,7 @@
class sp_name;
class Event_timed;
class Event_db_repository;
class THD;
typedef bool * (*event_timed_identifier_comparator)(Event_timed*, Event_timed*);
......@@ -31,17 +32,6 @@ events_shutdown();
class Event_scheduler
{
public:
/* Return codes */
enum enum_error_code
{
OP_OK= 0,
OP_NOT_RUNNING,
OP_CANT_KILL,
OP_CANT_INIT,
OP_DISABLED_EVENT,
OP_LOAD_ERROR,
OP_ALREADY_EXISTS
};
enum enum_state
{
......@@ -66,10 +56,10 @@ public:
/* Methods for queue management follow */
enum enum_error_code
int
create_event(THD *thd, Event_timed *et, bool check_existence);
enum enum_error_code
int
update_event(THD *thd, Event_timed *et, LEX_STRING *new_schema,
LEX_STRING *new_name);
......@@ -78,10 +68,10 @@ public:
int
drop_schema_events(THD *thd, LEX_STRING *schema);
drop_schema_events(THD *thd, LEX_STRING schema);
int
drop_user_events(THD *thd, LEX_STRING *definer, uint *dropped_num)
drop_user_events(THD *thd, LEX_STRING *definer)
{ DBUG_ASSERT(0); return 0;}
uint
......@@ -92,20 +82,24 @@ public:
bool
start();
enum enum_error_code
int
stop();
bool
start_suspended();
/*
Need to be public because has to be called from the function
passed to pthread_create.
*/
bool
run(THD *thd);
enum enum_error_code
int
suspend_or_resume(enum enum_suspend_or_resume action);
bool
init();
init(Event_db_repository *db_repo);
void
destroy();
......@@ -156,14 +150,11 @@ private:
void
stop_all_running_events(THD *thd);
enum enum_error_code
load_named_event(THD *thd, Event_timed *etn, Event_timed **etn_new);
int
load_events_from_db(THD *thd);
void
drop_matching_events(THD *thd, LEX_STRING *pattern,
drop_matching_events(THD *thd, LEX_STRING pattern,
bool (*)(Event_timed *,LEX_STRING *));
bool
......@@ -230,6 +221,8 @@ private:
/* The MEM_ROOT of the object */
MEM_ROOT scheduler_root;
Event_db_repository *db_repository;
/* The sorted queue with the Event_timed objects */
QUEUE queue;
......
This diff is collapsed.
......@@ -20,74 +20,91 @@ class sp_name;
class Event_timed;
class Event_parse_data;
#include "event_db_repository.h"
/* Return codes */
enum enum_events_error_code
{
OP_OK= 0,
OP_NOT_RUNNING,
OP_CANT_KILL,
OP_CANT_INIT,
OP_DISABLED_EVENT,
OP_LOAD_ERROR,
OP_ALREADY_EXISTS
};
int
sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
class Events
{
public:
/*
Quite NOT the best practice and will be removed once
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;
enum enum_table_field
{
FIELD_DB = 0,
FIELD_NAME,
FIELD_BODY,
FIELD_DEFINER,
FIELD_EXECUTE_AT,
FIELD_INTERVAL_EXPR,
FIELD_TRANSIENT_INTERVAL,
FIELD_CREATED,
FIELD_MODIFIED,
FIELD_LAST_EXECUTED,
FIELD_STARTS,
FIELD_ENDS,
FIELD_STATUS,
FIELD_ON_COMPLETION,
FIELD_SQL_MODE,
FIELD_COMMENT,
FIELD_COUNT /* a cool trick to count the number of fields :) */
};
static int
init();
static void
deinit();
static void
init_mutexes();
static void
destroy_mutexes();
static Events*
get_instance();
int
create_event(THD *thd, Event_timed *et, Event_parse_data *parse_data,
uint create_options, uint *rows_affected);
static int
int
update_event(THD *thd, Event_timed *et, Event_parse_data *parse_data,
sp_name *new_name, uint *rows_affected);
static int
int
drop_event(THD *thd, sp_name *name, bool drop_if_exists, uint *rows_affected);
static int
int
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
static int
int
show_create_event(THD *thd, sp_name *spn);
/* Needed for both SHOW CREATE EVENT and INFORMATION_SCHEMA */
static int
reconstruct_interval_expression(String *buf, interval_type interval,
longlong expression);
static int
int
drop_schema_events(THD *thd, char *db);
static int
int
dump_internal_status(THD *thd);
static int
init();
static void
shutdown();
static void
init_mutexes();
static void
destroy_mutexes();
Event_db_repository db_repository;
private:
/* Singleton DP is used */
Events(){}
~Events(){}
/* Singleton instance */
static Events singleton;
/* Prevent use of these */
Events(const Events &);
void operator=(Events &);
......
#ifndef _EVENT_PRIV_H_
#define _EVENT_PRIV_H_
/* Copyright (C) 2004-2006 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define EVENT_EXEC_STARTED 0
#define EVENT_EXEC_ALREADY_EXEC 1
#define EVENT_EXEC_CANT_FORK 2
#define EVEX_DB_FIELD_LEN 64
#define EVEX_NAME_FIELD_LEN 64
#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,
const LEX_STRING ev_name,
TABLE *table);
int
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,
MEM_ROOT *root);
int
db_create_event(THD *thd, Event_timed *et, my_bool create_if_not,
uint *rows_affected);
int
db_drop_events_from_table(THD *thd, LEX_STRING *db);
int
sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
/* Compares only the name part of the identifier */
bool
event_timed_name_equal(Event_timed *et, LEX_STRING *name);
/* Compares only the schema part of the identifier */
bool
event_timed_db_equal(Event_timed *et, LEX_STRING *db);
/*
Compares only the definer part of the identifier. Use during DROP USER
to drop user's events. (Still not implemented)
*/
bool
event_timed_definer_equal(Event_timed *et, LEX_STRING *definer);
/* Compares the whole identifier*/
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,
Security_context **backup);
void
restore_security_context(THD *thd, Security_context *backup);
#endif /* _EVENT_PRIV_H_ */
......@@ -886,7 +886,7 @@ static void close_connections(void)
}
(void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
Events::shutdown();
Events::deinit();
end_slave();
if (thread_count)
......
......@@ -3891,7 +3891,7 @@ byte *sys_var_thd_dbug::value_ptr(THD *thd, enum_var_type type, LEX_STRING *b)
bool
sys_var_event_scheduler::update(THD *thd, set_var *var)
{
enum Event_scheduler::enum_error_code res;
int res;
Event_scheduler *scheduler= Event_scheduler::get_instance();
/* here start the thread if not running. */
DBUG_ENTER("sys_var_event_scheduler::update");
......
......@@ -2048,6 +2048,63 @@ bool Security_context::set_user(char *user_arg)
return user == 0;
}
/*
Switches the security context
SYNOPSIS
THD::change_security_context()
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
FALSE OK
TRUE Error (generates error too)
*/
bool
THD::change_security_context(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= security_ctx;
security_ctx= s_ctx;
#endif
DBUG_RETURN(FALSE);
}
/*
Restores the security context
SYNOPSIS
restore_security_context()
thd Thread
backup Context to switch to
*/
void
THD::restore_security_context(Security_context *backup)
{
DBUG_ENTER("restore_security_context");
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (backup)
security_ctx= backup;
#endif
DBUG_VOID_RETURN;
}
/****************************************************************************
Handling of open and locked tables states.
......
......@@ -868,6 +868,14 @@ public:
char *db, *catalog;
Security_context main_security_ctx;
Security_context *security_ctx;
bool
change_security_context(LEX_STRING user, LEX_STRING host,
LEX_STRING db, Security_context *s_ctx,
Security_context **backup);
void
restore_security_context(Security_context *backup);
/* remote (peer) port */
uint16 peer_port;
......
......@@ -904,7 +904,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
exit:
(void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */
error= Events::drop_schema_events(thd, db);
error= Events::get_instance()->drop_schema_events(thd, db);
/*
If this database was the client's selected database, we silently change the
client's selected database to nothing (to have an empty SELECT DATABASE()
......
......@@ -3847,13 +3847,14 @@ end_with_restore_list:
switch (lex->sql_command) {
case SQLCOM_CREATE_EVENT:
res= Events::create_event(thd, lex->et, lex->event_parse_data,
(uint) lex->create_info.options,
&rows_affected);
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::update_event(thd, lex->et, lex->event_parse_data,
lex->spname, &rows_affected);
res= Events::get_instance()->
update_event(thd, lex->et, lex->event_parse_data,
lex->spname, &rows_affected);
break;
default:;
}
......@@ -3895,7 +3896,7 @@ end_with_restore_list:
}
if (lex->sql_command == SQLCOM_SHOW_CREATE_EVENT)
res= Events::show_create_event(thd, lex->spname);
res= Events::get_instance()->show_create_event(thd, lex->spname);
else
{
uint rows_affected= 1;
......@@ -3904,8 +3905,9 @@ end_with_restore_list:
res= -1;
break;
}
if (!(res= Events::drop_event(thd, lex->spname, lex->drop_if_exists,
&rows_affected)))
if (!(res= Events::get_instance()->drop_event(thd, lex->spname,
lex->drop_if_exists,
&rows_affected)))
send_ok(thd, rows_affected);
}
break;
......@@ -3913,7 +3915,7 @@ end_with_restore_list:
#ifndef DBUG_OFF
case SQLCOM_SHOW_SCHEDULER_STATUS:
{
res= Events::dump_internal_status(thd);
res= Events::get_instance()->dump_internal_status(thd);
break;
}
#endif
......
......@@ -4324,7 +4324,7 @@ int events_table_index_read_for_db(THD *thd, TABLE *schema_table,
DBUG_PRINT("info", ("Using prefix scanning on PK"));
event_table->file->ha_index_init(0, 1);
event_table->field[Events::FIELD_DB]->
event_table->field[ET_FIELD_DB]->
store(thd->lex->select_lex.db, strlen(thd->lex->select_lex.db), scs);
key_info= event_table->key_info;
key_len= key_info->key_part[0].store_length;
......@@ -4443,7 +4443,7 @@ int fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
thd->lex->select_lex.db:"(null)"));
thd->reset_n_backup_open_tables_state(&backup);
if (Events::open_event_table(thd, TL_READ, &event_table))
if (Events::get_instance()->open_event_table(thd, TL_READ, &event_table))
{
sql_print_error("Table mysql.event is damaged.");
thd->restore_backup_open_tables_state(&backup);
......
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