summaryrefslogtreecommitdiff
path: root/sql/events.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/events.cc')
-rw-r--r--sql/events.cc370
1 files changed, 238 insertions, 132 deletions
diff --git a/sql/events.cc b/sql/events.cc
index 008b6223702..187a3208d9f 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -1,5 +1,6 @@
/*
Copyright (c) 2005, 2013, Oracle and/or its affiliates.
+ Copyright (c) 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -14,6 +15,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sql_parse.h" // check_access
@@ -79,7 +81,8 @@ Event_queue *Events::event_queue;
Event_scheduler *Events::scheduler;
Event_db_repository *Events::db_repository;
ulong Events::opt_event_scheduler= Events::EVENTS_OFF;
-bool Events::check_system_tables_error= FALSE;
+ulong Events::startup_state= Events::EVENTS_OFF;
+ulong Events::inited;
/*
@@ -113,7 +116,7 @@ bool Events::check_if_system_tables_error()
{
DBUG_ENTER("Events::check_if_system_tables_error");
- if (check_system_tables_error)
+ if (!inited)
{
my_error(ER_EVENTS_DB_ERROR, MYF(0));
DBUG_RETURN(TRUE);
@@ -258,10 +261,10 @@ common_1_lev_code:
/**
- Create a new query string for removing executable comments
- for avoiding leak and keeping consistency of the execution
+ Create a new query string for removing executable comments
+ for avoiding leak and keeping consistency of the execution
on master and slave.
-
+
@param[in] thd Thread handler
@param[in] buf Query string
@@ -272,8 +275,14 @@ common_1_lev_code:
static int
create_query_string(THD *thd, String *buf)
{
+ buf->length(0);
/* Append the "CREATE" part of the query */
- if (buf->append(STRING_WITH_LEN("CREATE ")))
+ if (thd->lex->create_info.or_replace())
+ {
+ if (buf->append(STRING_WITH_LEN("CREATE OR REPLACE ")))
+ return 1;
+ }
+ else if (buf->append(STRING_WITH_LEN("CREATE ")))
return 1;
/* Append definer */
append_definer(thd, buf, &(thd->lex->definer->user), &(thd->lex->definer->host));
@@ -282,7 +291,7 @@ create_query_string(THD *thd, String *buf)
thd->lex->stmt_definition_end -
thd->lex->stmt_definition_begin))
return 1;
-
+
return 0;
}
@@ -292,8 +301,7 @@ create_query_string(THD *thd, String *buf)
@param[in,out] thd THD
@param[in] parse_data Event's data from parsing stage
- @param[in] if_not_exists Whether IF NOT EXISTS was
- specified
+
In case there is an event with the same name (db) and
IF NOT EXISTS is specified, an warning is put into the stack.
@sa Events::drop_event for the notes about locking, pre-locking
@@ -304,11 +312,11 @@ create_query_string(THD *thd, String *buf)
*/
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 ret;
- bool save_binlog_row_based, event_already_exists;
+ bool event_already_exists;
+ enum_binlog_format save_binlog_format;
DBUG_ENTER("Events::create_event");
if (check_if_system_tables_error())
@@ -327,6 +335,11 @@ Events::create_event(THD *thd, Event_parse_data *parse_data,
if (check_access(thd, EVENT_ACL, parse_data->dbname.str, NULL, NULL, 0, 0))
DBUG_RETURN(TRUE);
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+
+ if (lock_object_name(thd, MDL_key::EVENT,
+ parse_data->dbname.str, parse_data->name.str))
+ DBUG_RETURN(TRUE);
if (check_db_dir_existence(parse_data->dbname.str))
{
@@ -336,19 +349,17 @@ Events::create_event(THD *thd, Event_parse_data *parse_data,
if (parse_data->do_not_create)
DBUG_RETURN(FALSE);
- /*
- Turn off row binlogging of this statement and use statement-based
+ /*
+ Turn off row binlogging of this statement and use statement-based
so that all supporting tables are updated for CREATE EVENT command.
*/
- if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
- thd->clear_current_stmt_binlog_format_row();
+ save_binlog_format= thd->set_current_stmt_binlog_format_stmt();
- if (lock_object_name(thd, MDL_key::EVENT,
- parse_data->dbname.str, parse_data->name.str))
- DBUG_RETURN(TRUE);
+ if (thd->lex->create_info.or_replace() && event_queue)
+ event_queue->drop_event(thd, parse_data->dbname, parse_data->name);
/* On error conditions my_error() is called so no need to handle here */
- if (!(ret= db_repository->create_event(thd, parse_data, if_not_exists,
+ if (!(ret= db_repository->create_event(thd, parse_data,
&event_already_exists)))
{
Event_queue_element *new_element;
@@ -382,11 +393,14 @@ Events::create_event(THD *thd, Event_parse_data *parse_data,
{
/* Binlog the create event. */
DBUG_ASSERT(thd->query() && thd->query_length());
- String log_query;
+ char buffer[1024];
+ String log_query(buffer, sizeof(buffer), &my_charset_bin);
if (create_query_string(thd, &log_query))
{
- sql_print_error("Event Error: An error occurred while creating query "
- "string, before writing it into binary log.");
+ my_message_sql(ER_STARTUP,
+ "Event Error: An error occurred while creating query "
+ "string, before writing it into binary log.",
+ MYF(ME_NOREFRESH));
ret= true;
}
else
@@ -400,12 +414,14 @@ Events::create_event(THD *thd, Event_parse_data *parse_data,
}
}
}
- /* Restore the state of binlog format */
- DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
- if (save_binlog_row_based)
- thd->set_current_stmt_binlog_format_row();
+
+ thd->restore_stmt_binlog_format(save_binlog_format);
DBUG_RETURN(ret);
+
+WSREP_ERROR_LABEL:
+ DBUG_RETURN(TRUE);
+
}
@@ -433,7 +449,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
LEX_STRING *new_dbname, LEX_STRING *new_name)
{
int ret;
- bool save_binlog_row_based;
+ enum_binlog_format save_binlog_format;
Event_queue_element *new_element;
DBUG_ENTER("Events::update_event");
@@ -447,6 +463,19 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
if (check_access(thd, EVENT_ACL, parse_data->dbname.str, NULL, NULL, 0, 0))
DBUG_RETURN(TRUE);
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
+
+ if (lock_object_name(thd, MDL_key::EVENT,
+ parse_data->dbname.str, parse_data->name.str))
+ DBUG_RETURN(TRUE);
+
+ if (check_db_dir_existence(parse_data->dbname.str))
+ {
+ my_error(ER_BAD_DB_ERROR, MYF(0), parse_data->dbname.str);
+ DBUG_RETURN(TRUE);
+ }
+
+
if (new_dbname) /* It's a rename */
{
/* Check that the new and the old names differ. */
@@ -468,6 +497,13 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
if (check_access(thd, EVENT_ACL, new_dbname->str, NULL, NULL, 0, 0))
DBUG_RETURN(TRUE);
+ /*
+ Acquire mdl exclusive lock on target database name.
+ */
+ if (lock_object_name(thd, MDL_key::EVENT,
+ new_dbname->str, new_name->str))
+ DBUG_RETURN(TRUE);
+
/* Check that the target database exists */
if (check_db_dir_existence(new_dbname->str))
{
@@ -476,16 +512,11 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
}
}
- /*
- Turn off row binlogging of this statement and use statement-based
+ /*
+ Turn off row binlogging of this statement and use statement-based
so that all supporting tables are updated for UPDATE EVENT command.
*/
- if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
- thd->clear_current_stmt_binlog_format_row();
-
- if (lock_object_name(thd, MDL_key::EVENT,
- parse_data->dbname.str, parse_data->name.str))
- DBUG_RETURN(TRUE);
+ save_binlog_format= thd->set_current_stmt_binlog_format_stmt();
/* On error conditions my_error() is called so no need to handle here */
if (!(ret= db_repository->update_event(thd, parse_data,
@@ -515,12 +546,12 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
ret= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
}
}
- /* Restore the state of binlog format */
- DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
- if (save_binlog_row_based)
- thd->set_current_stmt_binlog_format_row();
+ thd->restore_stmt_binlog_format(save_binlog_format);
DBUG_RETURN(ret);
+
+WSREP_ERROR_LABEL:
+ DBUG_RETURN(TRUE);
}
@@ -552,7 +583,7 @@ bool
Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists)
{
int ret;
- bool save_binlog_row_based;
+ enum_binlog_format save_binlog_format;
DBUG_ENTER("Events::drop_event");
if (check_if_system_tables_error())
@@ -561,12 +592,13 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists)
if (check_access(thd, EVENT_ACL, dbname.str, NULL, NULL, 0, 0))
DBUG_RETURN(TRUE);
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
+
/*
Turn off row binlogging of this statement and use statement-based so
that all supporting tables are updated for DROP EVENT command.
*/
- if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
- thd->clear_current_stmt_binlog_format_row();
+ save_binlog_format= thd->set_current_stmt_binlog_format_stmt();
if (lock_object_name(thd, MDL_key::EVENT,
dbname.str, name.str))
@@ -580,11 +612,12 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists)
DBUG_ASSERT(thd->query() && thd->query_length());
ret= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
}
- /* Restore the state of binlog format */
- DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
- if (save_binlog_row_based)
- thd->set_current_stmt_binlog_format_row();
+
+ thd->restore_stmt_binlog_format(save_binlog_format);
DBUG_RETURN(ret);
+
+WSREP_ERROR_LABEL:
+ DBUG_RETURN(TRUE);
}
@@ -607,6 +640,8 @@ Events::drop_schema_events(THD *thd, char *db)
DBUG_ENTER("Events::drop_schema_events");
DBUG_PRINT("enter", ("dropping events from %s", db));
+ DBUG_ASSERT(ok_for_lower_case_names(db));
+
/*
Sic: no check if the scheduler is disabled or system tables
are damaged, as intended.
@@ -632,36 +667,45 @@ send_show_create_event(THD *thd, Event_timed *et, Protocol *protocol)
List<Item> field_list;
LEX_STRING sql_mode;
const String *tz_name;
-
+ MEM_ROOT *mem_root= thd->mem_root;
DBUG_ENTER("send_show_create_event");
show_str.length(0);
if (et->get_create_event(thd, &show_str))
DBUG_RETURN(TRUE);
- field_list.push_back(new Item_empty_string("Event", NAME_CHAR_LEN));
+ field_list.push_back(new (mem_root)
+ Item_empty_string(thd, "Event", NAME_CHAR_LEN),
+ mem_root);
if (sql_mode_string_representation(thd, et->sql_mode, &sql_mode))
DBUG_RETURN(TRUE);
- field_list.push_back(new Item_empty_string("sql_mode", (uint) sql_mode.length));
+ field_list.push_back(new (mem_root)
+ Item_empty_string(thd, "sql_mode",
+ (uint) sql_mode.length), mem_root);
tz_name= et->time_zone->get_name();
- field_list.push_back(new Item_empty_string("time_zone",
- tz_name->length()));
+ field_list.push_back(new (mem_root)
+ Item_empty_string(thd, "time_zone", tz_name->length()),
+ mem_root);
- field_list.push_back(new Item_empty_string("Create Event",
- show_str.length()));
+ field_list.push_back(new (mem_root)
+ Item_empty_string(thd, "Create Event",
+ show_str.length()), mem_root);
- field_list.push_back(
- new Item_empty_string("character_set_client", MY_CS_NAME_SIZE));
+ field_list.push_back(new (mem_root)
+ Item_empty_string(thd, "character_set_client",
+ MY_CS_NAME_SIZE), mem_root);
- field_list.push_back(
- new Item_empty_string("collation_connection", MY_CS_NAME_SIZE));
+ field_list.push_back(new (mem_root)
+ Item_empty_string(thd, "collation_connection",
+ MY_CS_NAME_SIZE), mem_root);
- field_list.push_back(
- new Item_empty_string("Database Collation", MY_CS_NAME_SIZE));
+ field_list.push_back(new (mem_root)
+ Item_empty_string(thd, "Database Collation",
+ MY_CS_NAME_SIZE), mem_root);
if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
@@ -760,6 +804,13 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
int ret;
DBUG_ENTER("Events::fill_schema_events");
+ /*
+ If we didn't start events because of --skip-grant-tables, return an
+ empty set
+ */
+ if (opt_noacl)
+ DBUG_RETURN(0);
+
if (check_if_system_tables_error())
DBUG_RETURN(1);
@@ -775,6 +826,9 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
NULL, NULL, 0, 0))
DBUG_RETURN(1);
db= thd->lex->select_lex.db;
+
+ if (lower_case_table_names)
+ my_casedn_str(system_charset_info, db);
}
ret= db_repository->fill_schema_events(thd, tables, db);
@@ -785,6 +839,7 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
/**
Initializes the scheduler's structures.
+ @param THD or null (if called by init)
@param opt_noacl_or_bootstrap
TRUE if there is --skip-grant-tables or --bootstrap
option. In that case we disable the event scheduler.
@@ -792,34 +847,55 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
@note This function is not synchronized.
@retval FALSE Perhaps there was an error, and the event scheduler
- is disabled. But the error is not fatal and the
+ is disabled. But the error is not fatal and the
server start up can continue.
@retval TRUE Fatal error. Startup must terminate (call unireg_abort()).
*/
bool
-Events::init(bool opt_noacl_or_bootstrap)
+Events::init(THD *thd, bool opt_noacl_or_bootstrap)
{
-
- THD *thd;
int err_no;
bool res= FALSE;
-
+ bool had_thd= thd != 0;
DBUG_ENTER("Events::init");
+ DBUG_ASSERT(inited == 0);
+
+ /*
+ Was disabled explicitly from the command line
+ */
+ if (opt_event_scheduler == Events::EVENTS_DISABLED ||
+ opt_noacl_or_bootstrap)
+ DBUG_RETURN(FALSE);
+
/* We need a temporary THD during boot */
- if (!(thd= new THD()))
+ if (!thd)
{
- res= TRUE;
- goto end;
+
+ if (!(thd= new THD()))
+ {
+ res= 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();
+ /*
+ Set current time for the thread that handles events.
+ Current time is stored in data member start_time of THD class.
+ Subsequently, this value is used to check whether event was expired
+ when make loading events from storage. Check for event expiration time
+ is done at Event_queue_element::compute_next_execution_time() where
+ event's status set to Event_parse_data::DISABLED and dropped flag set
+ to true if event was expired.
+ */
+ thd->set_time();
}
- /*
- 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();
/*
We will need Event_db_repository anyway, even if the scheduler is
@@ -840,28 +916,19 @@ Events::init(bool opt_noacl_or_bootstrap)
are most likely not there and we're going to disable the event
scheduler anyway.
*/
- if (opt_noacl_or_bootstrap || Event_db_repository::check_system_tables(thd))
+ if (Event_db_repository::check_system_tables(thd))
{
- if (! opt_noacl_or_bootstrap)
- {
- sql_print_error("Event Scheduler: An error occurred when initializing "
- "system tables. Disabling the Event Scheduler.");
- check_system_tables_error= TRUE;
- }
-
+ delete db_repository;
+ db_repository= 0;
+ my_message(ER_STARTUP,
+ "Event Scheduler: An error occurred when initializing "
+ "system tables. Disabling the Event Scheduler.",
+ MYF(ME_NOREFRESH));
/* Disable the scheduler since the system tables are not up to date */
- opt_event_scheduler= EVENTS_DISABLED;
+ opt_event_scheduler= EVENTS_OFF;
goto end;
}
- /*
- Was disabled explicitly from the command line, or because we're running
- with --skip-grant-tables, or --bootstrap, or because we have no system
- tables.
- */
- if (opt_event_scheduler == Events::EVENTS_DISABLED)
- goto end;
-
DBUG_ASSERT(opt_event_scheduler == Events::EVENTS_ON ||
opt_event_scheduler == Events::EVENTS_OFF);
@@ -876,22 +943,20 @@ Events::init(bool opt_noacl_or_bootstrap)
if (event_queue->init_queue(thd) || load_events_from_db(thd) ||
(opt_event_scheduler == EVENTS_ON && scheduler->start(&err_no)))
{
- sql_print_error("Event Scheduler: Error while loading from disk.");
+ my_message_sql(ER_STARTUP,
+ "Event Scheduler: Error while loading from mysql.event table.",
+ MYF(ME_NOREFRESH));
res= TRUE; /* fatal error: request unireg_abort */
goto end;
}
Event_worker_thread::init(db_repository);
+ inited= 1;
end:
if (res)
- {
- delete db_repository;
- delete event_queue;
- delete scheduler;
- }
- delete thd;
- /* Remember that we don't have a THD */
- my_pthread_setspecific_ptr(THR_THD, NULL);
+ deinit();
+ if (!had_thd)
+ delete thd;
DBUG_RETURN(res);
}
@@ -911,17 +976,14 @@ Events::deinit()
{
DBUG_ENTER("Events::deinit");
- if (opt_event_scheduler != EVENTS_DISABLED)
- {
- delete scheduler;
- scheduler= NULL; /* safety */
- delete event_queue;
- event_queue= NULL; /* safety */
- }
-
+ delete scheduler;
+ scheduler= NULL; /* For restart */
+ delete event_queue;
+ event_queue= NULL; /* For restart */
delete db_repository;
- db_repository= NULL; /* safety */
+ db_repository= NULL; /* For restart */
+ inited= 0;
DBUG_VOID_RETURN;
}
@@ -950,23 +1012,37 @@ static PSI_thread_info all_events_threads[]=
{ &key_thread_event_scheduler, "event_scheduler", PSI_FLAG_GLOBAL},
{ &key_thread_event_worker, "event_worker", 0}
};
+#endif /* HAVE_PSI_INTERFACE */
+
+PSI_stage_info stage_waiting_on_empty_queue= { 0, "Waiting on empty queue", 0};
+PSI_stage_info stage_waiting_for_next_activation= { 0, "Waiting for next activation", 0};
+PSI_stage_info stage_waiting_for_scheduler_to_stop= { 0, "Waiting for the scheduler to stop", 0};
+
+#ifdef HAVE_PSI_INTERFACE
+PSI_stage_info *all_events_stages[]=
+{
+ & stage_waiting_on_empty_queue,
+ & stage_waiting_for_next_activation,
+ & stage_waiting_for_scheduler_to_stop
+};
static void init_events_psi_keys(void)
{
const char* category= "sql";
int count;
- if (PSI_server == NULL)
- return;
-
count= array_elements(all_events_mutexes);
- PSI_server->register_mutex(category, all_events_mutexes, count);
+ mysql_mutex_register(category, all_events_mutexes, count);
count= array_elements(all_events_conds);
- PSI_server->register_cond(category, all_events_conds, count);
+ mysql_cond_register(category, all_events_conds, count);
count= array_elements(all_events_threads);
- PSI_server->register_thread(category, all_events_threads, count);
+ mysql_thread_register(category, all_events_threads, count);
+
+ count= array_elements(all_events_stages);
+ mysql_stage_register(category, all_events_stages, count);
+
}
#endif /* HAVE_PSI_INTERFACE */
@@ -1010,7 +1086,7 @@ Events::dump_internal_status()
holding LOCK_global_system_variables.
*/
mysql_mutex_lock(&LOCK_global_system_variables);
- if (opt_event_scheduler == EVENTS_DISABLED)
+ if (!inited)
puts("The Event Scheduler is disabled");
else
{
@@ -1024,11 +1100,13 @@ Events::dump_internal_status()
bool Events::start(int *err_no)
{
+ DBUG_ASSERT(inited);
return scheduler->start(err_no);
}
bool Events::stop()
{
+ DBUG_ASSERT(inited);
return scheduler->stop();
}
@@ -1058,7 +1136,6 @@ Events::load_events_from_db(THD *thd)
bool ret= TRUE;
uint count= 0;
ulong saved_master_access;
-
DBUG_ENTER("Events::load_events_from_db");
DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd));
@@ -1066,18 +1143,26 @@ Events::load_events_from_db(THD *thd)
NOTE: even if we run in read-only mode, we should be able to lock the
mysql.event table for writing. In order to achieve this, we should call
mysql_lock_tables() under the super user.
+
+ Same goes for transaction access mode.
+ Temporarily reset it to read-write.
*/
saved_master_access= thd->security_ctx->master_access;
thd->security_ctx->master_access |= SUPER_ACL;
+ bool save_tx_read_only= thd->tx_read_only;
+ thd->tx_read_only= false;
ret= db_repository->open_event_table(thd, TL_WRITE, &table);
+ thd->tx_read_only= save_tx_read_only;
thd->security_ctx->master_access= saved_master_access;
if (ret)
{
- sql_print_error("Event Scheduler: Failed to open table mysql.event");
+ my_message_sql(ER_STARTUP,
+ "Event Scheduler: Failed to open table mysql.event",
+ MYF(ME_NOREFRESH));
DBUG_RETURN(TRUE);
}
@@ -1090,8 +1175,7 @@ Events::load_events_from_db(THD *thd)
while (!(read_record_info.read_record(&read_record_info)))
{
Event_queue_element *et;
- bool created;
- bool drop_on_completion;
+ bool created, dropped;
if (!(et= new Event_queue_element))
goto end;
@@ -1100,16 +1184,20 @@ Events::load_events_from_db(THD *thd)
if (et->load_from_row(thd, table))
{
- sql_print_error("Event Scheduler: "
- "Error while loading events from mysql.event. "
- "The table probably contains bad data or is corrupted");
+ my_message(ER_STARTUP,
+ "Event Scheduler: "
+ "Error while loading events from mysql.event. "
+ "The table probably contains bad data or is corrupted",
+ MYF(ME_NOREFRESH));
delete et;
goto end;
}
- drop_on_completion= (et->on_completion ==
- Event_parse_data::ON_COMPLETION_DROP);
-
-
+ /**
+ Since the Event_queue_element object could be deleted inside
+ Event_queue::create_event we should save the value of dropped flag
+ into the temporary variable.
+ */
+ dropped= et->dropped;
if (event_queue->create_event(thd, et, &created))
{
/* Out of memory */
@@ -1118,7 +1206,7 @@ Events::load_events_from_db(THD *thd)
}
if (created)
count++;
- else if (drop_on_completion)
+ else if (dropped)
{
/*
If not created, a stale event - drop if immediately if
@@ -1137,9 +1225,12 @@ Events::load_events_from_db(THD *thd)
}
}
}
- if (global_system_variables.log_warnings)
- sql_print_information("Event Scheduler: Loaded %d event%s",
- count, (count == 1) ? "" : "s");
+ my_printf_error(ER_STARTUP,
+ "Event Scheduler: Loaded %d event%s",
+ MYF(ME_NOREFRESH |
+ (global_system_variables.log_warnings) ?
+ ME_JUST_INFO: 0),
+ count, (count == 1) ? "" : "s");
ret= FALSE;
end:
@@ -1149,6 +1240,21 @@ end:
DBUG_RETURN(ret);
}
+#ifdef WITH_WSREP
+int wsrep_create_event_query(THD *thd, uchar** buf, size_t* buf_len)
+{
+ char buffer[1024];
+ String log_query(buffer, sizeof(buffer), &my_charset_bin);
+
+ if (create_query_string(thd, &log_query))
+ {
+ WSREP_WARN("events create string failed: schema: %s, query: %s",
+ (thd->db ? thd->db : "(null)"), thd->query());
+ return 1;
+ }
+ return wsrep_to_buf_helper(thd, log_query.ptr(), log_query.length(), buf, buf_len);
+}
+#endif /* WITH_WSREP */
/**
@} (End of group Event_Scheduler)
*/