mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Post-merge and post-review fixes for the patch for
Bug#23631 "Events: SHOW VARIABLES doesn't work when mysql.event is damaged:
This commit is contained in:
@ -99,7 +99,9 @@ Event_parse_data::new_instance(THD *thd)
|
||||
*/
|
||||
|
||||
Event_parse_data::Event_parse_data()
|
||||
:on_completion(ON_COMPLETION_DROP), status(ENABLED), do_not_create(FALSE),
|
||||
:on_completion(Event_basic::ON_COMPLETION_DROP),
|
||||
status(Event_basic::ENABLED),
|
||||
do_not_create(FALSE),
|
||||
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)
|
||||
@ -241,7 +243,7 @@ Event_parse_data::check_if_in_the_past(THD *thd, my_time_t ltime_utc)
|
||||
if (ltime_utc >= (my_time_t) thd->query_start())
|
||||
return;
|
||||
|
||||
if (on_completion == ON_COMPLETION_DROP)
|
||||
if (on_completion == Event_basic::ON_COMPLETION_DROP)
|
||||
{
|
||||
switch (thd->lex->sql_command) {
|
||||
case SQLCOM_CREATE_EVENT:
|
||||
@ -258,9 +260,9 @@ Event_parse_data::check_if_in_the_past(THD *thd, my_time_t ltime_utc)
|
||||
|
||||
do_not_create= TRUE;
|
||||
}
|
||||
else if (status == ENABLED)
|
||||
else if (status == Event_basic::ENABLED)
|
||||
{
|
||||
status= DISABLED;
|
||||
status= Event_basic::DISABLED;
|
||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
ER_EVENT_EXEC_TIME_IN_THE_PAST,
|
||||
ER(ER_EVENT_EXEC_TIME_IN_THE_PAST));
|
||||
@ -589,6 +591,7 @@ Event_parse_data::check_parse_data(THD *thd)
|
||||
|
||||
ret= init_execute_at(thd) || init_interval(thd) || init_starts(thd) ||
|
||||
init_ends(thd);
|
||||
check_originator_id(thd);
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
|
||||
@ -635,6 +638,31 @@ Event_parse_data::init_definer(THD *thd)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Set the originator id of the event to the server_id if executing on
|
||||
the master or set to the server_id of the master if executing on
|
||||
the slave. If executing on slave, also set status to SLAVESIDE_DISABLED.
|
||||
|
||||
SYNOPSIS
|
||||
Event_parse_data::check_originator_id()
|
||||
*/
|
||||
void Event_parse_data::check_originator_id(THD *thd)
|
||||
{
|
||||
/* Disable replicated events on slave. */
|
||||
if ((thd->system_thread == SYSTEM_THREAD_SLAVE_SQL) ||
|
||||
(thd->system_thread == SYSTEM_THREAD_SLAVE_IO))
|
||||
{
|
||||
DBUG_PRINT("info", ("Invoked object status set to SLAVESIDE_DISABLED."));
|
||||
if ((status == Event_basic::ENABLED) ||
|
||||
(status == Event_basic::DISABLED))
|
||||
status = Event_basic::SLAVESIDE_DISABLED;
|
||||
originator = thd->server_id;
|
||||
}
|
||||
else
|
||||
originator = server_id;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Constructor
|
||||
|
||||
@ -1004,8 +1032,23 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
|
||||
goto error;
|
||||
|
||||
DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", name.str, ptr));
|
||||
status= (ptr[0]=='E'? Event_queue_element::ENABLED:
|
||||
Event_queue_element::DISABLED);
|
||||
|
||||
/* Set event status (ENABLED | SLAVESIDE_DISABLED | DISABLED) */
|
||||
switch (ptr[0])
|
||||
{
|
||||
case 'E' :
|
||||
status = Event_queue_element::ENABLED;
|
||||
break;
|
||||
case 'S' :
|
||||
status = Event_queue_element::SLAVESIDE_DISABLED;
|
||||
break;
|
||||
case 'D' :
|
||||
status = Event_queue_element::DISABLED;
|
||||
break;
|
||||
}
|
||||
if ((ptr= get_field(&mem_root, table->field[ET_FIELD_ORIGINATOR])) == NullS)
|
||||
goto error;
|
||||
originator = table->field[ET_FIELD_ORIGINATOR]->val_int();
|
||||
|
||||
/* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */
|
||||
if ((ptr= get_field(&mem_root,
|
||||
@ -1356,7 +1399,7 @@ Event_queue_element::compute_next_execution_time()
|
||||
(long) starts, (long) ends, (long) last_executed,
|
||||
(long) this));
|
||||
|
||||
if (status == Event_queue_element::DISABLED)
|
||||
if (status != Event_queue_element::ENABLED)
|
||||
{
|
||||
DBUG_PRINT("compute_next_execution_time",
|
||||
("Event %s is DISABLED", name.str));
|
||||
@ -1708,6 +1751,8 @@ Event_timed::get_create_event(THD *thd, String *buf)
|
||||
|
||||
if (status == Event_timed::ENABLED)
|
||||
buf->append(STRING_WITH_LEN("ENABLE"));
|
||||
else if (status == Event_timed::SLAVESIDE_DISABLED)
|
||||
buf->append(STRING_WITH_LEN("DISABLE ON SLAVE"));
|
||||
else
|
||||
buf->append(STRING_WITH_LEN("DISABLE"));
|
||||
|
||||
@ -1765,7 +1810,7 @@ Event_job_data::get_fake_create_event(String *buf)
|
||||
*/
|
||||
|
||||
int
|
||||
Event_job_data::execute(THD *thd)
|
||||
Event_job_data::execute(THD *thd, bool drop)
|
||||
{
|
||||
Security_context save_ctx;
|
||||
/* this one is local and not needed after exec */
|
||||
@ -1805,6 +1850,17 @@ Event_job_data::execute(THD *thd)
|
||||
definer_host.str, dbname.str));
|
||||
ret= -99;
|
||||
}
|
||||
if (drop)
|
||||
{
|
||||
sql_print_information("Event Scheduler: Dropping %s.%s",
|
||||
dbname.str, name.str);
|
||||
/*
|
||||
We must do it here since here we're under the right authentication
|
||||
ID of the event definer
|
||||
*/
|
||||
if (Events::drop_event(thd, dbname, name, FALSE))
|
||||
ret= 1;
|
||||
}
|
||||
|
||||
event_restore_security_context(thd, &save_ctx);
|
||||
done:
|
||||
|
@ -184,7 +184,7 @@ public:
|
||||
load_from_row(THD *thd, TABLE *table);
|
||||
|
||||
int
|
||||
execute(THD *thd);
|
||||
execute(THD *thd, bool drop);
|
||||
|
||||
int
|
||||
compile(THD *thd, MEM_ROOT *mem_root);
|
||||
|
@ -905,6 +905,13 @@ update_timing_fields_for_event(THD *thd,
|
||||
|
||||
DBUG_ENTER("Event_db_repository::update_timing_fields_for_event");
|
||||
|
||||
/*
|
||||
Turn off row binlogging of event timing updates. These are not used
|
||||
for RBR of events replicated to the slave.
|
||||
*/
|
||||
if (thd->current_stmt_binlog_row_based)
|
||||
thd->clear_current_stmt_binlog_row_based();
|
||||
|
||||
if (open_event_table(thd, TL_WRITE, &table))
|
||||
goto end;
|
||||
|
||||
|
@ -309,7 +309,7 @@ Event_worker_thread::run(THD *thd, Event_queue_element_for_exec *event)
|
||||
|
||||
thd->enable_slow_log= TRUE;
|
||||
|
||||
ret= job_data->execute(thd);
|
||||
ret= job_data->execute(thd, event->dropped);
|
||||
|
||||
print_warnings(thd, job_data);
|
||||
|
||||
@ -338,27 +338,6 @@ Event_worker_thread::run(THD *thd, Event_queue_element_for_exec *event)
|
||||
end:
|
||||
delete job_data;
|
||||
|
||||
if (event->dropped)
|
||||
{
|
||||
sql_print_information("Event Scheduler: Dropping %s.%s",
|
||||
event->dbname.str, event->name.str);
|
||||
/*
|
||||
Using db_repository can lead to a race condition because we access
|
||||
the table without holding LOCK_metadata.
|
||||
Scenario:
|
||||
1. CREATE EVENT xyz AT ... (conn thread)
|
||||
2. execute xyz (worker)
|
||||
3. CREATE EVENT XYZ EVERY ... (conn thread)
|
||||
4. drop xyz (worker)
|
||||
5. XYZ was just created on disk but `drop xyz` of the worker dropped it.
|
||||
A consequent load to create Event_queue_element will fail.
|
||||
|
||||
If all operations are performed under LOCK_metadata there is no such
|
||||
problem. However, this comes at the price of introduction bi-directional
|
||||
association between class Events and class Event_worker_thread.
|
||||
*/
|
||||
Events::drop_event(thd, event->dbname, event->name, FALSE);
|
||||
}
|
||||
DBUG_PRINT("info", ("Done with Event %s.%s", event->dbname.str,
|
||||
event->name.str));
|
||||
|
||||
|
@ -1041,14 +1041,14 @@ Events::dump_internal_status()
|
||||
*/
|
||||
|
||||
bool
|
||||
Events::start_or_stop_event_scheduler(enum_opt_event_scheduler start_or_stop)
|
||||
Events::switch_event_scheduler_state(enum_opt_event_scheduler new_state)
|
||||
{
|
||||
bool ret= FALSE;
|
||||
|
||||
DBUG_ENTER("Events::start_or_stop_event_scheduler");
|
||||
DBUG_ENTER("Events::switch_event_scheduler_state");
|
||||
|
||||
DBUG_ASSERT(start_or_stop == Events::EVENTS_ON ||
|
||||
start_or_stop == Events::EVENTS_OFF);
|
||||
DBUG_ASSERT(new_state == Events::EVENTS_ON ||
|
||||
new_state == Events::EVENTS_OFF);
|
||||
|
||||
/*
|
||||
If the scheduler was disabled because there are no/bad
|
||||
@ -1068,7 +1068,7 @@ Events::start_or_stop_event_scheduler(enum_opt_event_scheduler start_or_stop)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (start_or_stop == EVENTS_ON)
|
||||
if (new_state == EVENTS_ON)
|
||||
ret= scheduler->start();
|
||||
else
|
||||
ret= scheduler->stop();
|
||||
@ -1079,7 +1079,7 @@ Events::start_or_stop_event_scheduler(enum_opt_event_scheduler start_or_stop)
|
||||
goto end;
|
||||
}
|
||||
|
||||
opt_event_scheduler= start_or_stop;
|
||||
opt_event_scheduler= new_state;
|
||||
|
||||
end:
|
||||
pthread_mutex_unlock(&LOCK_event_metadata);
|
||||
|
@ -99,7 +99,7 @@ public:
|
||||
destroy_mutexes();
|
||||
|
||||
static bool
|
||||
start_or_stop_event_scheduler(enum enum_opt_event_scheduler start_or_stop);
|
||||
switch_event_scheduler_state(enum enum_opt_event_scheduler new_state);
|
||||
|
||||
static bool
|
||||
create_event(THD *thd, Event_parse_data *parse_data, bool if_exists);
|
||||
|
@ -4020,7 +4020,7 @@ sys_var_event_scheduler::update(THD *thd, set_var *var)
|
||||
new_state=
|
||||
(enum Events::enum_opt_event_scheduler) var->save_result.ulong_value;
|
||||
|
||||
res= Events::start_or_stop_event_scheduler(new_state);
|
||||
res= Events::switch_event_scheduler_state(new_state);
|
||||
|
||||
DBUG_RETURN((bool) res);
|
||||
}
|
||||
|
@ -948,7 +948,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
%token SIGNED_SYM
|
||||
%token SIMPLE_SYM /* SQL-2003-N */
|
||||
%token SLAVE
|
||||
%token SLAVESIDE_DISABLE_SYM
|
||||
%token SMALLINT /* SQL-2003-R */
|
||||
%token SNAPSHOT_SYM
|
||||
%token SOCKET_SYM
|
||||
@ -10004,7 +10003,6 @@ keyword_sp:
|
||||
| SIMPLE_SYM {}
|
||||
| SHARE_SYM {}
|
||||
| SHUTDOWN {}
|
||||
| SLAVESIDE_DISABLE_SYM {}
|
||||
| SNAPSHOT_SYM {}
|
||||
| SOUNDS_SYM {}
|
||||
| SQL_CACHE_SYM {}
|
||||
|
Reference in New Issue
Block a user