WL#3337 (Event scheduler new architecture)
Post-review fixes. Mostly whitespace, int-to-bool return value, fixed comments sql/Makefile.am: compile all submodules of Events before compiling the facade sql/event_data_objects.cc: - Use initialization list - Clean whitespaces - Shorten comments - Fix comments sql/event_data_objects.h: - Fix whitespace sql/event_db_repository.cc: - Change return type from int to bool where only one error code is returned. - Don't use macros but get the maximal number of characters in a column from the column - Fix comments - Make functions which has return value but it's not used - void. sql/event_db_repository.h: - Methods with only one error code int -> bool return value - Remove declaration of fill_schema_events, a function that does not exist sql/event_queue.cc: - Use initialization lists - Let find_n_remove_event delete the object thus making the code more robust. The caller could forget to destruct the object. In addition, find_n_remove_element() does not return a value. - Move check_system_tables() to class Events - Fix comments sql/event_queue.h: - Whitespace changes - init_queue() should allow passing of THD - check_system_tables moved to class Events - find_n_remove_event() is now void sql/event_scheduler.cc: - Initialize res before use - Remove end stop from message sql/event_scheduler.h: Add uninitialized state. The scheduler is in it before init_scheduler() is called. The rationale is that otherwise state has no value before the call. If the system tables were damaged the scheduler won't be initialized but in Events::deinit() Event_scheduler::stop() will be called and this will touch state, generating valgrind warning at minimum. sql/events.cc: - Whitespace changes - Fix comments - Make methods which have only one error code be bool instead of int - Create temporarily a THD to be used for the initialization of Event_queue - Event_queue::check_system_tables() moved to Events::check_system_tables - is_started() is renamed to is_execution_of_events_started() sql/events.h: - Whitespace changes - When a method returns only one error code it should be bool, not int - is_started() renamed to is_execution_of_events_started() sql/set_var.cc: is_started() is renamed to is_execution_of_events_started() sql/sql_db.cc: The return code is not used, thus don't return anything and drop_schema_events() is now void. sql/sql_yacc.yy: - Fix comments - Remove unneeded initialization which is performed in lex_init() sql/share/errmsg.txt: New error message sql/table.cc: - Fix comments - make table_check_intact() accespt const *table_def sql/table.h: Make table_check_intact() accespt const *table_def
This commit is contained in:
parent
e5a2cb50fa
commit
99adbd131a
@ -105,8 +105,8 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
|
|||||||
tztime.cc my_time.c my_user.c my_decimal.cc\
|
tztime.cc my_time.c my_user.c my_decimal.cc\
|
||||||
sp_head.cc sp_pcontext.cc sp_rcontext.cc sp.cc \
|
sp_head.cc sp_pcontext.cc sp_rcontext.cc sp.cc \
|
||||||
sp_cache.cc parse_file.cc sql_trigger.cc \
|
sp_cache.cc parse_file.cc sql_trigger.cc \
|
||||||
event_scheduler.cc events.cc event_data_objects.cc \
|
event_scheduler.cc event_data_objects.cc \
|
||||||
event_queue.cc event_db_repository.cc \
|
event_queue.cc event_db_repository.cc events.cc \
|
||||||
sql_plugin.cc sql_binlog.cc \
|
sql_plugin.cc sql_binlog.cc \
|
||||||
sql_builtin.cc sql_tablespace.cc partition_info.cc
|
sql_builtin.cc sql_tablespace.cc partition_info.cc
|
||||||
|
|
||||||
|
@ -59,19 +59,17 @@ Event_parse_data::new_instance(THD *thd)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Event_parse_data::Event_parse_data()
|
Event_parse_data::Event_parse_data()
|
||||||
|
:on_completion(ON_COMPLETION_DROP), status(ENABLED),
|
||||||
|
item_starts(NULL), item_ends(NULL), item_execute_at(NULL),
|
||||||
|
starts_null(TRUE), ends_null(TRUE), execute_at_null(TRUE),
|
||||||
|
item_expression(NULL), expression(0)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Event_parse_data::Event_parse_data");
|
DBUG_ENTER("Event_parse_data::Event_parse_data");
|
||||||
|
|
||||||
item_execute_at= item_expression= item_starts= item_ends= NULL;
|
|
||||||
status= ENABLED;
|
|
||||||
on_completion= ON_COMPLETION_DROP;
|
|
||||||
expression= 0;
|
|
||||||
|
|
||||||
/* Actually in the parser STARTS is always set */
|
/* Actually in the parser STARTS is always set */
|
||||||
set_zero_time(&starts, MYSQL_TIMESTAMP_DATETIME);
|
set_zero_time(&starts, MYSQL_TIMESTAMP_DATETIME);
|
||||||
set_zero_time(&ends, MYSQL_TIMESTAMP_DATETIME);
|
set_zero_time(&ends, MYSQL_TIMESTAMP_DATETIME);
|
||||||
set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
|
set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
|
||||||
starts_null= ends_null= execute_at_null= TRUE;
|
|
||||||
|
|
||||||
body.str= comment.str= NULL;
|
body.str= comment.str= NULL;
|
||||||
body.length= comment.length= 0;
|
body.length= comment.length= 0;
|
||||||
@ -736,8 +734,8 @@ Event_timed::~Event_timed()
|
|||||||
Event_job_data::Event_job_data()
|
Event_job_data::Event_job_data()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Event_job_data::Event_job_data():
|
Event_job_data::Event_job_data()
|
||||||
thd(NULL), sphead(NULL), sql_mode(0)
|
:thd(NULL), sphead(NULL), sql_mode(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1115,14 +1113,16 @@ bool get_next_time(TIME *next, TIME *start, TIME *time_now, TIME *last_exec,
|
|||||||
interval.month= (diff_months / months)*months;
|
interval.month= (diff_months / months)*months;
|
||||||
/*
|
/*
|
||||||
Check if the same month as last_exec (always set - prerequisite)
|
Check if the same month as last_exec (always set - prerequisite)
|
||||||
An event happens at most once per month so there is no way to schedule
|
An event happens at most once per month so there is no way to
|
||||||
it two times for the current month. This saves us from two calls to
|
schedule it two times for the current month. This saves us from two
|
||||||
date_add_interval() if the event was just executed. But if the scheduler
|
calls to date_add_interval() if the event was just executed. But if
|
||||||
is started and there was at least 1 scheduled date skipped this one does
|
the scheduler is started and there was at least 1 scheduled date
|
||||||
not help and two calls to date_add_interval() will be done, which is a
|
skipped this one does not help and two calls to date_add_interval()
|
||||||
bit more expensive but compared to the rareness of the case is neglectable.
|
will be done, which is a bit more expensive but compared to the
|
||||||
|
rareness of the case is neglectable.
|
||||||
*/
|
*/
|
||||||
if (time_now->year==last_exec->year && time_now->month==last_exec->month)
|
if (time_now->year == last_exec->year &&
|
||||||
|
time_now->month == last_exec->month)
|
||||||
interval.month+= months;
|
interval.month+= months;
|
||||||
|
|
||||||
tmp= *start;
|
tmp= *start;
|
||||||
@ -1454,7 +1454,8 @@ Event_queue_element::drop(THD *thd)
|
|||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
FALSE OK
|
FALSE OK
|
||||||
TRUE Error while opening mysql.event for writing or during write on disk
|
TRUE Error while opening mysql.event for writing or during
|
||||||
|
write on disk
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -1645,9 +1646,9 @@ Event_job_data::execute(THD *thd)
|
|||||||
event_change_security_context(thd, definer_user, definer_host, dbname,
|
event_change_security_context(thd, definer_user, definer_host, dbname,
|
||||||
&save_ctx);
|
&save_ctx);
|
||||||
/*
|
/*
|
||||||
THD::~THD will clean this or if there is DROP DATABASE in the SP then
|
THD::~THD will clean this or if there is DROP DATABASE in the
|
||||||
it will be free there. It should not point to our buffer which is allocated
|
SP then it will be free there. It should not point to our buffer
|
||||||
on a mem_root.
|
which is allocated on a mem_root.
|
||||||
*/
|
*/
|
||||||
thd->db= my_strdup(dbname.str, MYF(0));
|
thd->db= my_strdup(dbname.str, MYF(0));
|
||||||
thd->db_length= dbname.length;
|
thd->db_length= dbname.length;
|
||||||
@ -1719,7 +1720,6 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root)
|
|||||||
|
|
||||||
switch (get_fake_create_event(thd, &show_create)) {
|
switch (get_fake_create_event(thd, &show_create)) {
|
||||||
case EVEX_MICROSECOND_UNSUP:
|
case EVEX_MICROSECOND_UNSUP:
|
||||||
sql_print_error("Scheduler");
|
|
||||||
DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
|
DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
@ -1769,7 +1769,8 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root)
|
|||||||
Free lex associated resources
|
Free lex associated resources
|
||||||
QQ: Do we really need all this stuff here?
|
QQ: Do we really need all this stuff here?
|
||||||
*/
|
*/
|
||||||
sql_print_error("error during compile of %s.%s or thd->is_fatal_error=%d",
|
sql_print_error("SCHEDULER: Error during compilation of %s.%s or "
|
||||||
|
"thd->is_fatal_error=%d",
|
||||||
dbname.str, name.str, thd->is_fatal_error);
|
dbname.str, name.str, thd->is_fatal_error);
|
||||||
|
|
||||||
lex.unit.cleanup();
|
lex.unit.cleanup();
|
||||||
@ -1832,10 +1833,13 @@ event_basic_db_equal(LEX_STRING db, Event_basic *et)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Checks whether two events are equal by identifiers
|
Checks whether an event has equal `db` and `name`
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
event_basic_identifier_equal()
|
event_basic_identifier_equal()
|
||||||
|
db Schema
|
||||||
|
name Name
|
||||||
|
et The event object
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
TRUE Equal
|
TRUE Equal
|
||||||
@ -1851,7 +1855,8 @@ event_basic_identifier_equal(LEX_STRING db, LEX_STRING name, Event_basic *b)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Switches the security context
|
Switches the security context.
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
event_change_security_context()
|
event_change_security_context()
|
||||||
thd Thread
|
thd Thread
|
||||||
@ -1887,7 +1892,8 @@ event_change_security_context(THD *thd, LEX_STRING user, LEX_STRING host,
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Restores the security context
|
Restores the security context.
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
event_restore_security_context()
|
event_restore_security_context()
|
||||||
thd Thread
|
thd Thread
|
||||||
|
@ -237,7 +237,7 @@ public:
|
|||||||
new_instance(THD *thd);
|
new_instance(THD *thd);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
check_parse_data(THD *);
|
check_parse_data(THD *thd);
|
||||||
|
|
||||||
void
|
void
|
||||||
init_body(THD *thd);
|
init_body(THD *thd);
|
||||||
|
@ -22,14 +22,12 @@
|
|||||||
#include "sp.h"
|
#include "sp.h"
|
||||||
#include "sp_head.h"
|
#include "sp_head.h"
|
||||||
|
|
||||||
#define EVEX_DB_FIELD_LEN 64
|
|
||||||
#define EVEX_NAME_FIELD_LEN 64
|
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
time_t mysql_event_last_create_time= 0L;
|
time_t mysql_event_last_create_time= 0L;
|
||||||
|
|
||||||
static
|
static
|
||||||
TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] =
|
TABLE_FIELD_W_TYPE const event_table_fields[ET_FIELD_COUNT] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
{(char *) STRING_WITH_LEN("db")},
|
{(char *) STRING_WITH_LEN("db")},
|
||||||
@ -250,18 +248,18 @@ err_truncate:
|
|||||||
/*
|
/*
|
||||||
Performs an index scan of event_table (mysql.event) and fills schema_table.
|
Performs an index scan of event_table (mysql.event) and fills schema_table.
|
||||||
|
|
||||||
Synopsis
|
SYNOPSIS
|
||||||
Event_db_repository::index_read_for_db_for_i_s()
|
Event_db_repository::index_read_for_db_for_i_s()
|
||||||
thd Thread
|
thd Thread
|
||||||
schema_table The I_S.EVENTS table
|
schema_table The I_S.EVENTS table
|
||||||
event_table The event table to use for loading (mysql.event)
|
event_table The event table to use for loading (mysql.event)
|
||||||
|
|
||||||
Returns
|
RETURN VALUE
|
||||||
0 OK
|
0 OK
|
||||||
1 Error
|
1 Error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
bool
|
||||||
Event_db_repository::index_read_for_db_for_i_s(THD *thd, TABLE *schema_table,
|
Event_db_repository::index_read_for_db_for_i_s(THD *thd, TABLE *schema_table,
|
||||||
TABLE *event_table, char *db)
|
TABLE *event_table, char *db)
|
||||||
{
|
{
|
||||||
@ -305,33 +303,34 @@ Event_db_repository::index_read_for_db_for_i_s(THD *thd, TABLE *schema_table,
|
|||||||
event_table->file->ha_index_end();
|
event_table->file->ha_index_end();
|
||||||
/* ret is guaranteed to be != 0 */
|
/* ret is guaranteed to be != 0 */
|
||||||
if (ret == HA_ERR_END_OF_FILE || ret == HA_ERR_KEY_NOT_FOUND)
|
if (ret == HA_ERR_END_OF_FILE || ret == HA_ERR_KEY_NOT_FOUND)
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(FALSE);
|
||||||
DBUG_RETURN(1);
|
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Performs a table scan of event_table (mysql.event) and fills schema_table.
|
Performs a table scan of event_table (mysql.event) and fills schema_table.
|
||||||
|
|
||||||
Synopsis
|
SYNOPSIS
|
||||||
Events_db_repository::table_scan_all_for_i_s()
|
Events_db_repository::table_scan_all_for_i_s()
|
||||||
thd Thread
|
thd Thread
|
||||||
schema_table The I_S.EVENTS in memory table
|
schema_table The I_S.EVENTS in memory table
|
||||||
event_table The event table to use for loading.
|
event_table The event table to use for loading.
|
||||||
|
|
||||||
Returns
|
RETURN VALUE
|
||||||
0 OK
|
FALSE OK
|
||||||
1 Error
|
TRUE Error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
bool
|
||||||
Event_db_repository::table_scan_all_for_i_s(THD *thd, TABLE *schema_table,
|
Event_db_repository::table_scan_all_for_i_s(THD *thd, TABLE *schema_table,
|
||||||
TABLE *event_table)
|
TABLE *event_table)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
READ_RECORD read_record_info;
|
READ_RECORD read_record_info;
|
||||||
|
|
||||||
DBUG_ENTER("Event_db_repository::table_scan_all_for_i_s");
|
DBUG_ENTER("Event_db_repository::table_scan_all_for_i_s");
|
||||||
|
|
||||||
init_read_record(&read_record_info, thd, event_table, NULL, 1, 0);
|
init_read_record(&read_record_info, thd, event_table, NULL, 1, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -350,7 +349,7 @@ Event_db_repository::table_scan_all_for_i_s(THD *thd, TABLE *schema_table,
|
|||||||
end_read_record(&read_record_info);
|
end_read_record(&read_record_info);
|
||||||
|
|
||||||
/* ret is guaranteed to be != 0 */
|
/* ret is guaranteed to be != 0 */
|
||||||
DBUG_RETURN(ret == -1? 0:1);
|
DBUG_RETURN(ret == -1? FALSE:TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -358,15 +357,15 @@ Event_db_repository::table_scan_all_for_i_s(THD *thd, TABLE *schema_table,
|
|||||||
Fills I_S.EVENTS with data loaded from mysql.event. Also used by
|
Fills I_S.EVENTS with data loaded from mysql.event. Also used by
|
||||||
SHOW EVENTS
|
SHOW EVENTS
|
||||||
|
|
||||||
Synopsis
|
SYNOPSIS
|
||||||
Event_db_repository::fill_schema_events()
|
Event_db_repository::fill_schema_events()
|
||||||
thd Thread
|
thd Thread
|
||||||
tables The schema table
|
tables The schema table
|
||||||
db If not NULL then get events only from this schema
|
db If not NULL then get events only from this schema
|
||||||
|
|
||||||
Returns
|
RETURN VALUE
|
||||||
0 OK
|
FALSE OK
|
||||||
1 Error
|
TRUE Error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -459,12 +458,12 @@ Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type,
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
check_parse_params()
|
check_parse_params()
|
||||||
thd THD
|
thd Thread context
|
||||||
et event's data
|
parse_data Event's data
|
||||||
|
|
||||||
RETURNS
|
RETURN VALUE
|
||||||
0 OK
|
FALSE OK
|
||||||
EVEX_BAD_PARAMS Error (reported)
|
TRUE Error (reported)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -504,7 +503,7 @@ check_parse_params(THD *thd, Event_parse_data *parse_data)
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
Event_db_repository::create_event()
|
Event_db_repository::create_event()
|
||||||
thd [in] THD
|
thd [in] THD
|
||||||
et [in] Object containing info about the event
|
parse_data [in] Object containing info about the event
|
||||||
create_if_not [in] Whether to generate anwarning in case event exists
|
create_if_not [in] Whether to generate anwarning in case event exists
|
||||||
rows_affected [out] How many rows were affected
|
rows_affected [out] How many rows were affected
|
||||||
|
|
||||||
@ -517,7 +516,7 @@ check_parse_params(THD *thd, Event_parse_data *parse_data)
|
|||||||
::update_event. The name of the event is inside "et".
|
::update_event. The name of the event is inside "et".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
bool
|
||||||
Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
|
Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
|
||||||
my_bool create_if_not, uint *rows_affected)
|
my_bool create_if_not, uint *rows_affected)
|
||||||
{
|
{
|
||||||
@ -531,6 +530,9 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
|
|||||||
DBUG_ENTER("Event_db_repository::create_event");
|
DBUG_ENTER("Event_db_repository::create_event");
|
||||||
|
|
||||||
*rows_affected= 0;
|
*rows_affected= 0;
|
||||||
|
if (check_parse_params(thd, parse_data))
|
||||||
|
goto err;
|
||||||
|
|
||||||
DBUG_PRINT("info", ("open mysql.event for update"));
|
DBUG_PRINT("info", ("open mysql.event for update"));
|
||||||
if (open_event_table(thd, TL_WRITE, &table))
|
if (open_event_table(thd, TL_WRITE, &table))
|
||||||
{
|
{
|
||||||
@ -538,8 +540,6 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_parse_params(thd, parse_data))
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
DBUG_PRINT("info", ("name: %.*s", parse_data->name.length,
|
DBUG_PRINT("info", ("name: %.*s", parse_data->name.length,
|
||||||
parse_data->name.str));
|
parse_data->name.str));
|
||||||
@ -570,16 +570,17 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
|
|||||||
|
|
||||||
if (system_charset_info->cset->
|
if (system_charset_info->cset->
|
||||||
numchars(system_charset_info, parse_data->dbname.str,
|
numchars(system_charset_info, parse_data->dbname.str,
|
||||||
parse_data->dbname.str +
|
parse_data->dbname.str + parse_data->dbname.length) >
|
||||||
parse_data->dbname.length) > EVEX_DB_FIELD_LEN)
|
table->field[ET_FIELD_DB]->char_length())
|
||||||
{
|
{
|
||||||
my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->dbname.str);
|
my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->dbname.str);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (system_charset_info->cset->
|
if (system_charset_info->cset->
|
||||||
numchars(system_charset_info, parse_data->name.str,
|
numchars(system_charset_info, parse_data->name.str,
|
||||||
parse_data->name.str +
|
parse_data->name.str + parse_data->name.length) >
|
||||||
parse_data->name.length) > EVEX_DB_FIELD_LEN)
|
table->field[ET_FIELD_NAME]->char_length())
|
||||||
{
|
{
|
||||||
my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->name.str);
|
my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->name.str);
|
||||||
goto err;
|
goto err;
|
||||||
@ -622,36 +623,18 @@ ok:
|
|||||||
if (dbchanged)
|
if (dbchanged)
|
||||||
(void) mysql_change_db(thd, old_db.str, 1);
|
(void) mysql_change_db(thd, old_db.str, 1);
|
||||||
/*
|
/*
|
||||||
When valgrinded, the following call may lead to the following error:
|
This statement may cause a spooky valgrind warning at startup
|
||||||
|
inside init_key_cache on my system (ahristov, 2006/08/10)
|
||||||
Syscall param pwrite64(buf) points to uninitialised byte(s)
|
|
||||||
at 0x406003B: do_pwrite64 (in /lib/tls/libpthread.so.0)
|
|
||||||
by 0x40600EF: pwrite64 (in /lib/tls/libpthread.so.0)
|
|
||||||
by 0x856FF74: my_pwrite (my_pread.c:146)
|
|
||||||
by 0x85734E1: flush_cached_blocks (mf_keycache.c:2280)
|
|
||||||
....
|
|
||||||
Address 0x6618110 is 56 bytes inside a block of size 927,772 alloc'd
|
|
||||||
at 0x401C451: malloc (vg_replace_malloc.c:149)
|
|
||||||
by 0x8578CDC: _mymalloc (safemalloc.c:138)
|
|
||||||
by 0x858E5E2: my_large_malloc (my_largepage.c:65)
|
|
||||||
by 0x8570634: init_key_cache (mf_keycache.c:343)
|
|
||||||
by 0x82EDA51: ha_init_key_cache(char const*, st_key_cache*) (handler.cc:2509)
|
|
||||||
by 0x8212071: process_key_caches(int (*)(char const*, st_key_cache*))
|
|
||||||
(set_var.cc:3824)
|
|
||||||
by 0x8206D75: init_server_components() (mysqld.cc:3304)
|
|
||||||
by 0x8207163: main (mysqld.cc:3578)
|
|
||||||
|
|
||||||
I think it is safe not to think about it.
|
|
||||||
*/
|
*/
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(FALSE);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (dbchanged)
|
if (dbchanged)
|
||||||
(void) mysql_change_db(thd, old_db.str, 1);
|
(void) mysql_change_db(thd, old_db.str, 1);
|
||||||
if (table)
|
if (table)
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
DBUG_RETURN(EVEX_GENERAL_ERROR);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -665,8 +648,8 @@ err:
|
|||||||
et event's data
|
et event's data
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
0 OK
|
FALSE OK
|
||||||
EVEX_GENERAL_ERROR Error occured and reported
|
TRUE Error (reported)
|
||||||
|
|
||||||
NOTES
|
NOTES
|
||||||
sp_name is passed since this is the name of the event to
|
sp_name is passed since this is the name of the event to
|
||||||
@ -679,7 +662,6 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
|
|||||||
{
|
{
|
||||||
CHARSET_INFO *scs= system_charset_info;
|
CHARSET_INFO *scs= system_charset_info;
|
||||||
TABLE *table= NULL;
|
TABLE *table= NULL;
|
||||||
int ret;
|
|
||||||
DBUG_ENTER("Event_db_repository::update_event");
|
DBUG_ENTER("Event_db_repository::update_event");
|
||||||
|
|
||||||
if (open_event_table(thd, TL_WRITE, &table))
|
if (open_event_table(thd, TL_WRITE, &table))
|
||||||
@ -698,7 +680,7 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
|
|||||||
DBUG_PRINT("info", ("rename to: %s@%s", new_dbname->str, new_name->str));
|
DBUG_PRINT("info", ("rename to: %s@%s", new_dbname->str, new_name->str));
|
||||||
|
|
||||||
/* first look whether we overwrite */
|
/* first look whether we overwrite */
|
||||||
if (new_dbname)
|
if (new_name)
|
||||||
{
|
{
|
||||||
if (!sortcmp_lex_string(parse_data->name, *new_name, scs) &&
|
if (!sortcmp_lex_string(parse_data->name, *new_name, scs) &&
|
||||||
!sortcmp_lex_string(parse_data->dbname, *new_dbname, scs))
|
!sortcmp_lex_string(parse_data->dbname, *new_dbname, scs))
|
||||||
@ -747,9 +729,10 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
|
|||||||
if (end_active_trans(thd))
|
if (end_active_trans(thd))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (table->file->ha_update_row(table->record[1], table->record[0]))
|
int res;
|
||||||
|
if ((res= table->file->ha_update_row(table->record[1], table->record[0])))
|
||||||
{
|
{
|
||||||
my_error(ER_EVENT_STORE_FAILED, MYF(0), parse_data->name.str, ret);
|
my_error(ER_EVENT_STORE_FAILED, MYF(0), parse_data->name.str, res);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -887,16 +870,14 @@ Event_db_repository::find_named_event(THD *thd, LEX_STRING db, LEX_STRING name,
|
|||||||
Event_db_repository::drop_schema_events()
|
Event_db_repository::drop_schema_events()
|
||||||
thd Thread
|
thd Thread
|
||||||
schema The database to clean from events
|
schema The database to clean from events
|
||||||
|
|
||||||
RETURN VALUE
|
|
||||||
0 OK
|
|
||||||
!0 Error (Reported)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
void
|
||||||
Event_db_repository::drop_schema_events(THD *thd, LEX_STRING schema)
|
Event_db_repository::drop_schema_events(THD *thd, LEX_STRING schema)
|
||||||
{
|
{
|
||||||
return drop_events_by_field(thd, ET_FIELD_DB, schema);
|
DBUG_ENTER("Event_db_repository::drop_schema_events");
|
||||||
|
drop_events_by_field(thd, ET_FIELD_DB, schema);
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -909,28 +890,29 @@ Event_db_repository::drop_schema_events(THD *thd, LEX_STRING schema)
|
|||||||
table mysql.event TABLE
|
table mysql.event TABLE
|
||||||
field Which field of the row to use for matching
|
field Which field of the row to use for matching
|
||||||
field_value The value that should match
|
field_value The value that should match
|
||||||
|
|
||||||
RETURN VALUE
|
|
||||||
0 OK
|
|
||||||
!0 Error from ha_delete_row
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
void
|
||||||
Event_db_repository::drop_events_by_field(THD *thd,
|
Event_db_repository::drop_events_by_field(THD *thd,
|
||||||
enum enum_events_table_field field,
|
enum enum_events_table_field field,
|
||||||
LEX_STRING field_value)
|
LEX_STRING field_value)
|
||||||
{
|
{
|
||||||
int ret= 0;
|
int ret= 0;
|
||||||
TABLE *table= NULL;
|
TABLE *table= NULL;
|
||||||
Open_tables_state backup;
|
|
||||||
READ_RECORD read_record_info;
|
READ_RECORD read_record_info;
|
||||||
DBUG_ENTER("Event_db_repository::drop_events_by_field");
|
DBUG_ENTER("Event_db_repository::drop_events_by_field");
|
||||||
DBUG_PRINT("enter", ("field=%d field_value=%s", field, field_value.str));
|
DBUG_PRINT("enter", ("field=%d field_value=%s", field, field_value.str));
|
||||||
|
|
||||||
if (open_event_table(thd, TL_WRITE, &table))
|
if (open_event_table(thd, TL_WRITE, &table))
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Currently being used only for DROP DATABASE - In this case we don't need
|
||||||
|
error message since the OK packet has been sent. But for DROP USER we
|
||||||
|
could need it.
|
||||||
|
|
||||||
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
|
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
|
||||||
DBUG_RETURN(1);
|
*/
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* only enabled events are in memory, so we go now and delete the rest */
|
/* only enabled events are in memory, so we go now and delete the rest */
|
||||||
@ -939,22 +921,20 @@ Event_db_repository::drop_events_by_field(THD *thd,
|
|||||||
{
|
{
|
||||||
char *et_field= get_field(thd->mem_root, table->field[field]);
|
char *et_field= get_field(thd->mem_root, table->field[field]);
|
||||||
|
|
||||||
LEX_STRING et_field_lex= {et_field, strlen(et_field)};
|
LEX_STRING et_field_lex= { et_field, strlen(et_field) };
|
||||||
DBUG_PRINT("info", ("Current event %s name=%s", et_field,
|
DBUG_PRINT("info", ("Current event %s name=%s", et_field,
|
||||||
get_field(thd->mem_root, table->field[ET_FIELD_NAME])));
|
get_field(thd->mem_root, table->field[ET_FIELD_NAME])));
|
||||||
|
|
||||||
if (!sortcmp_lex_string(et_field_lex, field_value, system_charset_info))
|
if (!sortcmp_lex_string(et_field_lex, field_value, system_charset_info))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("Dropping"));
|
DBUG_PRINT("info", ("Dropping"));
|
||||||
if ((ret= table->file->ha_delete_row(table->record[0])))
|
ret= table->file->ha_delete_row(table->record[0]);
|
||||||
my_error(ER_EVENT_DROP_FAILED, MYF(0),
|
|
||||||
get_field(thd->mem_root, table->field[ET_FIELD_NAME]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end_read_record(&read_record_info);
|
end_read_record(&read_record_info);
|
||||||
thd->version--; /* Force close to free memory */
|
close_thread_tables(thd);
|
||||||
|
|
||||||
DBUG_RETURN(ret);
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -964,10 +944,10 @@ Event_db_repository::drop_events_by_field(THD *thd,
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
Event_db_repository::load_named_event()
|
Event_db_repository::load_named_event()
|
||||||
thd [in] THD
|
thd [in] Thread context
|
||||||
dbname [in] Event's db name
|
dbname [in] Event's db name
|
||||||
name [in] Event's name
|
name [in] Event's name
|
||||||
etn_new [out] The loaded event
|
etn [out] The loaded event
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
FALSE OK
|
FALSE OK
|
||||||
|
@ -47,9 +47,6 @@ events_table_index_read_for_db(THD *thd, TABLE *schema_table,
|
|||||||
int
|
int
|
||||||
events_table_scan_all(THD *thd, TABLE *schema_table, TABLE *event_table);
|
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_basic;
|
class Event_basic;
|
||||||
class Event_parse_data;
|
class Event_parse_data;
|
||||||
|
|
||||||
@ -58,7 +55,7 @@ class Event_db_repository
|
|||||||
public:
|
public:
|
||||||
Event_db_repository(){}
|
Event_db_repository(){}
|
||||||
|
|
||||||
int
|
bool
|
||||||
create_event(THD *thd, Event_parse_data *parse_data, 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);
|
||||||
|
|
||||||
@ -70,7 +67,7 @@ public:
|
|||||||
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,
|
||||||
uint *rows_affected);
|
uint *rows_affected);
|
||||||
|
|
||||||
int
|
void
|
||||||
drop_schema_events(THD *thd, LEX_STRING schema);
|
drop_schema_events(THD *thd, LEX_STRING schema);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -79,7 +76,6 @@ public:
|
|||||||
bool
|
bool
|
||||||
load_named_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_basic *et);
|
load_named_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_basic *et);
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
|
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
|
||||||
|
|
||||||
@ -87,14 +83,14 @@ public:
|
|||||||
fill_schema_events(THD *thd, TABLE_LIST *tables, char *db);
|
fill_schema_events(THD *thd, TABLE_LIST *tables, char *db);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int
|
void
|
||||||
drop_events_by_field(THD *thd, enum enum_events_table_field field,
|
drop_events_by_field(THD *thd, enum enum_events_table_field field,
|
||||||
LEX_STRING field_value);
|
LEX_STRING field_value);
|
||||||
int
|
bool
|
||||||
index_read_for_db_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table,
|
index_read_for_db_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table,
|
||||||
char *db);
|
char *db);
|
||||||
|
|
||||||
int
|
bool
|
||||||
table_scan_all_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table);
|
table_scan_all_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table);
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -73,35 +73,6 @@ event_queue_element_compare_q(void *vptr, byte* a, byte *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pthread_handler_t
|
|
||||||
event_queue_loader_thread(void *arg)
|
|
||||||
{
|
|
||||||
/* needs to be first for thread_stack */
|
|
||||||
THD *thd= (THD *)((struct event_queue_param *) arg)->thd;
|
|
||||||
struct event_queue_param *param= (struct event_queue_param *) arg;
|
|
||||||
thd->thread_stack= (char *) &thd;
|
|
||||||
|
|
||||||
if (post_init_event_thread(thd))
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
DBUG_ENTER("event_queue_loader_thread");
|
|
||||||
|
|
||||||
|
|
||||||
pthread_mutex_lock(¶m->LOCK_loaded);
|
|
||||||
param->queue->check_system_tables(thd);
|
|
||||||
param->queue->load_events_from_db(thd);
|
|
||||||
|
|
||||||
param->loading_finished= TRUE;
|
|
||||||
pthread_cond_signal(¶m->COND_loaded);
|
|
||||||
|
|
||||||
pthread_mutex_unlock(¶m->LOCK_loaded);
|
|
||||||
|
|
||||||
end:
|
|
||||||
deinit_event_thread(thd);
|
|
||||||
DBUG_RETURN(0); // Against gcc warnings
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Constructor of class Event_queue.
|
Constructor of class Event_queue.
|
||||||
|
|
||||||
@ -110,14 +81,12 @@ end:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Event_queue::Event_queue()
|
Event_queue::Event_queue()
|
||||||
|
:mutex_last_unlocked_at_line(0), mutex_last_locked_at_line(0),
|
||||||
|
mutex_last_attempted_lock_at_line(0),
|
||||||
|
mutex_queue_data_locked(FALSE), mutex_queue_data_attempting_lock(FALSE)
|
||||||
{
|
{
|
||||||
mutex_last_unlocked_at_line= mutex_last_locked_at_line=
|
|
||||||
mutex_last_attempted_lock_at_line= 0;
|
|
||||||
|
|
||||||
mutex_last_unlocked_in_func= mutex_last_locked_in_func=
|
mutex_last_unlocked_in_func= mutex_last_locked_in_func=
|
||||||
mutex_last_attempted_lock_in_func= "";
|
mutex_last_attempted_lock_in_func= "";
|
||||||
|
|
||||||
mutex_queue_data_locked= mutex_queue_data_attempting_lock= FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -150,7 +119,12 @@ Event_queue::deinit_mutexes()
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Inits the queue
|
This is a queue's constructor. Until this method is called, the
|
||||||
|
queue is unusable. We don't use a C++ constructor instead in
|
||||||
|
order to be able to check the return value. The queue is
|
||||||
|
initialized once at server startup. Initialization can fail in
|
||||||
|
case of a failure reading events from the database or out of
|
||||||
|
memory.
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
Event_queue::init()
|
Event_queue::init()
|
||||||
@ -161,9 +135,9 @@ Event_queue::deinit_mutexes()
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Event_queue::init_queue(Event_db_repository *db_repo, Event_scheduler *sched)
|
Event_queue::init_queue(THD *thd, Event_db_repository *db_repo,
|
||||||
|
Event_scheduler *sched)
|
||||||
{
|
{
|
||||||
THD *new_thd;
|
|
||||||
pthread_t th;
|
pthread_t th;
|
||||||
bool res;
|
bool res;
|
||||||
struct event_queue_param *event_queue_param_value= NULL;
|
struct event_queue_param *event_queue_param_value= NULL;
|
||||||
@ -186,43 +160,16 @@ Event_queue::init_queue(Event_db_repository *db_repo, Event_scheduler *sched)
|
|||||||
if (sizeof(my_time_t) != sizeof(time_t))
|
if (sizeof(my_time_t) != sizeof(time_t))
|
||||||
{
|
{
|
||||||
sql_print_error("SCHEDULER: sizeof(my_time_t) != sizeof(time_t) ."
|
sql_print_error("SCHEDULER: sizeof(my_time_t) != sizeof(time_t) ."
|
||||||
"The scheduler may not work correctly. Stopping.");
|
"The scheduler may not work correctly. Stopping");
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(new_thd= new THD))
|
res= load_events_from_db(thd);
|
||||||
goto err;
|
|
||||||
|
|
||||||
pre_init_event_thread(new_thd);
|
|
||||||
new_thd->security_ctx->set_user((char*)"event_scheduler_loader");
|
|
||||||
|
|
||||||
event_queue_param_value= (struct event_queue_param *)
|
|
||||||
my_malloc(sizeof(struct event_queue_param), MYF(0));
|
|
||||||
|
|
||||||
event_queue_param_value->thd= new_thd;
|
|
||||||
event_queue_param_value->queue= this;
|
|
||||||
event_queue_param_value->loading_finished= FALSE;
|
|
||||||
pthread_mutex_init(&event_queue_param_value->LOCK_loaded, MY_MUTEX_INIT_FAST);
|
|
||||||
pthread_cond_init(&event_queue_param_value->COND_loaded, NULL);
|
|
||||||
|
|
||||||
pthread_mutex_lock(&event_queue_param_value->LOCK_loaded);
|
|
||||||
DBUG_PRINT("info", ("Forking new thread for scheduduler. THD=0x%lx", new_thd));
|
|
||||||
if (!(res= pthread_create(&th, &connection_attrib, event_queue_loader_thread,
|
|
||||||
(void*)event_queue_param_value)))
|
|
||||||
{
|
|
||||||
do {
|
|
||||||
pthread_cond_wait(&event_queue_param_value->COND_loaded,
|
|
||||||
&event_queue_param_value->LOCK_loaded);
|
|
||||||
} while (event_queue_param_value->loading_finished == FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&event_queue_param_value->LOCK_loaded);
|
|
||||||
pthread_mutex_destroy(&event_queue_param_value->LOCK_loaded);
|
|
||||||
pthread_cond_destroy(&event_queue_param_value->COND_loaded);
|
|
||||||
my_free((char *)event_queue_param_value, MYF(0));
|
|
||||||
|
|
||||||
UNLOCK_QUEUE_DATA();
|
UNLOCK_QUEUE_DATA();
|
||||||
|
if (res)
|
||||||
|
deinit_queue();
|
||||||
|
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
@ -316,16 +263,15 @@ Event_queue::update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
|
|||||||
LEX_STRING *new_schema, LEX_STRING *new_name)
|
LEX_STRING *new_schema, LEX_STRING *new_name)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
Event_queue_element *old_element= NULL,
|
Event_queue_element *new_element;
|
||||||
*new_element;
|
|
||||||
|
|
||||||
DBUG_ENTER("Event_queue::update_event");
|
DBUG_ENTER("Event_queue::update_event");
|
||||||
DBUG_PRINT("enter", ("thd=0x%lx et=[%s.%s]", thd, dbname.str, name.str));
|
DBUG_PRINT("enter", ("thd=0x%lx et=[%s.%s]", thd, dbname.str, name.str));
|
||||||
|
|
||||||
new_element= new Event_queue_element();
|
new_element= new Event_queue_element();
|
||||||
|
|
||||||
res= db_repository->load_named_event(thd, new_schema? *new_schema:dbname,
|
res= db_repository->load_named_event(thd, new_schema ? *new_schema:dbname,
|
||||||
new_name? *new_name:name, new_element);
|
new_name ? *new_name:name, new_element);
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
delete new_element;
|
delete new_element;
|
||||||
@ -345,16 +291,12 @@ Event_queue::update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
|
|||||||
new_element->compute_next_execution_time();
|
new_element->compute_next_execution_time();
|
||||||
|
|
||||||
LOCK_QUEUE_DATA();
|
LOCK_QUEUE_DATA();
|
||||||
if (!(old_element= find_n_remove_event(dbname, name)))
|
find_n_remove_event(dbname, name);
|
||||||
{
|
|
||||||
DBUG_PRINT("info", ("%s.%s not cached, probably was DISABLED",
|
|
||||||
dbname.str, name.str));
|
|
||||||
}
|
|
||||||
/* If not disabled event */
|
/* If not disabled event */
|
||||||
if (new_element)
|
if (new_element)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("new event in the Q 0x%lx old 0x%lx",
|
DBUG_PRINT("info", ("new event in the Q 0x%lx", new_element));
|
||||||
new_element, old_element));
|
|
||||||
queue_insert_safe(&queue, (byte *) new_element);
|
queue_insert_safe(&queue, (byte *) new_element);
|
||||||
}
|
}
|
||||||
dbug_dump_queue(thd->query_start());
|
dbug_dump_queue(thd->query_start());
|
||||||
@ -363,8 +305,6 @@ Event_queue::update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
|
|||||||
if (new_element)
|
if (new_element)
|
||||||
notify_observers();
|
notify_observers();
|
||||||
|
|
||||||
if (old_element)
|
|
||||||
delete old_element;
|
|
||||||
end:
|
end:
|
||||||
DBUG_PRINT("info", ("res=%d", res));
|
DBUG_PRINT("info", ("res=%d", res));
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
@ -385,20 +325,14 @@ void
|
|||||||
Event_queue::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
|
Event_queue::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
Event_queue_element *element;
|
|
||||||
DBUG_ENTER("Event_queue::drop_event");
|
DBUG_ENTER("Event_queue::drop_event");
|
||||||
DBUG_PRINT("enter", ("thd=0x%lx name=0x%lx", thd, name));
|
DBUG_PRINT("enter", ("thd=0x%lx name=0x%lx", thd, name));
|
||||||
|
|
||||||
LOCK_QUEUE_DATA();
|
LOCK_QUEUE_DATA();
|
||||||
element= find_n_remove_event(dbname, name);
|
find_n_remove_event(dbname, name);
|
||||||
dbug_dump_queue(thd->query_start());
|
dbug_dump_queue(thd->query_start());
|
||||||
UNLOCK_QUEUE_DATA();
|
UNLOCK_QUEUE_DATA();
|
||||||
|
|
||||||
if (element)
|
|
||||||
delete element;
|
|
||||||
else
|
|
||||||
DBUG_PRINT("info", ("No such event found, probably DISABLED"));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We don't signal here because the scheduler will catch the change
|
We don't signal here because the scheduler will catch the change
|
||||||
next time it wakes up.
|
next time it wakes up.
|
||||||
@ -429,10 +363,10 @@ void
|
|||||||
Event_queue::drop_matching_events(THD *thd, LEX_STRING pattern,
|
Event_queue::drop_matching_events(THD *thd, LEX_STRING pattern,
|
||||||
bool (*comparator)(LEX_STRING, Event_basic *))
|
bool (*comparator)(LEX_STRING, Event_basic *))
|
||||||
{
|
{
|
||||||
|
uint i= 0;
|
||||||
DBUG_ENTER("Event_queue::drop_matching_events");
|
DBUG_ENTER("Event_queue::drop_matching_events");
|
||||||
DBUG_PRINT("enter", ("pattern=%s", pattern.str));
|
DBUG_PRINT("enter", ("pattern=%s", pattern.str));
|
||||||
|
|
||||||
uint i= 0;
|
|
||||||
while (i < queue.elements)
|
while (i < queue.elements)
|
||||||
{
|
{
|
||||||
Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i);
|
Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i);
|
||||||
@ -440,10 +374,10 @@ Event_queue::drop_matching_events(THD *thd, LEX_STRING pattern,
|
|||||||
if (comparator(pattern, et))
|
if (comparator(pattern, et))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
The queue is ordered. If we remove an element, then all elements after
|
The queue is ordered. If we remove an element, then all elements
|
||||||
it will shift one position to the left, if we imagine it as an array
|
after it will shift one position to the left, if we imagine it as
|
||||||
from left to the right. In this case we should not increment the
|
an array from left to the right. In this case we should not
|
||||||
counter and the (i < queue.elements) condition is ok.
|
increment the counter and the (i < queue.elements) condition is ok.
|
||||||
*/
|
*/
|
||||||
queue_remove(&queue, i);
|
queue_remove(&queue, i);
|
||||||
delete et;
|
delete et;
|
||||||
@ -453,12 +387,12 @@ Event_queue::drop_matching_events(THD *thd, LEX_STRING pattern,
|
|||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
We don't call notify_observers() . If we remove the top event:
|
We don't call notify_observers() . If we remove the top event:
|
||||||
1. The queue is empty. The scheduler will wake up at some time and realize
|
1. The queue is empty. The scheduler will wake up at some time and
|
||||||
that the queue is empty. If create_event() comes inbetween it will
|
realize that the queue is empty. If create_event() comes inbetween
|
||||||
signal the scheduler
|
it will signal the scheduler
|
||||||
2. The queue is not empty, but the next event after the previous top, won't
|
2. The queue is not empty, but the next event after the previous top,
|
||||||
be executed any time sooner than the element we removed. Hence, we may
|
won't be executed any time sooner than the element we removed. Hence,
|
||||||
not notify the scheduler and it will realize the change when it
|
we may not notify the scheduler and it will realize the change when it
|
||||||
wakes up from timedwait.
|
wakes up from timedwait.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -472,11 +406,8 @@ Event_queue::drop_matching_events(THD *thd, LEX_STRING pattern,
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
Event_queue::drop_schema_events()
|
Event_queue::drop_schema_events()
|
||||||
thd THD
|
thd HD
|
||||||
db The schema name
|
schema The schema name
|
||||||
|
|
||||||
RETURN VALUE
|
|
||||||
>=0 Number of dropped events
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -516,16 +447,12 @@ Event_queue::notify_observers()
|
|||||||
db The schema of the event to find
|
db The schema of the event to find
|
||||||
name The event to find
|
name The event to find
|
||||||
|
|
||||||
RETURN VALUE
|
|
||||||
NULL Not found
|
|
||||||
otherwise Address
|
|
||||||
|
|
||||||
NOTE
|
NOTE
|
||||||
The caller should do the locking also the caller is responsible for
|
The caller should do the locking also the caller is responsible for
|
||||||
actual signalling in case an event is removed from the queue.
|
actual signalling in case an event is removed from the queue.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Event_queue_element *
|
void
|
||||||
Event_queue::find_n_remove_event(LEX_STRING db, LEX_STRING name)
|
Event_queue::find_n_remove_event(LEX_STRING db, LEX_STRING name)
|
||||||
{
|
{
|
||||||
uint i;
|
uint i;
|
||||||
@ -539,11 +466,12 @@ Event_queue::find_n_remove_event(LEX_STRING db, LEX_STRING name)
|
|||||||
if (event_basic_identifier_equal(db, name, et))
|
if (event_basic_identifier_equal(db, name, et))
|
||||||
{
|
{
|
||||||
queue_remove(&queue, i);
|
queue_remove(&queue, i);
|
||||||
DBUG_RETURN(et);
|
delete et;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_RETURN(NULL);
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -583,7 +511,7 @@ Event_queue::load_events_from_db(THD *thd)
|
|||||||
|
|
||||||
if ((ret= db_repository->open_event_table(thd, TL_READ, &table)))
|
if ((ret= db_repository->open_event_table(thd, TL_READ, &table)))
|
||||||
{
|
{
|
||||||
sql_print_error("SCHEDULER: Table mysql.event is damaged. Can not open.");
|
sql_print_error("SCHEDULER: Table mysql.event is damaged. Can not open");
|
||||||
DBUG_RETURN(EVEX_OPEN_TABLE_FAILED);
|
DBUG_RETURN(EVEX_OPEN_TABLE_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,14 +553,17 @@ Event_queue::load_events_from_db(THD *thd)
|
|||||||
|
|
||||||
temp_job_data.load_from_row(table);
|
temp_job_data.load_from_row(table);
|
||||||
|
|
||||||
/* We load only on scheduler root just to check whether the body compiles */
|
/*
|
||||||
|
We load only on scheduler root just to check whether the body
|
||||||
|
compiles.
|
||||||
|
*/
|
||||||
switch (ret= temp_job_data.compile(thd, thd->mem_root)) {
|
switch (ret= temp_job_data.compile(thd, thd->mem_root)) {
|
||||||
case EVEX_MICROSECOND_UNSUP:
|
case EVEX_MICROSECOND_UNSUP:
|
||||||
sql_print_error("SCHEDULER: mysql.event is tampered. MICROSECOND is not "
|
sql_print_error("SCHEDULER: mysql.event is tampered. MICROSECOND is not "
|
||||||
"supported but found in mysql.event");
|
"supported but found in mysql.event");
|
||||||
break;
|
break;
|
||||||
case EVEX_COMPILE_ERROR:
|
case EVEX_COMPILE_ERROR:
|
||||||
sql_print_error("SCHEDULER: Error while compiling %s.%s. Aborting load.",
|
sql_print_error("SCHEDULER: Error while compiling %s.%s. Aborting load",
|
||||||
et->dbname.str, et->name.str);
|
et->dbname.str, et->name.str);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -663,12 +594,10 @@ end:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret= 0;
|
ret= 0;
|
||||||
sql_print_information("SCHEDULER: Loaded %d event%s", count, (count == 1)?"":"s");
|
sql_print_information("SCHEDULER: Loaded %d event%s", count,
|
||||||
|
(count == 1)?"":"s");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Force close to free memory */
|
|
||||||
thd->version--;
|
|
||||||
|
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
|
|
||||||
DBUG_PRINT("info", ("Status code %d. Loaded %d event(s)", ret, count));
|
DBUG_PRINT("info", ("Status code %d. Loaded %d event(s)", ret, count));
|
||||||
@ -676,71 +605,6 @@ end:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Opens mysql.db and mysql.user and checks whether:
|
|
||||||
1. mysql.db has column Event_priv at column 20 (0 based);
|
|
||||||
2. mysql.user has column Event_priv at column 29 (0 based);
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
Event_queue::check_system_tables()
|
|
||||||
thd Thread
|
|
||||||
|
|
||||||
RETURN VALUE
|
|
||||||
FALSE OK
|
|
||||||
TRUE Error
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
Event_queue::check_system_tables(THD *thd)
|
|
||||||
{
|
|
||||||
TABLE_LIST tables;
|
|
||||||
bool not_used;
|
|
||||||
Open_tables_state backup;
|
|
||||||
bool ret;
|
|
||||||
|
|
||||||
DBUG_ENTER("Event_queue::check_system_tables");
|
|
||||||
DBUG_PRINT("enter", ("thd=0x%lx", thd));
|
|
||||||
|
|
||||||
thd->reset_n_backup_open_tables_state(&backup);
|
|
||||||
|
|
||||||
bzero((char*) &tables, sizeof(tables));
|
|
||||||
tables.db= (char*) "mysql";
|
|
||||||
tables.table_name= tables.alias= (char*) "db";
|
|
||||||
tables.lock_type= TL_READ;
|
|
||||||
|
|
||||||
if ((ret= simple_open_n_lock_tables(thd, &tables)))
|
|
||||||
{
|
|
||||||
sql_print_error("Cannot open mysql.db");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
ret= table_check_intact(tables.table, MYSQL_DB_FIELD_COUNT,
|
|
||||||
mysql_db_table_fields, &mysql_db_table_last_check,
|
|
||||||
ER_CANNOT_LOAD_FROM_TABLE);
|
|
||||||
close_thread_tables(thd);
|
|
||||||
|
|
||||||
bzero((char*) &tables, sizeof(tables));
|
|
||||||
tables.db= (char*) "mysql";
|
|
||||||
tables.table_name= tables.alias= (char*) "user";
|
|
||||||
tables.lock_type= TL_READ;
|
|
||||||
|
|
||||||
if (simple_open_n_lock_tables(thd, &tables))
|
|
||||||
sql_print_error("Cannot open mysql.db");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (tables.table->s->fields < 29 ||
|
|
||||||
strncmp(tables.table->field[29]->field_name,
|
|
||||||
STRING_WITH_LEN("Event_priv")))
|
|
||||||
sql_print_error("mysql.user has no `Event_priv` column at position 29");
|
|
||||||
close_thread_tables(thd);
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
|
||||||
thd->restore_backup_open_tables_state(&backup);
|
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Recalculates activation times in the queue. There is one reason for
|
Recalculates activation times in the queue. There is one reason for
|
||||||
that. Because the values (execute_at) by which the queue is ordered are
|
that. Because the values (execute_at) by which the queue is ordered are
|
||||||
|
@ -36,7 +36,7 @@ public:
|
|||||||
deinit_mutexes();
|
deinit_mutexes();
|
||||||
|
|
||||||
bool
|
bool
|
||||||
init_queue(Event_db_repository *db_repo, Event_scheduler *sched);
|
init_queue(THD *thd, Event_db_repository *db_repo, Event_scheduler *sched);
|
||||||
|
|
||||||
void
|
void
|
||||||
deinit_queue();
|
deinit_queue();
|
||||||
@ -56,9 +56,6 @@ public:
|
|||||||
void
|
void
|
||||||
drop_schema_events(THD *thd, LEX_STRING schema);
|
drop_schema_events(THD *thd, LEX_STRING schema);
|
||||||
|
|
||||||
void
|
|
||||||
check_system_tables(THD *thd);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
recalculate_activation_times(THD *thd);
|
recalculate_activation_times(THD *thd);
|
||||||
|
|
||||||
@ -72,7 +69,7 @@ public:
|
|||||||
load_events_from_db(THD *thd);
|
load_events_from_db(THD *thd);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Event_queue_element *
|
void
|
||||||
find_n_remove_event(LEX_STRING db, LEX_STRING name);
|
find_n_remove_event(LEX_STRING db, LEX_STRING name);
|
||||||
|
|
||||||
|
|
||||||
|
@ -384,7 +384,7 @@ Event_scheduler::start()
|
|||||||
|
|
||||||
if (!(new_thd= new THD))
|
if (!(new_thd= new THD))
|
||||||
{
|
{
|
||||||
sql_print_error("SCHEDULER: Cannot init manager event thread.");
|
sql_print_error("SCHEDULER: Cannot init manager event thread");
|
||||||
ret= TRUE;
|
ret= TRUE;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
@ -441,7 +441,7 @@ end:
|
|||||||
bool
|
bool
|
||||||
Event_scheduler::run(THD *thd)
|
Event_scheduler::run(THD *thd)
|
||||||
{
|
{
|
||||||
int res;
|
int res= FALSE;
|
||||||
struct timespec abstime;
|
struct timespec abstime;
|
||||||
Event_job_data *job_data;
|
Event_job_data *job_data;
|
||||||
DBUG_ENTER("Event_scheduler::run");
|
DBUG_ENTER("Event_scheduler::run");
|
||||||
@ -464,7 +464,7 @@ Event_scheduler::run(THD *thd)
|
|||||||
&job_data, &abstime))
|
&job_data, &abstime))
|
||||||
{
|
{
|
||||||
sql_print_information("SCHEDULER: Serious error during getting next"
|
sql_print_information("SCHEDULER: Serious error during getting next"
|
||||||
" event to execute. Stopping.");
|
" event to execute. Stopping");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -532,7 +532,7 @@ Event_scheduler::execute_top(THD *thd, Event_job_data *job_data)
|
|||||||
pthread_t th;
|
pthread_t th;
|
||||||
int res= 0;
|
int res= 0;
|
||||||
DBUG_ENTER("Event_scheduler::execute_top");
|
DBUG_ENTER("Event_scheduler::execute_top");
|
||||||
if (!(new_thd= new THD))
|
if (!(new_thd= new THD()))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
pre_init_event_thread(new_thd);
|
pre_init_event_thread(new_thd);
|
||||||
|
@ -31,12 +31,13 @@ deinit_event_thread(THD *thd);
|
|||||||
class Event_scheduler
|
class Event_scheduler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Event_scheduler(){}
|
Event_scheduler():state(UNINITIALIZED){}
|
||||||
~Event_scheduler(){}
|
~Event_scheduler(){}
|
||||||
|
|
||||||
enum enum_state
|
enum enum_state
|
||||||
{
|
{
|
||||||
INITIALIZED = 0,
|
UNINITIALIZED = 0,
|
||||||
|
INITIALIZED,
|
||||||
RUNNING,
|
RUNNING,
|
||||||
STOPPING
|
STOPPING
|
||||||
};
|
};
|
||||||
|
270
sql/events.cc
270
sql/events.cc
@ -70,6 +70,15 @@ TYPELIB Events::opt_typelib=
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static
|
||||||
|
Event_queue events_event_queue;
|
||||||
|
|
||||||
|
static
|
||||||
|
Event_scheduler events_event_scheduler;
|
||||||
|
|
||||||
|
static
|
||||||
|
Event_db_repository events_event_db_repository;
|
||||||
|
|
||||||
Events Events::singleton;
|
Events Events::singleton;
|
||||||
|
|
||||||
ulong Events::opt_event_scheduler= 2;
|
ulong Events::opt_event_scheduler= 2;
|
||||||
@ -247,6 +256,22 @@ common_1_lev_code:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Constructor of Events class. It's called when events.o
|
||||||
|
is loaded. Assigning addressed of static variables in this
|
||||||
|
object file.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
Events::Events()
|
||||||
|
*/
|
||||||
|
|
||||||
|
Events::Events()
|
||||||
|
{
|
||||||
|
scheduler= &events_event_scheduler;
|
||||||
|
event_queue= &events_event_queue;
|
||||||
|
db_repository= &events_event_db_repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Opens mysql.event table with specified lock
|
Opens mysql.event table with specified lock
|
||||||
@ -277,25 +302,30 @@ Events::open_event_table(THD *thd, enum thr_lock_type lock_type,
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
Events::create_event()
|
Events::create_event()
|
||||||
thd [in] THD
|
thd [in] THD
|
||||||
et [in] Event's data from parsing stage
|
parse_data [in] Event's data from parsing stage
|
||||||
if_not_exists [in] Whether IF NOT EXISTS was specified in the DDL
|
if_not_exists [in] Whether IF NOT EXISTS was specified in the DDL
|
||||||
rows_affected [out] How many rows were affected
|
rows_affected [out] How many rows were affected
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
0 OK
|
FALSE OK
|
||||||
!0 Error (Reported)
|
TRUE Error (Reported)
|
||||||
|
|
||||||
NOTES
|
NOTES
|
||||||
In case there is an event with the same name (db) and
|
In case there is an event with the same name (db) and
|
||||||
IF NOT EXISTS is specified, an warning is put into the stack.
|
IF NOT EXISTS is specified, an warning is put into the stack.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
bool
|
||||||
Events::create_event(THD *thd, Event_parse_data *parse_data, bool if_not_exists,
|
Events::create_event(THD *thd, Event_parse_data *parse_data, bool if_not_exists,
|
||||||
uint *rows_affected)
|
uint *rows_affected)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
DBUG_ENTER("Events::create_event");
|
DBUG_ENTER("Events::create_event");
|
||||||
|
if (unlikely(check_system_tables_error))
|
||||||
|
{
|
||||||
|
my_error(ER_EVENTS_DB_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&LOCK_event_metadata);
|
pthread_mutex_lock(&LOCK_event_metadata);
|
||||||
/* On error conditions my_error() is called so no need to handle here */
|
/* On error conditions my_error() is called so no need to handle here */
|
||||||
@ -321,13 +351,13 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, bool if_not_exists,
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
Events::update_event()
|
Events::update_event()
|
||||||
thd [in] THD
|
thd [in] THD
|
||||||
et [in] Event's data from parsing stage
|
parse_data [in] Event's data from parsing stage
|
||||||
rename_to [in] Set in case of RENAME TO.
|
rename_to [in] Set in case of RENAME TO.
|
||||||
rows_affected [out] How many rows were affected.
|
rows_affected [out] How many rows were affected.
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
0 OK
|
FALSE OK
|
||||||
!0 Error
|
TRUE Error
|
||||||
|
|
||||||
NOTES
|
NOTES
|
||||||
et contains data about dbname and event name.
|
et contains data about dbname and event name.
|
||||||
@ -335,14 +365,19 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, bool if_not_exists,
|
|||||||
that RENAME TO was specified in the query
|
that RENAME TO was specified in the query
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
bool
|
||||||
Events::update_event(THD *thd, Event_parse_data *parse_data, sp_name *rename_to,
|
Events::update_event(THD *thd, Event_parse_data *parse_data, sp_name *rename_to,
|
||||||
uint *rows_affected)
|
uint *rows_affected)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
DBUG_ENTER("Events::update_event");
|
DBUG_ENTER("Events::update_event");
|
||||||
LEX_STRING *new_dbname= rename_to? &rename_to->m_db: NULL;
|
LEX_STRING *new_dbname= rename_to ? &rename_to->m_db : NULL;
|
||||||
LEX_STRING *new_name= rename_to? &rename_to->m_name: NULL;
|
LEX_STRING *new_name= rename_to ? &rename_to->m_name : NULL;
|
||||||
|
if (unlikely(check_system_tables_error))
|
||||||
|
{
|
||||||
|
my_error(ER_EVENTS_DB_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&LOCK_event_metadata);
|
pthread_mutex_lock(&LOCK_event_metadata);
|
||||||
/* On error conditions my_error() is called so no need to handle here */
|
/* On error conditions my_error() is called so no need to handle here */
|
||||||
@ -378,16 +413,21 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, sp_name *rename_to,
|
|||||||
removal from memory queue.
|
removal from memory queue.
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
0 OK
|
FALSE OK
|
||||||
!0 Error (reported)
|
TRUE Error (reported)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
bool
|
||||||
Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists,
|
Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists,
|
||||||
uint *rows_affected, bool only_from_disk)
|
uint *rows_affected, bool only_from_disk)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
DBUG_ENTER("Events::drop_event");
|
DBUG_ENTER("Events::drop_event");
|
||||||
|
if (unlikely(check_system_tables_error))
|
||||||
|
{
|
||||||
|
my_error(ER_EVENTS_DB_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&LOCK_event_metadata);
|
pthread_mutex_lock(&LOCK_event_metadata);
|
||||||
/* On error conditions my_error() is called so no need to handle here */
|
/* On error conditions my_error() is called so no need to handle here */
|
||||||
@ -409,27 +449,27 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists,
|
|||||||
Events::drop_schema_events()
|
Events::drop_schema_events()
|
||||||
thd Thread
|
thd Thread
|
||||||
db ASCIIZ schema name
|
db ASCIIZ schema name
|
||||||
|
|
||||||
RETURN VALUE
|
|
||||||
0 OK
|
|
||||||
!0 Error
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
void
|
||||||
Events::drop_schema_events(THD *thd, char *db)
|
Events::drop_schema_events(THD *thd, char *db)
|
||||||
{
|
{
|
||||||
int ret= 0;
|
LEX_STRING const db_lex= { db, strlen(db) };
|
||||||
LEX_STRING db_lex= {db, strlen(db)};
|
|
||||||
|
|
||||||
DBUG_ENTER("Events::drop_schema_events");
|
DBUG_ENTER("Events::drop_schema_events");
|
||||||
DBUG_PRINT("enter", ("dropping events from %s", db));
|
DBUG_PRINT("enter", ("dropping events from %s", db));
|
||||||
|
if (unlikely(check_system_tables_error))
|
||||||
|
{
|
||||||
|
my_error(ER_EVENTS_DB_ERROR, MYF(0));
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&LOCK_event_metadata);
|
pthread_mutex_lock(&LOCK_event_metadata);
|
||||||
event_queue->drop_schema_events(thd, db_lex);
|
event_queue->drop_schema_events(thd, db_lex);
|
||||||
ret= db_repository->drop_schema_events(thd, db_lex);
|
db_repository->drop_schema_events(thd, db_lex);
|
||||||
pthread_mutex_unlock(&LOCK_event_metadata);
|
pthread_mutex_unlock(&LOCK_event_metadata);
|
||||||
|
|
||||||
DBUG_RETURN(ret);
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -438,15 +478,15 @@ Events::drop_schema_events(THD *thd, char *db)
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
Events::show_create_event()
|
Events::show_create_event()
|
||||||
thd THD
|
thd Thread context
|
||||||
spn the name of the event (db, name)
|
spn The name of the event (db, name)
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
0 OK
|
FALSE OK
|
||||||
1 Error during writing to the wire
|
TRUE Error during writing to the wire
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
bool
|
||||||
Events::show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
|
Events::show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
|
||||||
{
|
{
|
||||||
CHARSET_INFO *scs= system_charset_info;
|
CHARSET_INFO *scs= system_charset_info;
|
||||||
@ -455,6 +495,11 @@ Events::show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
|
|||||||
|
|
||||||
DBUG_ENTER("Events::show_create_event");
|
DBUG_ENTER("Events::show_create_event");
|
||||||
DBUG_PRINT("enter", ("name: %s@%s", dbname.str, name.str));
|
DBUG_PRINT("enter", ("name: %s@%s", dbname.str, name.str));
|
||||||
|
if (unlikely(check_system_tables_error))
|
||||||
|
{
|
||||||
|
my_error(ER_EVENTS_DB_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
ret= db_repository->load_named_event(thd, dbname, name, et);
|
ret= db_repository->load_named_event(thd, dbname, name, et);
|
||||||
|
|
||||||
@ -481,8 +526,8 @@ Events::show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
|
|||||||
|
|
||||||
field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len));
|
field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len));
|
||||||
|
|
||||||
field_list.
|
field_list.push_back(new Item_empty_string("Create Event",
|
||||||
push_back(new Item_empty_string("Create Event", show_str.length()));
|
show_str.length()));
|
||||||
|
|
||||||
if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
|
if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
|
||||||
Protocol::SEND_EOF))
|
Protocol::SEND_EOF))
|
||||||
@ -501,7 +546,7 @@ Events::show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
|
|||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
err:
|
err:
|
||||||
delete et;
|
delete et;
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -511,7 +556,7 @@ err:
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
Events::fill_schema_events()
|
Events::fill_schema_events()
|
||||||
thd Thread
|
thd Thread context
|
||||||
tables The schema table
|
tables The schema table
|
||||||
cond Unused
|
cond Unused
|
||||||
|
|
||||||
@ -525,6 +570,13 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
|
|||||||
{
|
{
|
||||||
char *db= NULL;
|
char *db= NULL;
|
||||||
DBUG_ENTER("Events::fill_schema_events");
|
DBUG_ENTER("Events::fill_schema_events");
|
||||||
|
Events *myself= get_instance();
|
||||||
|
if (unlikely(myself->check_system_tables_error))
|
||||||
|
{
|
||||||
|
my_error(ER_EVENTS_DB_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If it's SHOW EVENTS then thd->lex->select_lex.db is guaranteed not to
|
If it's SHOW EVENTS then thd->lex->select_lex.db is guaranteed not to
|
||||||
be NULL. Let's do an assert anyway.
|
be NULL. Let's do an assert anyway.
|
||||||
@ -537,8 +589,7 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
|
|||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
db= thd->lex->select_lex.db;
|
db= thd->lex->select_lex.db;
|
||||||
}
|
}
|
||||||
DBUG_RETURN(get_instance()->db_repository->
|
DBUG_RETURN(myself->db_repository->fill_schema_events(thd, tables, db));
|
||||||
fill_schema_events(thd, tables, db));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -552,31 +603,60 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
|
|||||||
This function is not synchronized.
|
This function is not synchronized.
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
0 OK
|
FALSE OK
|
||||||
1 Error in case the scheduler can't start
|
TRUE Error in case the scheduler can't start
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Events::init()
|
Events::init()
|
||||||
{
|
{
|
||||||
int res;
|
THD *thd;
|
||||||
|
bool res= FALSE;
|
||||||
DBUG_ENTER("Events::init");
|
DBUG_ENTER("Events::init");
|
||||||
if (event_queue->init_queue(db_repository, scheduler))
|
|
||||||
|
/* We need a temporary THD during boot */
|
||||||
|
if (!(thd= new THD()))
|
||||||
{
|
{
|
||||||
sql_print_information("SCHEDULER: Error while loading from disk.");
|
res= TRUE;
|
||||||
DBUG_RETURN(TRUE);
|
goto end;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
The thread stack does not start from this function but we cannot
|
||||||
|
guess the real value. So better some value that doesn't assert than
|
||||||
|
no value.
|
||||||
|
*/
|
||||||
|
thd->thread_stack= (char*) &thd;
|
||||||
|
thd->store_globals();
|
||||||
|
|
||||||
|
if (check_system_tables(thd))
|
||||||
|
{
|
||||||
|
check_system_tables_error= TRUE;
|
||||||
|
sql_print_error("SCHEDULER: The system tables are damaged. "
|
||||||
|
"The scheduler subsystem will be unusable during this run.");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
check_system_tables_error= FALSE;
|
||||||
|
|
||||||
|
if (event_queue->init_queue(thd, db_repository, scheduler))
|
||||||
|
{
|
||||||
|
sql_print_error("SCHEDULER: Error while loading from disk.");
|
||||||
|
goto end;
|
||||||
}
|
}
|
||||||
scheduler->init_scheduler(event_queue);
|
scheduler->init_scheduler(event_queue);
|
||||||
|
|
||||||
/* it should be an assignment! */
|
|
||||||
if (opt_event_scheduler)
|
if (opt_event_scheduler)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(opt_event_scheduler == 1 || opt_event_scheduler == 2);
|
DBUG_ASSERT(opt_event_scheduler == 1 || opt_event_scheduler == 2);
|
||||||
if (opt_event_scheduler == 1)
|
if (opt_event_scheduler == 1)
|
||||||
DBUG_RETURN(scheduler->start());
|
res= scheduler->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_RETURN(FALSE);
|
end:
|
||||||
|
delete thd;
|
||||||
|
/* Remember that we don't have a THD */
|
||||||
|
my_pthread_setspecific_ptr(THR_THD, NULL);
|
||||||
|
|
||||||
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -595,10 +675,13 @@ Events::deinit()
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("Events::deinit");
|
DBUG_ENTER("Events::deinit");
|
||||||
|
|
||||||
|
if (likely(!check_system_tables_error))
|
||||||
|
{
|
||||||
scheduler->stop();
|
scheduler->stop();
|
||||||
scheduler->deinit_scheduler();
|
scheduler->deinit_scheduler();
|
||||||
|
|
||||||
event_queue->deinit_queue();
|
event_queue->deinit_queue();
|
||||||
|
}
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -616,13 +699,7 @@ void
|
|||||||
Events::init_mutexes()
|
Events::init_mutexes()
|
||||||
{
|
{
|
||||||
pthread_mutex_init(&LOCK_event_metadata, MY_MUTEX_INIT_FAST);
|
pthread_mutex_init(&LOCK_event_metadata, MY_MUTEX_INIT_FAST);
|
||||||
|
|
||||||
db_repository= new Event_db_repository;
|
|
||||||
|
|
||||||
event_queue= new Event_queue;
|
|
||||||
event_queue->init_mutexes();
|
event_queue->init_mutexes();
|
||||||
|
|
||||||
scheduler= new Event_scheduler;
|
|
||||||
scheduler->init_mutexes();
|
scheduler->init_mutexes();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -639,11 +716,6 @@ Events::destroy_mutexes()
|
|||||||
{
|
{
|
||||||
event_queue->deinit_mutexes();
|
event_queue->deinit_mutexes();
|
||||||
scheduler->deinit_mutexes();
|
scheduler->deinit_mutexes();
|
||||||
|
|
||||||
delete scheduler;
|
|
||||||
delete db_repository;
|
|
||||||
delete event_queue;
|
|
||||||
|
|
||||||
pthread_mutex_destroy(&LOCK_event_metadata);
|
pthread_mutex_destroy(&LOCK_event_metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -700,6 +772,11 @@ bool
|
|||||||
Events::start_execution_of_events()
|
Events::start_execution_of_events()
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Events::start_execution_of_events");
|
DBUG_ENTER("Events::start_execution_of_events");
|
||||||
|
if (unlikely(check_system_tables_error))
|
||||||
|
{
|
||||||
|
my_error(ER_EVENTS_DB_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
DBUG_RETURN(scheduler->start());
|
DBUG_RETURN(scheduler->start());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -721,6 +798,11 @@ bool
|
|||||||
Events::stop_execution_of_events()
|
Events::stop_execution_of_events()
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Events::stop_execution_of_events");
|
DBUG_ENTER("Events::stop_execution_of_events");
|
||||||
|
if (unlikely(check_system_tables_error))
|
||||||
|
{
|
||||||
|
my_error(ER_EVENTS_DB_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
DBUG_RETURN(scheduler->stop());
|
DBUG_RETURN(scheduler->stop());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -737,8 +819,86 @@ Events::stop_execution_of_events()
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Events::is_started()
|
Events::is_execution_of_events_started()
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Events::is_started");
|
DBUG_ENTER("Events::is_execution_of_events_started");
|
||||||
|
if (unlikely(check_system_tables_error))
|
||||||
|
{
|
||||||
|
my_error(ER_EVENTS_DB_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
DBUG_RETURN(scheduler->get_state() == Event_scheduler::RUNNING);
|
DBUG_RETURN(scheduler->get_state() == Event_scheduler::RUNNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Opens mysql.db and mysql.user and checks whether:
|
||||||
|
1. mysql.db has column Event_priv at column 20 (0 based);
|
||||||
|
2. mysql.user has column Event_priv at column 29 (0 based);
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
Events::check_system_tables()
|
||||||
|
thd Thread
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
FALSE OK
|
||||||
|
TRUE Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
Events::check_system_tables(THD *thd)
|
||||||
|
{
|
||||||
|
TABLE_LIST tables;
|
||||||
|
bool not_used;
|
||||||
|
Open_tables_state backup;
|
||||||
|
bool ret= FALSE;
|
||||||
|
|
||||||
|
DBUG_ENTER("Events::check_system_tables");
|
||||||
|
DBUG_PRINT("enter", ("thd=0x%lx", thd));
|
||||||
|
|
||||||
|
thd->reset_n_backup_open_tables_state(&backup);
|
||||||
|
|
||||||
|
bzero((char*) &tables, sizeof(tables));
|
||||||
|
tables.db= (char*) "mysql";
|
||||||
|
tables.table_name= tables.alias= (char*) "db";
|
||||||
|
tables.lock_type= TL_READ;
|
||||||
|
|
||||||
|
if ((ret= simple_open_n_lock_tables(thd, &tables)))
|
||||||
|
{
|
||||||
|
sql_print_error("SCHEDULER: Cannot open mysql.db");
|
||||||
|
ret= TRUE;
|
||||||
|
}
|
||||||
|
ret= table_check_intact(tables.table, MYSQL_DB_FIELD_COUNT,
|
||||||
|
mysql_db_table_fields, &mysql_db_table_last_check,
|
||||||
|
ER_CANNOT_LOAD_FROM_TABLE);
|
||||||
|
close_thread_tables(thd);
|
||||||
|
|
||||||
|
bzero((char*) &tables, sizeof(tables));
|
||||||
|
tables.db= (char*) "mysql";
|
||||||
|
tables.table_name= tables.alias= (char*) "user";
|
||||||
|
tables.lock_type= TL_READ;
|
||||||
|
|
||||||
|
if (simple_open_n_lock_tables(thd, &tables))
|
||||||
|
{
|
||||||
|
sql_print_error("SCHEDULER: Cannot open mysql.user");
|
||||||
|
ret= TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (tables.table->s->fields < 29 ||
|
||||||
|
strncmp(tables.table->field[29]->field_name,
|
||||||
|
STRING_WITH_LEN("Event_priv")))
|
||||||
|
{
|
||||||
|
sql_print_error("mysql.user has no `Event_priv` column at position %d",
|
||||||
|
29);
|
||||||
|
ret= TRUE;
|
||||||
|
}
|
||||||
|
close_thread_tables(thd);
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
thd->restore_backup_open_tables_state(&backup);
|
||||||
|
|
||||||
|
DBUG_RETURN(ret);
|
||||||
|
}
|
||||||
|
23
sql/events.h
23
sql/events.h
@ -42,12 +42,12 @@ sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
|
|||||||
class Events
|
class Events
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
friend class Event_queue_element;
|
|
||||||
/*
|
/*
|
||||||
Quite NOT the best practice and will be removed once
|
Quite NOT the best practice and will be removed once
|
||||||
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_queue_element;
|
||||||
|
|
||||||
static ulong opt_event_scheduler;
|
static ulong opt_event_scheduler;
|
||||||
static TYPELIB opt_typelib;
|
static TYPELIB opt_typelib;
|
||||||
@ -71,30 +71,30 @@ public:
|
|||||||
stop_execution_of_events();
|
stop_execution_of_events();
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_started();
|
is_execution_of_events_started();
|
||||||
|
|
||||||
static Events*
|
static Events *
|
||||||
get_instance();
|
get_instance();
|
||||||
|
|
||||||
int
|
bool
|
||||||
create_event(THD *thd, Event_parse_data *parse_data, bool if_exists,
|
create_event(THD *thd, Event_parse_data *parse_data, bool if_exists,
|
||||||
uint *rows_affected);
|
uint *rows_affected);
|
||||||
|
|
||||||
int
|
bool
|
||||||
update_event(THD *thd, Event_parse_data *parse_data, sp_name *rename_to,
|
update_event(THD *thd, Event_parse_data *parse_data, sp_name *rename_to,
|
||||||
uint *rows_affected);
|
uint *rows_affected);
|
||||||
|
|
||||||
int
|
bool
|
||||||
drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists,
|
drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists,
|
||||||
uint *rows_affected, bool only_from_disk);
|
uint *rows_affected, bool only_from_disk);
|
||||||
|
|
||||||
int
|
void
|
||||||
drop_schema_events(THD *thd, char *db);
|
drop_schema_events(THD *thd, char *db);
|
||||||
|
|
||||||
int
|
int
|
||||||
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
|
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
|
||||||
|
|
||||||
int
|
bool
|
||||||
show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name);
|
show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name);
|
||||||
|
|
||||||
/* Needed for both SHOW CREATE EVENT and INFORMATION_SCHEMA */
|
/* Needed for both SHOW CREATE EVENT and INFORMATION_SCHEMA */
|
||||||
@ -109,8 +109,11 @@ public:
|
|||||||
dump_internal_status(THD *thd);
|
dump_internal_status(THD *thd);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool
|
||||||
|
check_system_tables(THD *thd);
|
||||||
|
|
||||||
/* Singleton DP is used */
|
/* Singleton DP is used */
|
||||||
Events(){}
|
Events();
|
||||||
~Events(){}
|
~Events(){}
|
||||||
|
|
||||||
/* Singleton instance */
|
/* Singleton instance */
|
||||||
@ -122,6 +125,8 @@ private:
|
|||||||
|
|
||||||
pthread_mutex_t LOCK_event_metadata;
|
pthread_mutex_t LOCK_event_metadata;
|
||||||
|
|
||||||
|
bool check_system_tables_error;
|
||||||
|
|
||||||
/* Prevent use of these */
|
/* Prevent use of these */
|
||||||
Events(const Events &);
|
Events(const Events &);
|
||||||
void operator=(Events &);
|
void operator=(Events &);
|
||||||
|
@ -3978,7 +3978,7 @@ byte *sys_var_event_scheduler::value_ptr(THD *thd, enum_var_type type,
|
|||||||
{
|
{
|
||||||
if (Events::opt_event_scheduler == 0)
|
if (Events::opt_event_scheduler == 0)
|
||||||
thd->sys_var_tmp.long_value= 0;
|
thd->sys_var_tmp.long_value= 0;
|
||||||
else if (Events::get_instance()->is_started())
|
else if (Events::get_instance()->is_execution_of_events_started())
|
||||||
thd->sys_var_tmp.long_value= 1;
|
thd->sys_var_tmp.long_value= 1;
|
||||||
else
|
else
|
||||||
thd->sys_var_tmp.long_value= 2;
|
thd->sys_var_tmp.long_value= 2;
|
||||||
|
@ -5851,3 +5851,5 @@ ER_CANT_DROP_LOG_TABLE
|
|||||||
eng "Cannot drop log table if log is enabled"
|
eng "Cannot drop log table if log is enabled"
|
||||||
ER_EVENT_RECURSIVITY_FORBIDDEN
|
ER_EVENT_RECURSIVITY_FORBIDDEN
|
||||||
eng "Recursivity of EVENT DDL statements is forbidden when body is present"
|
eng "Recursivity of EVENT DDL statements is forbidden when body is present"
|
||||||
|
ER_EVENTS_DB_ERROR
|
||||||
|
eng "Cannot proceed because the tables used by events were found damaged at server start"
|
||||||
|
@ -949,7 +949,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
|
|||||||
|
|
||||||
exit:
|
exit:
|
||||||
(void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */
|
(void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */
|
||||||
error= Events::get_instance()->drop_schema_events(thd, db);
|
Events::get_instance()->drop_schema_events(thd, db);
|
||||||
/*
|
/*
|
||||||
If this database was the client's selected database, we silently
|
If this database was the client's selected database, we silently
|
||||||
change the client's selected database to nothing (to have an empty
|
change the client's selected database to nothing (to have an empty
|
||||||
|
@ -1445,11 +1445,11 @@ ev_sql_stmt:
|
|||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
|
|
||||||
// return back to the original memory root ASAP
|
/* return back to the original memory root ASAP */
|
||||||
lex->sphead->init_strings(YYTHD, lex);
|
lex->sphead->init_strings(YYTHD, lex);
|
||||||
lex->sphead->restore_thd_mem_root(YYTHD);
|
lex->sphead->restore_thd_mem_root(YYTHD);
|
||||||
|
|
||||||
lex->sp_chistics.suid= SP_IS_SUID;//always the definer!
|
lex->sp_chistics.suid= SP_IS_SUID; //always the definer!
|
||||||
|
|
||||||
Lex->event_parse_data->init_body(YYTHD);
|
Lex->event_parse_data->init_body(YYTHD);
|
||||||
}
|
}
|
||||||
@ -1568,9 +1568,9 @@ create_function_tail:
|
|||||||
sp->m_type= TYPE_ENUM_FUNCTION;
|
sp->m_type= TYPE_ENUM_FUNCTION;
|
||||||
lex->sphead= sp;
|
lex->sphead= sp;
|
||||||
/*
|
/*
|
||||||
* We have to turn of CLIENT_MULTI_QUERIES while parsing a
|
We have to turn off CLIENT_MULTI_QUERIES while parsing a
|
||||||
* stored procedure, otherwise yylex will chop it into pieces
|
stored procedure, otherwise yylex will chop it into pieces
|
||||||
* at each ';'.
|
at each ';'.
|
||||||
*/
|
*/
|
||||||
$<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;
|
||||||
@ -4684,14 +4684,13 @@ alter:
|
|||||||
If it had to be supported spname had to be added to
|
If it had to be supported spname had to be added to
|
||||||
Event_parse_data.
|
Event_parse_data.
|
||||||
*/
|
*/
|
||||||
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;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We have to turn of CLIENT_MULTI_QUERIES while parsing a
|
We have to turn off CLIENT_MULTI_QUERIES while parsing a
|
||||||
stored procedure, otherwise yylex will chop it into pieces
|
stored procedure, otherwise yylex will chop it into pieces
|
||||||
at each ';'.
|
at each ';'.
|
||||||
*/
|
*/
|
||||||
@ -4757,9 +4756,11 @@ ev_alter_on_schedule_completion: /* empty */ { $$= 0;}
|
|||||||
opt_ev_rename_to: /* empty */ { $$= 0;}
|
opt_ev_rename_to: /* empty */ { $$= 0;}
|
||||||
| RENAME TO_SYM sp_name
|
| RENAME TO_SYM sp_name
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
/*
|
||||||
lex->spname= $3; //use lex's spname to hold the new name
|
Use lex's spname to hold the new name.
|
||||||
//the original name is in the Event_parse_data object
|
The original name is in the Event_parse_data object
|
||||||
|
*/
|
||||||
|
Lex->spname= $3;
|
||||||
$$= 1;
|
$$= 1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@ -4783,7 +4784,7 @@ alter_commands:
|
|||||||
| remove_partitioning
|
| remove_partitioning
|
||||||
| partitioning
|
| partitioning
|
||||||
/*
|
/*
|
||||||
This part was added for release 5.1 by Mikael Ronström.
|
This part was added for release 5.1 by Mikael Ronström.
|
||||||
From here we insert a number of commands to manage the partitions of a
|
From here we insert a number of commands to manage the partitions of a
|
||||||
partitioned table such as adding partitions, dropping partitions,
|
partitioned table such as adding partitions, dropping partitions,
|
||||||
reorganising partitions in various manners. In future releases the list
|
reorganising partitions in various manners. In future releases the list
|
||||||
|
34
sql/table.cc
34
sql/table.cc
@ -2352,28 +2352,28 @@ bool check_column_name(const char *name)
|
|||||||
Checks whether a table is intact. Should be done *just* after the table has
|
Checks whether a table is intact. Should be done *just* after the table has
|
||||||
been opened.
|
been opened.
|
||||||
|
|
||||||
Synopsis
|
SYNOPSIS
|
||||||
table_check_intact()
|
table_check_intact()
|
||||||
table - the table to check
|
table The table to check
|
||||||
table_f_count - expected number of columns in the table
|
table_f_count Expected number of columns in the table
|
||||||
table_def - expected structure of the table (column name and type)
|
table_def Expected structure of the table (column name and type)
|
||||||
last_create_time- the table->file->create_time of the table in memory
|
last_create_time The table->file->create_time of the table in memory
|
||||||
we have checked last time
|
we have checked last time
|
||||||
error_num - ER_XXXX from the error messages file. When 0 no error
|
error_num ER_XXXX from the error messages file. When 0 no error
|
||||||
is sent to the client in case types does not match.
|
is sent to the client in case types does not match.
|
||||||
If different col number either
|
If different col number either
|
||||||
ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE or
|
ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE or
|
||||||
ER_COL_COUNT_DOESNT_MATCH_CORRUPTED is used
|
ER_COL_COUNT_DOESNT_MATCH_CORRUPTED is used
|
||||||
|
|
||||||
RETURNS
|
RETURNS
|
||||||
0 - OK
|
FALSE OK
|
||||||
1 - There was an error
|
TRUE There was an error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
my_bool
|
my_bool
|
||||||
table_check_intact(TABLE *table, uint table_f_count,
|
table_check_intact(TABLE *table, const uint table_f_count,
|
||||||
TABLE_FIELD_W_TYPE *table_def, time_t *last_create_time,
|
const TABLE_FIELD_W_TYPE *table_def,
|
||||||
int error_num)
|
time_t *last_create_time, int error_num)
|
||||||
{
|
{
|
||||||
uint i;
|
uint i;
|
||||||
my_bool error= FALSE;
|
my_bool error= FALSE;
|
||||||
@ -2388,7 +2388,7 @@ table_check_intact(TABLE *table, uint table_f_count,
|
|||||||
DBUG_PRINT("info", ("I am suspecting, checking table"));
|
DBUG_PRINT("info", ("I am suspecting, checking table"));
|
||||||
if (fields_diff_count)
|
if (fields_diff_count)
|
||||||
{
|
{
|
||||||
// previous MySQL version
|
/* previous MySQL version */
|
||||||
error= TRUE;
|
error= TRUE;
|
||||||
if (MYSQL_VERSION_ID > table->s->mysql_version)
|
if (MYSQL_VERSION_ID > table->s->mysql_version)
|
||||||
{
|
{
|
||||||
@ -2411,22 +2411,22 @@ table_check_intact(TABLE *table, uint table_f_count,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
moving from newer mysql to older one -> let's say not an error but
|
Moving from newer mysql to older one -> let's say not an error but
|
||||||
will check the definition afterwards. If a column was added at the
|
will check the definition afterwards. If a column was added at the
|
||||||
end then we don't care much since it's not in the middle.
|
end then we don't care much since it's not in the middle.
|
||||||
*/
|
*/
|
||||||
error= FALSE;
|
error= FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//definitely something has changed
|
/* definitely something has changed */
|
||||||
char buffer[255];
|
char buffer[255];
|
||||||
for (i=0 ; i < table_f_count; i++, table_def++)
|
for (i=0 ; i < table_f_count; i++, table_def++)
|
||||||
{
|
{
|
||||||
String sql_type(buffer, sizeof(buffer), system_charset_info);
|
String sql_type(buffer, sizeof(buffer), system_charset_info);
|
||||||
sql_type.length(0);
|
sql_type.length(0);
|
||||||
/*
|
/*
|
||||||
name changes are not fatal, we use sequence numbers => no prob for us
|
Name changes are not fatal, we use sequence numbers => no problem
|
||||||
but this can show tampered table or broken table.
|
for us but this can show tampered table or broken table.
|
||||||
*/
|
*/
|
||||||
if (i < table->s->fields)
|
if (i < table->s->fields)
|
||||||
{
|
{
|
||||||
@ -2440,7 +2440,7 @@ table_check_intact(TABLE *table, uint table_f_count,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
IF the type does not match than something is really wrong
|
If the type does not match than something is really wrong
|
||||||
Check up to length - 1. Why?
|
Check up to length - 1. Why?
|
||||||
1. datetime -> datetim -> the same
|
1. datetime -> datetim -> the same
|
||||||
2. int(11) -> int(11 -> the same
|
2. int(11) -> int(11 -> the same
|
||||||
|
@ -965,9 +965,9 @@ typedef struct st_table_field_w_type
|
|||||||
|
|
||||||
|
|
||||||
my_bool
|
my_bool
|
||||||
table_check_intact(TABLE *table, uint table_f_count,
|
table_check_intact(TABLE *table, const uint table_f_count,
|
||||||
TABLE_FIELD_W_TYPE *table_def, time_t *last_create_time,
|
const TABLE_FIELD_W_TYPE * const table_def,
|
||||||
int error_num);
|
time_t *last_create_time, int error_num);
|
||||||
|
|
||||||
static inline my_bitmap_map *tmp_use_all_columns(TABLE *table,
|
static inline my_bitmap_map *tmp_use_all_columns(TABLE *table,
|
||||||
MY_BITMAP *bitmap)
|
MY_BITMAP *bitmap)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user