summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libmysqld/Makefile.am4
-rw-r--r--mysql-test/r/events_embedded.result2
-rw-r--r--mysql-test/r/is_embedded.require2
-rw-r--r--mysql-test/t/events_embedded.test5
-rw-r--r--mysql-test/t/events_trans.test2
-rw-r--r--sql/Makefile.am5
-rw-r--r--sql/event_data_objects.cc559
-rw-r--r--sql/event_data_objects.h99
-rw-r--r--sql/event_parse_data.cc535
-rw-r--r--sql/event_parse_data.h116
-rw-r--r--sql/event_queue.cc18
-rw-r--r--sql/events.cc4
-rw-r--r--sql/mysqld.cc6
-rw-r--r--sql/set_var.cc8
-rw-r--r--sql/set_var.h3
-rw-r--r--sql/sql_db.cc2
-rw-r--r--sql/sql_parse.cc10
-rw-r--r--sql/sql_show.cc18
-rw-r--r--sql/sql_test.cc4
-rw-r--r--sql/sql_yacc.yy13
20 files changed, 745 insertions, 670 deletions
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
index c2f342367dd..504980cbd07 100644
--- a/libmysqld/Makefile.am
+++ b/libmysqld/Makefile.am
@@ -73,12 +73,10 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
spatial.cc gstream.cc sql_help.cc tztime.cc sql_cursor.cc \
sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \
parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
- event_scheduler.cc events.cc event_data_objects.cc \
- event_queue.cc event_db_repository.cc \
rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
sql_tablespace.cc \
rpl_injector.cc my_user.c partition_info.cc \
- sql_servers.cc
+ sql_servers.cc event_parse_data.cc
libmysqld_int_a_SOURCES= $(libmysqld_sources)
nodist_libmysqld_int_a_SOURCES= $(libmysqlsources) $(sqlsources)
diff --git a/mysql-test/r/events_embedded.result b/mysql-test/r/events_embedded.result
new file mode 100644
index 00000000000..1a02188f2df
--- /dev/null
+++ b/mysql-test/r/events_embedded.result
@@ -0,0 +1,2 @@
+set global event_scheduler=ON;
+ERROR HY000: Unknown system variable 'event_scheduler'
diff --git a/mysql-test/r/is_embedded.require b/mysql-test/r/is_embedded.require
new file mode 100644
index 00000000000..10594809fe7
--- /dev/null
+++ b/mysql-test/r/is_embedded.require
@@ -0,0 +1,2 @@
+have_embedded
+1
diff --git a/mysql-test/t/events_embedded.test b/mysql-test/t/events_embedded.test
new file mode 100644
index 00000000000..9922ea6dfee
--- /dev/null
+++ b/mysql-test/t/events_embedded.test
@@ -0,0 +1,5 @@
+--source include/is_embedded.inc
+
+--error 1193
+set global event_scheduler=ON;
+
diff --git a/mysql-test/t/events_trans.test b/mysql-test/t/events_trans.test
index 562b5a9625f..a94b75bb812 100644
--- a/mysql-test/t/events_trans.test
+++ b/mysql-test/t/events_trans.test
@@ -2,6 +2,8 @@
# Tests that require transactions
#
-- source include/have_innodb.inc
+-- source include/not_embedded.inc
+
--disable_warnings
drop database if exists events_test;
drop database if exists mysqltest_no_such_database;
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 33664b77957..5b5f7aa1c5d 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -73,7 +73,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
parse_file.h sql_view.h sql_trigger.h \
sql_array.h sql_cursor.h events.h scheduler.h \
event_db_repository.h event_queue.h \
- sql_plugin.h authors.h \
+ sql_plugin.h authors.h event_parse_data.h \
event_data_objects.h event_scheduler.h \
sql_partition.h partition_info.h partition_element.h \
contributors.h sql_servers.h
@@ -120,7 +120,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
event_queue.cc event_db_repository.cc events.cc \
sql_plugin.cc sql_binlog.cc \
sql_builtin.cc sql_tablespace.cc partition_info.cc \
- sql_servers.cc
+ sql_servers.cc event_parse_data.cc
nodist_mysqld_SOURCES = mini_client_errors.c pack.c client.c my_time.c my_user.c
@@ -140,6 +140,7 @@ DEFS = -DMYSQL_SERVER \
-DDATADIR="\"$(MYSQLDATAdir)\"" \
-DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
-DPLUGINDIR="\"$(pkgplugindir)\"" \
+ -DHAVE_EVENT_SCHEDULER \
@DEFS@
BUILT_MAINT_SRC = sql_yacc.cc sql_yacc.h
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc
index f4b64ab3012..dd47b8dd916 100644
--- a/sql/event_data_objects.cc
+++ b/sql/event_data_objects.cc
@@ -25,8 +25,6 @@
@{
*/
-#define EVEX_MAX_INTERVAL_VALUE 1000000000L
-
/*************************************************************************/
/**
@@ -188,524 +186,6 @@ Event_queue_element_for_exec::~Event_queue_element_for_exec()
/*
- Returns a new instance
-
- SYNOPSIS
- Event_parse_data::new_instance()
-
- RETURN VALUE
- Address or NULL in case of error
-
- NOTE
- Created on THD's mem_root
-*/
-
-Event_parse_data *
-Event_parse_data::new_instance(THD *thd)
-{
- return new (thd->mem_root) Event_parse_data;
-}
-
-
-/*
- Constructor
-
- SYNOPSIS
- Event_parse_data::Event_parse_data()
-*/
-
-Event_parse_data::Event_parse_data()
- :on_completion(Event_basic::ON_COMPLETION_DROP),
- status(Event_basic::ENABLED),
- do_not_create(FALSE),
- body_changed(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)
-{
- DBUG_ENTER("Event_parse_data::Event_parse_data");
-
- /* Actually in the parser STARTS is always set */
- starts= ends= execute_at= 0;
-
- comment.str= NULL;
- comment.length= 0;
-
- DBUG_VOID_RETURN;
-}
-
-
-/*
- Set a name of the event
-
- SYNOPSIS
- Event_parse_data::init_name()
- thd THD
- spn the name extracted in the parser
-*/
-
-void
-Event_parse_data::init_name(THD *thd, sp_name *spn)
-{
- DBUG_ENTER("Event_parse_data::init_name");
-
- /* We have to copy strings to get them into the right memroot */
- dbname.length= spn->m_db.length;
- dbname.str= thd->strmake(spn->m_db.str, spn->m_db.length);
- name.length= spn->m_name.length;
- name.str= thd->strmake(spn->m_name.str, spn->m_name.length);
-
- if (spn->m_qname.length == 0)
- spn->init_qname(thd);
-
- DBUG_VOID_RETURN;
-}
-
-
-/*
- This function is called on CREATE EVENT or ALTER EVENT. When either
- ENDS or AT is in the past, we are trying to create an event that
- will never be executed. If it has ON COMPLETION NOT PRESERVE
- (default), then it would normally be dropped already, so on CREATE
- EVENT we give a warning, and do not create anyting. On ALTER EVENT
- we give a error, and do not change the event.
-
- If the event has ON COMPLETION PRESERVE, then we see if the event is
- created or altered to the ENABLED (default) state. If so, then we
- give a warning, and change the state to DISABLED.
-
- Otherwise it is a valid event in ON COMPLETION PRESERVE DISABLE
- state.
-*/
-
-void
-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 == Event_basic::ON_COMPLETION_DROP)
- {
- switch (thd->lex->sql_command) {
- case SQLCOM_CREATE_EVENT:
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
- ER_EVENT_CANNOT_CREATE_IN_THE_PAST,
- ER(ER_EVENT_CANNOT_CREATE_IN_THE_PAST));
- break;
- case SQLCOM_ALTER_EVENT:
- my_error(ER_EVENT_CANNOT_ALTER_IN_THE_PAST, MYF(0));
- break;
- default:
- DBUG_ASSERT(0);
- }
-
- do_not_create= TRUE;
- }
- else if (status == Event_basic::ENABLED)
- {
- 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));
- }
-}
-
-
-/*
- Sets time for execution for one-time event.
-
- SYNOPSIS
- Event_parse_data::init_execute_at()
- thd Thread
-
- RETURN VALUE
- 0 OK
- ER_WRONG_VALUE Wrong value for execute at (reported)
-*/
-
-int
-Event_parse_data::init_execute_at(THD *thd)
-{
- my_bool not_used;
- MYSQL_TIME ltime;
- my_time_t ltime_utc;
-
- DBUG_ENTER("Event_parse_data::init_execute_at");
-
- if (!item_execute_at)
- DBUG_RETURN(0);
-
- if (item_execute_at->fix_fields(thd, &item_execute_at))
- goto wrong_value;
-
- /* no starts and/or ends in case of execute_at */
- DBUG_PRINT("info", ("starts_null && ends_null should be 1 is %d",
- (starts_null && ends_null)));
- DBUG_ASSERT(starts_null && ends_null);
-
- if ((not_used= item_execute_at->get_date(&ltime, TIME_NO_ZERO_DATE)))
- goto wrong_value;
-
- ltime_utc= TIME_to_timestamp(thd,&ltime,&not_used);
- if (!ltime_utc)
- {
- DBUG_PRINT("error", ("Execute AT after year 2037"));
- goto wrong_value;
- }
-
- check_if_in_the_past(thd, ltime_utc);
-
- execute_at_null= FALSE;
- execute_at= ltime_utc;
- DBUG_RETURN(0);
-
-wrong_value:
- report_bad_value("AT", item_execute_at);
- DBUG_RETURN(ER_WRONG_VALUE);
-}
-
-
-/*
- Sets time for execution of multi-time event.s
-
- SYNOPSIS
- Event_parse_data::init_interval()
- thd Thread
-
- RETURN VALUE
- 0 OK
- EVEX_BAD_PARAMS Interval is not positive or MICROSECOND (reported)
- ER_WRONG_VALUE Wrong value for interval (reported)
-*/
-
-int
-Event_parse_data::init_interval(THD *thd)
-{
- String value;
- INTERVAL interval_tmp;
-
- DBUG_ENTER("Event_parse_data::init_interval");
- if (!item_expression)
- DBUG_RETURN(0);
-
- switch (interval) {
- case INTERVAL_MINUTE_MICROSECOND:
- case INTERVAL_HOUR_MICROSECOND:
- case INTERVAL_DAY_MICROSECOND:
- case INTERVAL_SECOND_MICROSECOND:
- case INTERVAL_MICROSECOND:
- my_error(ER_NOT_SUPPORTED_YET, MYF(0), "MICROSECOND");
- DBUG_RETURN(EVEX_BAD_PARAMS);
- default:
- break;
- }
-
- if (item_expression->fix_fields(thd, &item_expression))
- goto wrong_value;
-
- value.alloc(MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN);
- if (get_interval_value(item_expression, interval, &value, &interval_tmp))
- goto wrong_value;
-
- expression= 0;
-
- switch (interval) {
- case INTERVAL_YEAR:
- expression= interval_tmp.year;
- break;
- case INTERVAL_QUARTER:
- case INTERVAL_MONTH:
- expression= interval_tmp.month;
- break;
- case INTERVAL_WEEK:
- case INTERVAL_DAY:
- expression= interval_tmp.day;
- break;
- case INTERVAL_HOUR:
- expression= interval_tmp.hour;
- break;
- case INTERVAL_MINUTE:
- expression= interval_tmp.minute;
- break;
- case INTERVAL_SECOND:
- expression= interval_tmp.second;
- break;
- case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM
- expression= interval_tmp.year* 12 + interval_tmp.month;
- break;
- case INTERVAL_DAY_HOUR:
- expression= interval_tmp.day* 24 + interval_tmp.hour;
- break;
- case INTERVAL_DAY_MINUTE:
- expression= (interval_tmp.day* 24 + interval_tmp.hour) * 60 +
- interval_tmp.minute;
- break;
- case INTERVAL_HOUR_SECOND: /* day is anyway 0 */
- case INTERVAL_DAY_SECOND:
- /* DAY_SECOND having problems because of leap seconds? */
- expression= ((interval_tmp.day* 24 + interval_tmp.hour) * 60 +
- interval_tmp.minute)*60
- + interval_tmp.second;
- break;
- case INTERVAL_HOUR_MINUTE:
- expression= interval_tmp.hour * 60 + interval_tmp.minute;
- break;
- case INTERVAL_MINUTE_SECOND:
- expression= interval_tmp.minute * 60 + interval_tmp.second;
- break;
- case INTERVAL_LAST:
- DBUG_ASSERT(0);
- default:
- ;/* these are the microsec stuff */
- }
- if (interval_tmp.neg || expression == 0 ||
- expression > EVEX_MAX_INTERVAL_VALUE)
- {
- my_error(ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG, MYF(0));
- DBUG_RETURN(EVEX_BAD_PARAMS);
- }
-
- DBUG_RETURN(0);
-
-wrong_value:
- report_bad_value("INTERVAL", item_expression);
- DBUG_RETURN(ER_WRONG_VALUE);
-}
-
-
-/*
- Sets STARTS.
-
- SYNOPSIS
- Event_parse_data::init_starts()
- expr how much?
-
- NOTES
- Note that activation time is not execution time.
- EVERY 5 MINUTE STARTS "2004-12-12 10:00:00" means that
- the event will be executed every 5 minutes but this will
- start at the date shown above. Expressions are possible :
- DATE_ADD(NOW(), INTERVAL 1 DAY) -- start tommorow at
- same time.
-
- RETURN VALUE
- 0 OK
- ER_WRONG_VALUE Starts before now
-*/
-
-int
-Event_parse_data::init_starts(THD *thd)
-{
- my_bool not_used;
- MYSQL_TIME ltime;
- my_time_t ltime_utc;
-
- DBUG_ENTER("Event_parse_data::init_starts");
- if (!item_starts)
- DBUG_RETURN(0);
-
- if (item_starts->fix_fields(thd, &item_starts))
- goto wrong_value;
-
- if ((not_used= item_starts->get_date(&ltime, TIME_NO_ZERO_DATE)))
- goto wrong_value;
-
- ltime_utc= TIME_to_timestamp(thd, &ltime, &not_used);
- if (!ltime_utc)
- goto wrong_value;
-
- DBUG_PRINT("info",("now: %ld starts: %ld",
- (long) thd->query_start(), (long) ltime_utc));
-
- starts_null= FALSE;
- starts= ltime_utc;
- DBUG_RETURN(0);
-
-wrong_value:
- report_bad_value("STARTS", item_starts);
- DBUG_RETURN(ER_WRONG_VALUE);
-}
-
-
-/*
- Sets ENDS (deactivation time).
-
- SYNOPSIS
- Event_parse_data::init_ends()
- thd THD
-
- NOTES
- Note that activation time is not execution time.
- EVERY 5 MINUTE ENDS "2004-12-12 10:00:00" means that
- the event will be executed every 5 minutes but this will
- end at the date shown above. Expressions are possible :
- DATE_ADD(NOW(), INTERVAL 1 DAY) -- end tommorow at
- same time.
-
- RETURN VALUE
- 0 OK
- EVEX_BAD_PARAMS Error (reported)
-*/
-
-int
-Event_parse_data::init_ends(THD *thd)
-{
- my_bool not_used;
- MYSQL_TIME ltime;
- my_time_t ltime_utc;
-
- DBUG_ENTER("Event_parse_data::init_ends");
- if (!item_ends)
- DBUG_RETURN(0);
-
- if (item_ends->fix_fields(thd, &item_ends))
- goto error_bad_params;
-
- DBUG_PRINT("info", ("convert to TIME"));
- if ((not_used= item_ends->get_date(&ltime, TIME_NO_ZERO_DATE)))
- goto error_bad_params;
-
- ltime_utc= TIME_to_timestamp(thd, &ltime, &not_used);
- if (!ltime_utc)
- goto error_bad_params;
-
- /* Check whether ends is after starts */
- DBUG_PRINT("info", ("ENDS after STARTS?"));
- if (!starts_null && starts >= ltime_utc)
- goto error_bad_params;
-
- check_if_in_the_past(thd, ltime_utc);
-
- ends_null= FALSE;
- ends= ltime_utc;
- DBUG_RETURN(0);
-
-error_bad_params:
- my_error(ER_EVENT_ENDS_BEFORE_STARTS, MYF(0));
- DBUG_RETURN(EVEX_BAD_PARAMS);
-}
-
-
-/*
- Prints an error message about invalid value. Internally used
- during input data verification
-
- SYNOPSIS
- Event_parse_data::report_bad_value()
- item_name The name of the parameter
- bad_item The parameter
-*/
-
-void
-Event_parse_data::report_bad_value(const char *item_name, Item *bad_item)
-{
- char buff[120];
- String str(buff,(uint32) sizeof(buff), system_charset_info);
- String *str2= bad_item->fixed? bad_item->val_str(&str):NULL;
- my_error(ER_WRONG_VALUE, MYF(0), item_name, str2? str2->c_ptr_safe():"NULL");
-}
-
-
-/*
- Checks for validity the data gathered during the parsing phase.
-
- SYNOPSIS
- Event_parse_data::check_parse_data()
- thd Thread
-
- RETURN VALUE
- FALSE OK
- TRUE Error (reported)
-*/
-
-bool
-Event_parse_data::check_parse_data(THD *thd)
-{
- bool ret;
- DBUG_ENTER("Event_parse_data::check_parse_data");
- DBUG_PRINT("info", ("execute_at: 0x%lx expr=0x%lx starts=0x%lx ends=0x%lx",
- (long) item_execute_at, (long) item_expression,
- (long) item_starts, (long) item_ends));
-
- init_name(thd, identifier);
-
- init_definer(thd);
-
- ret= init_execute_at(thd) || init_interval(thd) || init_starts(thd) ||
- init_ends(thd);
- check_originator_id(thd);
- DBUG_RETURN(ret);
-}
-
-
-/*
- Inits definer (definer_user and definer_host) during parsing.
-
- SYNOPSIS
- Event_parse_data::init_definer()
- thd Thread
-*/
-
-void
-Event_parse_data::init_definer(THD *thd)
-{
- DBUG_ENTER("Event_parse_data::init_definer");
-
- DBUG_ASSERT(thd->lex->definer);
-
- const char *definer_user= thd->lex->definer->user.str;
- const char *definer_host= thd->lex->definer->host.str;
- int definer_user_len= thd->lex->definer->user.length;
- int definer_host_len= thd->lex->definer->host.length;
-
- DBUG_PRINT("info",("init definer_user thd->mem_root: 0x%lx "
- "definer_user: 0x%lx", (long) thd->mem_root,
- (long) definer_user));
-
- /* + 1 for @ */
- DBUG_PRINT("info",("init definer as whole"));
- definer.length= definer_user_len + definer_host_len + 1;
- definer.str= (char*) thd->alloc(definer.length + 1);
-
- DBUG_PRINT("info",("copy the user"));
- memcpy(definer.str, definer_user, definer_user_len);
- definer.str[definer_user_len]= '@';
-
- DBUG_PRINT("info",("copy the host"));
- memcpy(definer.str + definer_user_len + 1, definer_host, definer_host_len);
- definer.str[definer.length]= '\0';
- DBUG_PRINT("info",("definer [%s] initted", definer.str));
-
- DBUG_VOID_RETURN;
-}
-
-
-/**
- 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
SYNOPSIS
@@ -799,8 +279,9 @@ Event_basic::load_time_zone(THD *thd, const LEX_STRING tz_name)
Event_queue_element::Event_queue_element():
status_changed(FALSE), last_executed_changed(FALSE),
- on_completion(ON_COMPLETION_DROP), status(ENABLED),
- expression(0), dropped(FALSE), execution_count(0)
+ on_completion(Event_parse_data::ON_COMPLETION_DROP),
+ status(Event_parse_data::ENABLED), expression(0), dropped(FALSE),
+ execution_count(0)
{
DBUG_ENTER("Event_queue_element::Event_queue_element");
@@ -1057,14 +538,14 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
switch (ptr[0])
{
case 'E' :
- status = Event_queue_element::ENABLED;
+ status = Event_parse_data::ENABLED;
break;
case 'S' :
- status = Event_queue_element::SLAVESIDE_DISABLED;
+ status = Event_parse_data::SLAVESIDE_DISABLED;
break;
case 'D' :
default:
- status = Event_queue_element::DISABLED;
+ status = Event_parse_data::DISABLED;
break;
}
if ((ptr= get_field(&mem_root, table->field[ET_FIELD_ORIGINATOR])) == NullS)
@@ -1076,8 +557,8 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
table->field[ET_FIELD_ON_COMPLETION])) == NullS)
DBUG_RETURN(TRUE);
- on_completion= (ptr[0]=='D'? Event_queue_element::ON_COMPLETION_DROP:
- Event_queue_element::ON_COMPLETION_PRESERVE);
+ on_completion= (ptr[0]=='D'? Event_parse_data::ON_COMPLETION_DROP:
+ Event_parse_data::ON_COMPLETION_PRESERVE);
DBUG_RETURN(FALSE);
}
@@ -1423,7 +904,7 @@ Event_queue_element::compute_next_execution_time()
(long) starts, (long) ends, (long) last_executed,
(long) this));
- if (status != Event_queue_element::ENABLED)
+ if (status != Event_parse_data::ENABLED)
{
DBUG_PRINT("compute_next_execution_time",
("Event %s is DISABLED", name.str));
@@ -1437,10 +918,10 @@ Event_queue_element::compute_next_execution_time()
{
DBUG_PRINT("info",("One-time event %s.%s of was already executed",
dbname.str, name.str));
- dropped= (on_completion == Event_queue_element::ON_COMPLETION_DROP);
+ dropped= (on_completion == Event_parse_data::ON_COMPLETION_DROP);
DBUG_PRINT("info",("One-time event will be dropped: %d.", dropped));
- status= Event_queue_element::DISABLED;
+ status= Event_parse_data::DISABLED;
status_changed= TRUE;
}
goto ret;
@@ -1457,10 +938,10 @@ Event_queue_element::compute_next_execution_time()
/* time_now is after ends. don't execute anymore */
execute_at= 0;
execute_at_null= TRUE;
- if (on_completion == Event_queue_element::ON_COMPLETION_DROP)
+ if (on_completion == Event_parse_data::ON_COMPLETION_DROP)
dropped= TRUE;
DBUG_PRINT("info", ("Dropped: %d", dropped));
- status= Event_queue_element::DISABLED;
+ status= Event_parse_data::DISABLED;
status_changed= TRUE;
goto ret;
@@ -1521,9 +1002,9 @@ Event_queue_element::compute_next_execution_time()
/* Next execution after ends. No more executions */
execute_at= 0;
execute_at_null= TRUE;
- if (on_completion == Event_queue_element::ON_COMPLETION_DROP)
+ if (on_completion == Event_parse_data::ON_COMPLETION_DROP)
dropped= TRUE;
- status= Event_queue_element::DISABLED;
+ status= Event_parse_data::DISABLED;
status_changed= TRUE;
}
else
@@ -1613,9 +1094,9 @@ Event_queue_element::compute_next_execution_time()
DBUG_PRINT("info", ("Next execution after ENDS. Stop executing."));
execute_at= 0;
execute_at_null= TRUE;
- status= Event_queue_element::DISABLED;
+ status= Event_parse_data::DISABLED;
status_changed= TRUE;
- if (on_completion == Event_queue_element::ON_COMPLETION_DROP)
+ if (on_completion == Event_parse_data::ON_COMPLETION_DROP)
dropped= TRUE;
}
else
@@ -1767,14 +1248,14 @@ Event_timed::get_create_event(THD *thd, String *buf)
STRING_WITH_LEN("ON SCHEDULE AT"));
}
- if (on_completion == Event_timed::ON_COMPLETION_DROP)
+ if (on_completion == Event_parse_data::ON_COMPLETION_DROP)
buf->append(STRING_WITH_LEN(" ON COMPLETION NOT PRESERVE "));
else
buf->append(STRING_WITH_LEN(" ON COMPLETION PRESERVE "));
- if (status == Event_timed::ENABLED)
+ if (status == Event_parse_data::ENABLED)
buf->append(STRING_WITH_LEN("ENABLE"));
- else if (status == Event_timed::SLAVESIDE_DISABLED)
+ else if (status == Event_parse_data::SLAVESIDE_DISABLED)
buf->append(STRING_WITH_LEN("DISABLE ON SLAVE"));
else
buf->append(STRING_WITH_LEN("DISABLE"));
diff --git a/sql/event_data_objects.h b/sql/event_data_objects.h
index 7a49d1597d6..e32077b9c97 100644
--- a/sql/event_data_objects.h
+++ b/sql/event_data_objects.h
@@ -22,10 +22,7 @@
@file event_data_objects.h
*/
-#define EVEX_GET_FIELD_FAILED -2
-#define EVEX_BAD_PARAMS -5
-#define EVEX_MICROSECOND_UNSUP -6
-
+#include "event_parse_data.h"
class Event_queue_element_for_exec
{
@@ -54,23 +51,6 @@ protected:
MEM_ROOT mem_root;
public:
- /*
- ENABLED = feature can function normally (is turned on)
- SLAVESIDE_DISABLED = feature is turned off on slave
- DISABLED = feature is turned off
- */
- enum enum_status
- {
- ENABLED = 1,
- DISABLED,
- SLAVESIDE_DISABLED
- };
-
- enum enum_on_completion
- {
- ON_COMPLETION_DROP = 1,
- ON_COMPLETION_PRESERVE
- };
LEX_STRING dbname;
LEX_STRING name;
@@ -201,83 +181,6 @@ private:
};
-class Event_parse_data : public Sql_alloc
-{
-public:
-
- int on_completion;
- int status;
- longlong originator;
- /*
- do_not_create will be set if STARTS time is in the past and
- on_completion == ON_COMPLETION_DROP.
- */
- bool do_not_create;
-
- bool body_changed;
-
- LEX_STRING dbname;
- LEX_STRING name;
- LEX_STRING definer;// combination of user and host
- LEX_STRING comment;
-
- Item* item_starts;
- Item* item_ends;
- Item* item_execute_at;
-
- my_time_t starts;
- my_time_t ends;
- my_time_t execute_at;
- my_bool starts_null;
- my_bool ends_null;
- my_bool execute_at_null;
-
- sp_name *identifier;
- Item* item_expression;
- longlong expression;
- interval_type interval;
-
- static Event_parse_data *
- new_instance(THD *thd);
-
- bool
- check_parse_data(THD *thd);
-
-private:
-
- void
- init_definer(THD *thd);
-
- void
- init_name(THD *thd, sp_name *spn);
-
- int
- init_execute_at(THD *thd);
-
- int
- init_interval(THD *thd);
-
- int
- init_starts(THD *thd);
-
- int
- init_ends(THD *thd);
-
- Event_parse_data();
- ~Event_parse_data();
-
- void
- report_bad_value(const char *item_name, Item *bad_item);
-
- void
- check_if_in_the_past(THD *thd, my_time_t ltime_utc);
-
- Event_parse_data(const Event_parse_data &); /* Prevent use of these */
- void check_originator_id(THD *thd);
- void operator=(Event_parse_data &);
-};
-
-
/* Compares only the schema part of the identifier */
bool
event_basic_db_equal(LEX_STRING db, Event_basic *et);
diff --git a/sql/event_parse_data.cc b/sql/event_parse_data.cc
new file mode 100644
index 00000000000..e87e4593f8f
--- /dev/null
+++ b/sql/event_parse_data.cc
@@ -0,0 +1,535 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "mysql_priv.h"
+#include "sp_head.h"
+#include "event_parse_data.h"
+
+/*
+ Returns a new instance
+
+ SYNOPSIS
+ Event_parse_data::new_instance()
+
+ RETURN VALUE
+ Address or NULL in case of error
+
+ NOTE
+ Created on THD's mem_root
+*/
+
+Event_parse_data *
+Event_parse_data::new_instance(THD *thd)
+{
+ return new (thd->mem_root) Event_parse_data;
+}
+
+
+/*
+ Constructor
+
+ SYNOPSIS
+ Event_parse_data::Event_parse_data()
+*/
+
+Event_parse_data::Event_parse_data()
+ :on_completion(Event_parse_data::ON_COMPLETION_DROP),
+ status(Event_parse_data::ENABLED),
+ do_not_create(FALSE),
+ body_changed(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)
+{
+ DBUG_ENTER("Event_parse_data::Event_parse_data");
+
+ /* Actually in the parser STARTS is always set */
+ starts= ends= execute_at= 0;
+
+ comment.str= NULL;
+ comment.length= 0;
+
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Set a name of the event
+
+ SYNOPSIS
+ Event_parse_data::init_name()
+ thd THD
+ spn the name extracted in the parser
+*/
+
+void
+Event_parse_data::init_name(THD *thd, sp_name *spn)
+{
+ DBUG_ENTER("Event_parse_data::init_name");
+
+ /* We have to copy strings to get them into the right memroot */
+ dbname.length= spn->m_db.length;
+ dbname.str= thd->strmake(spn->m_db.str, spn->m_db.length);
+ name.length= spn->m_name.length;
+ name.str= thd->strmake(spn->m_name.str, spn->m_name.length);
+
+ if (spn->m_qname.length == 0)
+ spn->init_qname(thd);
+
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ This function is called on CREATE EVENT or ALTER EVENT. When either
+ ENDS or AT is in the past, we are trying to create an event that
+ will never be executed. If it has ON COMPLETION NOT PRESERVE
+ (default), then it would normally be dropped already, so on CREATE
+ EVENT we give a warning, and do not create anyting. On ALTER EVENT
+ we give a error, and do not change the event.
+
+ If the event has ON COMPLETION PRESERVE, then we see if the event is
+ created or altered to the ENABLED (default) state. If so, then we
+ give a warning, and change the state to DISABLED.
+
+ Otherwise it is a valid event in ON COMPLETION PRESERVE DISABLE
+ state.
+*/
+
+void
+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 == Event_parse_data::ON_COMPLETION_DROP)
+ {
+ switch (thd->lex->sql_command) {
+ case SQLCOM_CREATE_EVENT:
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_EVENT_CANNOT_CREATE_IN_THE_PAST,
+ ER(ER_EVENT_CANNOT_CREATE_IN_THE_PAST));
+ break;
+ case SQLCOM_ALTER_EVENT:
+ my_error(ER_EVENT_CANNOT_ALTER_IN_THE_PAST, MYF(0));
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+
+ do_not_create= TRUE;
+ }
+ else if (status == Event_parse_data::ENABLED)
+ {
+ status= Event_parse_data::DISABLED;
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_EVENT_EXEC_TIME_IN_THE_PAST,
+ ER(ER_EVENT_EXEC_TIME_IN_THE_PAST));
+ }
+}
+
+
+/*
+ Sets time for execution for one-time event.
+
+ SYNOPSIS
+ Event_parse_data::init_execute_at()
+ thd Thread
+
+ RETURN VALUE
+ 0 OK
+ ER_WRONG_VALUE Wrong value for execute at (reported)
+*/
+
+int
+Event_parse_data::init_execute_at(THD *thd)
+{
+ my_bool not_used;
+ MYSQL_TIME ltime;
+ my_time_t ltime_utc;
+
+ DBUG_ENTER("Event_parse_data::init_execute_at");
+
+ if (!item_execute_at)
+ DBUG_RETURN(0);
+
+ if (item_execute_at->fix_fields(thd, &item_execute_at))
+ goto wrong_value;
+
+ /* no starts and/or ends in case of execute_at */
+ DBUG_PRINT("info", ("starts_null && ends_null should be 1 is %d",
+ (starts_null && ends_null)));
+ DBUG_ASSERT(starts_null && ends_null);
+
+ if ((not_used= item_execute_at->get_date(&ltime, TIME_NO_ZERO_DATE)))
+ goto wrong_value;
+
+ ltime_utc= TIME_to_timestamp(thd,&ltime,&not_used);
+ if (!ltime_utc)
+ {
+ DBUG_PRINT("error", ("Execute AT after year 2037"));
+ goto wrong_value;
+ }
+
+ check_if_in_the_past(thd, ltime_utc);
+
+ execute_at_null= FALSE;
+ execute_at= ltime_utc;
+ DBUG_RETURN(0);
+
+wrong_value:
+ report_bad_value("AT", item_execute_at);
+ DBUG_RETURN(ER_WRONG_VALUE);
+}
+
+
+/*
+ Sets time for execution of multi-time event.s
+
+ SYNOPSIS
+ Event_parse_data::init_interval()
+ thd Thread
+
+ RETURN VALUE
+ 0 OK
+ EVEX_BAD_PARAMS Interval is not positive or MICROSECOND (reported)
+ ER_WRONG_VALUE Wrong value for interval (reported)
+*/
+
+int
+Event_parse_data::init_interval(THD *thd)
+{
+ String value;
+ INTERVAL interval_tmp;
+
+ DBUG_ENTER("Event_parse_data::init_interval");
+ if (!item_expression)
+ DBUG_RETURN(0);
+
+ switch (interval) {
+ case INTERVAL_MINUTE_MICROSECOND:
+ case INTERVAL_HOUR_MICROSECOND:
+ case INTERVAL_DAY_MICROSECOND:
+ case INTERVAL_SECOND_MICROSECOND:
+ case INTERVAL_MICROSECOND:
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "MICROSECOND");
+ DBUG_RETURN(EVEX_BAD_PARAMS);
+ default:
+ break;
+ }
+
+ if (item_expression->fix_fields(thd, &item_expression))
+ goto wrong_value;
+
+ value.alloc(MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN);
+ if (get_interval_value(item_expression, interval, &value, &interval_tmp))
+ goto wrong_value;
+
+ expression= 0;
+
+ switch (interval) {
+ case INTERVAL_YEAR:
+ expression= interval_tmp.year;
+ break;
+ case INTERVAL_QUARTER:
+ case INTERVAL_MONTH:
+ expression= interval_tmp.month;
+ break;
+ case INTERVAL_WEEK:
+ case INTERVAL_DAY:
+ expression= interval_tmp.day;
+ break;
+ case INTERVAL_HOUR:
+ expression= interval_tmp.hour;
+ break;
+ case INTERVAL_MINUTE:
+ expression= interval_tmp.minute;
+ break;
+ case INTERVAL_SECOND:
+ expression= interval_tmp.second;
+ break;
+ case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM
+ expression= interval_tmp.year* 12 + interval_tmp.month;
+ break;
+ case INTERVAL_DAY_HOUR:
+ expression= interval_tmp.day* 24 + interval_tmp.hour;
+ break;
+ case INTERVAL_DAY_MINUTE:
+ expression= (interval_tmp.day* 24 + interval_tmp.hour) * 60 +
+ interval_tmp.minute;
+ break;
+ case INTERVAL_HOUR_SECOND: /* day is anyway 0 */
+ case INTERVAL_DAY_SECOND:
+ /* DAY_SECOND having problems because of leap seconds? */
+ expression= ((interval_tmp.day* 24 + interval_tmp.hour) * 60 +
+ interval_tmp.minute)*60
+ + interval_tmp.second;
+ break;
+ case INTERVAL_HOUR_MINUTE:
+ expression= interval_tmp.hour * 60 + interval_tmp.minute;
+ break;
+ case INTERVAL_MINUTE_SECOND:
+ expression= interval_tmp.minute * 60 + interval_tmp.second;
+ break;
+ case INTERVAL_LAST:
+ DBUG_ASSERT(0);
+ default:
+ ;/* these are the microsec stuff */
+ }
+ if (interval_tmp.neg || expression == 0 ||
+ expression > EVEX_MAX_INTERVAL_VALUE)
+ {
+ my_error(ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG, MYF(0));
+ DBUG_RETURN(EVEX_BAD_PARAMS);
+ }
+
+ DBUG_RETURN(0);
+
+wrong_value:
+ report_bad_value("INTERVAL", item_expression);
+ DBUG_RETURN(ER_WRONG_VALUE);
+}
+
+
+/*
+ Sets STARTS.
+
+ SYNOPSIS
+ Event_parse_data::init_starts()
+ expr how much?
+
+ NOTES
+ Note that activation time is not execution time.
+ EVERY 5 MINUTE STARTS "2004-12-12 10:00:00" means that
+ the event will be executed every 5 minutes but this will
+ start at the date shown above. Expressions are possible :
+ DATE_ADD(NOW(), INTERVAL 1 DAY) -- start tommorow at
+ same time.
+
+ RETURN VALUE
+ 0 OK
+ ER_WRONG_VALUE Starts before now
+*/
+
+int
+Event_parse_data::init_starts(THD *thd)
+{
+ my_bool not_used;
+ MYSQL_TIME ltime;
+ my_time_t ltime_utc;
+
+ DBUG_ENTER("Event_parse_data::init_starts");
+ if (!item_starts)
+ DBUG_RETURN(0);
+
+ if (item_starts->fix_fields(thd, &item_starts))
+ goto wrong_value;
+
+ if ((not_used= item_starts->get_date(&ltime, TIME_NO_ZERO_DATE)))
+ goto wrong_value;
+
+ ltime_utc= TIME_to_timestamp(thd, &ltime, &not_used);
+ if (!ltime_utc)
+ goto wrong_value;
+
+ DBUG_PRINT("info",("now: %ld starts: %ld",
+ (long) thd->query_start(), (long) ltime_utc));
+
+ starts_null= FALSE;
+ starts= ltime_utc;
+ DBUG_RETURN(0);
+
+wrong_value:
+ report_bad_value("STARTS", item_starts);
+ DBUG_RETURN(ER_WRONG_VALUE);
+}
+
+
+/*
+ Sets ENDS (deactivation time).
+
+ SYNOPSIS
+ Event_parse_data::init_ends()
+ thd THD
+
+ NOTES
+ Note that activation time is not execution time.
+ EVERY 5 MINUTE ENDS "2004-12-12 10:00:00" means that
+ the event will be executed every 5 minutes but this will
+ end at the date shown above. Expressions are possible :
+ DATE_ADD(NOW(), INTERVAL 1 DAY) -- end tommorow at
+ same time.
+
+ RETURN VALUE
+ 0 OK
+ EVEX_BAD_PARAMS Error (reported)
+*/
+
+int
+Event_parse_data::init_ends(THD *thd)
+{
+ my_bool not_used;
+ MYSQL_TIME ltime;
+ my_time_t ltime_utc;
+
+ DBUG_ENTER("Event_parse_data::init_ends");
+ if (!item_ends)
+ DBUG_RETURN(0);
+
+ if (item_ends->fix_fields(thd, &item_ends))
+ goto error_bad_params;
+
+ DBUG_PRINT("info", ("convert to TIME"));
+ if ((not_used= item_ends->get_date(&ltime, TIME_NO_ZERO_DATE)))
+ goto error_bad_params;
+
+ ltime_utc= TIME_to_timestamp(thd, &ltime, &not_used);
+ if (!ltime_utc)
+ goto error_bad_params;
+
+ /* Check whether ends is after starts */
+ DBUG_PRINT("info", ("ENDS after STARTS?"));
+ if (!starts_null && starts >= ltime_utc)
+ goto error_bad_params;
+
+ check_if_in_the_past(thd, ltime_utc);
+
+ ends_null= FALSE;
+ ends= ltime_utc;
+ DBUG_RETURN(0);
+
+error_bad_params:
+ my_error(ER_EVENT_ENDS_BEFORE_STARTS, MYF(0));
+ DBUG_RETURN(EVEX_BAD_PARAMS);
+}
+
+
+/*
+ Prints an error message about invalid value. Internally used
+ during input data verification
+
+ SYNOPSIS
+ Event_parse_data::report_bad_value()
+ item_name The name of the parameter
+ bad_item The parameter
+*/
+
+void
+Event_parse_data::report_bad_value(const char *item_name, Item *bad_item)
+{
+ char buff[120];
+ String str(buff,(uint32) sizeof(buff), system_charset_info);
+ String *str2= bad_item->fixed? bad_item->val_str(&str):NULL;
+ my_error(ER_WRONG_VALUE, MYF(0), item_name, str2? str2->c_ptr_safe():"NULL");
+}
+
+
+/*
+ Checks for validity the data gathered during the parsing phase.
+
+ SYNOPSIS
+ Event_parse_data::check_parse_data()
+ thd Thread
+
+ RETURN VALUE
+ FALSE OK
+ TRUE Error (reported)
+*/
+
+bool
+Event_parse_data::check_parse_data(THD *thd)
+{
+ bool ret;
+ DBUG_ENTER("Event_parse_data::check_parse_data");
+ DBUG_PRINT("info", ("execute_at: 0x%lx expr=0x%lx starts=0x%lx ends=0x%lx",
+ (long) item_execute_at, (long) item_expression,
+ (long) item_starts, (long) item_ends));
+
+ init_name(thd, identifier);
+
+ init_definer(thd);
+
+ ret= init_execute_at(thd) || init_interval(thd) || init_starts(thd) ||
+ init_ends(thd);
+ check_originator_id(thd);
+ DBUG_RETURN(ret);
+}
+
+
+/*
+ Inits definer (definer_user and definer_host) during parsing.
+
+ SYNOPSIS
+ Event_parse_data::init_definer()
+ thd Thread
+*/
+
+void
+Event_parse_data::init_definer(THD *thd)
+{
+ DBUG_ENTER("Event_parse_data::init_definer");
+
+ DBUG_ASSERT(thd->lex->definer);
+
+ const char *definer_user= thd->lex->definer->user.str;
+ const char *definer_host= thd->lex->definer->host.str;
+ int definer_user_len= thd->lex->definer->user.length;
+ int definer_host_len= thd->lex->definer->host.length;
+
+ DBUG_PRINT("info",("init definer_user thd->mem_root: 0x%lx "
+ "definer_user: 0x%lx", (long) thd->mem_root,
+ (long) definer_user));
+
+ /* + 1 for @ */
+ DBUG_PRINT("info",("init definer as whole"));
+ definer.length= definer_user_len + definer_host_len + 1;
+ definer.str= (char*) thd->alloc(definer.length + 1);
+
+ DBUG_PRINT("info",("copy the user"));
+ memcpy(definer.str, definer_user, definer_user_len);
+ definer.str[definer_user_len]= '@';
+
+ DBUG_PRINT("info",("copy the host"));
+ memcpy(definer.str + definer_user_len + 1, definer_host, definer_host_len);
+ definer.str[definer.length]= '\0';
+ DBUG_PRINT("info",("definer [%s] initted", definer.str));
+
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ 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_parse_data::ENABLED) ||
+ (status == Event_parse_data::DISABLED))
+ status = Event_parse_data::SLAVESIDE_DISABLED;
+ originator = thd->server_id;
+ }
+ else
+ originator = server_id;
+}
diff --git a/sql/event_parse_data.h b/sql/event_parse_data.h
new file mode 100644
index 00000000000..221bf92664f
--- /dev/null
+++ b/sql/event_parse_data.h
@@ -0,0 +1,116 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef _EVENT_PARSE_DATA_H_
+#define _EVENT_PARSE_DATA_H_
+
+#define EVEX_GET_FIELD_FAILED -2
+#define EVEX_BAD_PARAMS -5
+#define EVEX_MICROSECOND_UNSUP -6
+#define EVEX_MAX_INTERVAL_VALUE 1000000000L
+
+class Event_parse_data : public Sql_alloc
+{
+public:
+ /*
+ ENABLED = feature can function normally (is turned on)
+ SLAVESIDE_DISABLED = feature is turned off on slave
+ DISABLED = feature is turned off
+ */
+ enum enum_status
+ {
+ ENABLED = 1,
+ DISABLED,
+ SLAVESIDE_DISABLED
+ };
+
+ enum enum_on_completion
+ {
+ ON_COMPLETION_DROP = 1,
+ ON_COMPLETION_PRESERVE
+ };
+
+ int on_completion;
+ int status;
+ longlong originator;
+ /*
+ do_not_create will be set if STARTS time is in the past and
+ on_completion == ON_COMPLETION_DROP.
+ */
+ bool do_not_create;
+
+ bool body_changed;
+
+ LEX_STRING dbname;
+ LEX_STRING name;
+ LEX_STRING definer;// combination of user and host
+ LEX_STRING comment;
+
+ Item* item_starts;
+ Item* item_ends;
+ Item* item_execute_at;
+
+ my_time_t starts;
+ my_time_t ends;
+ my_time_t execute_at;
+ my_bool starts_null;
+ my_bool ends_null;
+ my_bool execute_at_null;
+
+ sp_name *identifier;
+ Item* item_expression;
+ longlong expression;
+ interval_type interval;
+
+ static Event_parse_data *
+ new_instance(THD *thd);
+
+ bool
+ check_parse_data(THD *thd);
+
+private:
+
+ void
+ init_definer(THD *thd);
+
+ void
+ init_name(THD *thd, sp_name *spn);
+
+ int
+ init_execute_at(THD *thd);
+
+ int
+ init_interval(THD *thd);
+
+ int
+ init_starts(THD *thd);
+
+ int
+ init_ends(THD *thd);
+
+ Event_parse_data();
+ ~Event_parse_data();
+
+ void
+ report_bad_value(const char *item_name, Item *bad_item);
+
+ void
+ check_if_in_the_past(THD *thd, my_time_t ltime_utc);
+
+ Event_parse_data(const Event_parse_data &); /* Prevent use of these */
+ void check_originator_id(THD *thd);
+ void operator=(Event_parse_data &);
+};
+#endif
diff --git a/sql/event_queue.cc b/sql/event_queue.cc
index 719a837cbfb..04d4f858b43 100644
--- a/sql/event_queue.cc
+++ b/sql/event_queue.cc
@@ -65,10 +65,10 @@ int event_queue_element_compare_q(void *vptr, uchar* a, uchar *b)
my_time_t lhs = left->execute_at;
my_time_t rhs = right->execute_at;
- if (left->status == Event_queue_element::DISABLED)
- return right->status != Event_queue_element::DISABLED;
+ if (left->status == Event_parse_data::DISABLED)
+ return right->status != Event_parse_data::DISABLED;
- if (right->status == Event_queue_element::DISABLED)
+ if (right->status == Event_parse_data::DISABLED)
return 1;
return (lhs < rhs ? -1 : (lhs > rhs ? 1 : 0));
@@ -198,7 +198,7 @@ Event_queue::create_event(THD *thd, Event_queue_element *new_element,
/* Will do nothing if the event is disabled */
new_element->compute_next_execution_time();
- if (new_element->status != Event_queue_element::ENABLED)
+ if (new_element->status != Event_parse_data::ENABLED)
{
delete new_element;
*created= FALSE;
@@ -236,8 +236,8 @@ Event_queue::update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
DBUG_ENTER("Event_queue::update_event");
DBUG_PRINT("enter", ("thd: 0x%lx et=[%s.%s]", (long) thd, dbname.str, name.str));
- if ((new_element->status == Event_queue_element::DISABLED) ||
- (new_element->status == Event_queue_element::SLAVESIDE_DISABLED))
+ if ((new_element->status == Event_parse_data::DISABLED) ||
+ (new_element->status == Event_parse_data::SLAVESIDE_DISABLED))
{
DBUG_PRINT("info", ("The event is disabled."));
/*
@@ -452,7 +452,7 @@ Event_queue::recalculate_activation_times(THD *thd)
for (i= queue.elements; i > 0; i--)
{
Event_queue_element *element = (Event_queue_element*)queue_element(&queue, i - 1);
- if (element->status != Event_queue_element::DISABLED)
+ if (element->status != Event_parse_data::DISABLED)
break;
/*
This won't cause queue re-order, because we remove
@@ -615,14 +615,14 @@ Event_queue::get_top_for_execution_if_time(THD *thd,
DBUG_PRINT("info", ("Ready for execution"));
top->mark_last_executed(thd);
if (top->compute_next_execution_time())
- top->status= Event_queue_element::DISABLED;
+ top->status= Event_parse_data::DISABLED;
DBUG_PRINT("info", ("event %s status is %d", top->name.str, top->status));
top->execution_count++;
(*event_name)->dropped= top->dropped;
top->update_timing_fields(thd);
- if (top->status == Event_queue_element::DISABLED)
+ if (top->status == Event_parse_data::DISABLED)
{
DBUG_PRINT("info", ("removing from the queue"));
sql_print_information("Event Scheduler: Last execution of %s.%s. %s",
diff --git a/sql/events.cc b/sql/events.cc
index 4225ca055de..a98c1c90298 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -861,6 +861,7 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
bool
Events::init(my_bool opt_noacl)
{
+
THD *thd;
bool res= FALSE;
@@ -954,7 +955,6 @@ end:
DBUG_RETURN(res);
}
-
/*
Cleans up scheduler's resources. Called at server shutdown.
@@ -1170,7 +1170,7 @@ Events::load_events_from_db(THD *thd)
goto end;
}
drop_on_completion= (et->on_completion ==
- Event_queue_element::ON_COMPLETION_DROP);
+ Event_parse_data::ON_COMPLETION_DROP);
if (event_queue->create_event(thd, et, &created))
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index f619899f3b1..0c1ad3ffc69 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -3498,7 +3498,9 @@ static int init_thread_environment()
(void) pthread_mutex_init(&LOCK_server_started, MY_MUTEX_INIT_FAST);
(void) pthread_cond_init(&COND_server_started,NULL);
sp_cache_init();
+#ifdef HAVE_EVENT_SCHEDULER
Events::init_mutexes();
+#endif
/* Parameter for threads created for connections */
(void) pthread_attr_init(&connection_attrib);
(void) pthread_attr_setdetachstate(&connection_attrib,
@@ -7831,8 +7833,12 @@ mysqld_get_one_option(int optid,
}
#endif
case OPT_EVENT_SCHEDULER:
+#ifndef HAVE_EVENT_SCHEDULER
+ sql_perror("Event scheduler is not supported in embedded build.");
+#else
if (Events::set_opt_event_scheduler(argument))
exit(1);
+#endif
break;
case (int) OPT_SKIP_NEW:
opt_specialflag|= SPECIAL_NO_NEW_FUNC;
diff --git a/sql/set_var.cc b/sql/set_var.cc
index b4b81ba2fbe..fd81dc1a867 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -241,7 +241,10 @@ static sys_var_long_ptr sys_delayed_insert_timeout(&vars, "delayed_insert_timeou
static sys_var_long_ptr sys_delayed_queue_size(&vars, "delayed_queue_size",
&delayed_queue_size);
+#ifdef HAVE_EVENT_SCHEDULER
static sys_var_event_scheduler sys_event_scheduler(&vars, "event_scheduler");
+#endif
+
static sys_var_long_ptr sys_expire_logs_days(&vars, "expire_logs_days",
&expire_logs_days);
static sys_var_bool_ptr sys_flush(&vars, "flush", &myisam_flush);
@@ -4026,13 +4029,12 @@ uchar *sys_var_thd_dbug::value_ptr(THD *thd, enum_var_type type, LEX_STRING *b)
return (uchar*) thd->strdup(buf);
}
-
+#ifdef HAVE_EVENT_SCHEDULER
bool sys_var_event_scheduler::check(THD *thd, set_var *var)
{
return check_enum(thd, var, &Events::var_typelib);
}
-
/*
The update method of the global variable event_scheduler.
If event_scheduler is switched from 0 to 1 then the scheduler main
@@ -4071,7 +4073,7 @@ uchar *sys_var_event_scheduler::value_ptr(THD *thd, enum_var_type type,
{
return (uchar *) Events::get_opt_event_scheduler_str();
}
-
+#endif
/****************************************************************************
Used templates
diff --git a/sql/set_var.h b/sql/set_var.h
index b33a3a968bb..290d1bf0eb1 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -1085,7 +1085,7 @@ public:
virtual void set_default(THD *thd, enum_var_type type);
};
-
+#ifdef HAVE_EVENT_SCHEDULER
class sys_var_event_scheduler :public sys_var_long_ptr
{
/* We need a derived class only to have a warn_deprecated() */
@@ -1101,6 +1101,7 @@ public:
return type != STRING_RESULT && type != INT_RESULT;
}
};
+#endif
extern void fix_binlog_format_after_update(THD *thd, enum_var_type type);
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 2c7e0e82b3c..bb55f5f7a4f 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -922,7 +922,9 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
ha_drop_database(path);
query_cache_invalidate1(db);
(void) sp_drop_db_routines(thd, db); /* @todo Do not ignore errors */
+#ifdef HAVE_EVENT_SCHEDULER
Events::drop_schema_events(thd, db);
+#endif
error = 0;
}
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index f2e8d713371..ddcec92a0d3 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1998,7 +1998,12 @@ mysql_execute_command(THD *thd)
DBUG_ASSERT(thd->transaction.stmt.modified_non_trans_table == FALSE);
switch (lex->sql_command) {
+
case SQLCOM_SHOW_EVENTS:
+#ifndef HAVE_EVENT_SCHEDULER
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "embedded server");
+ break;
+#endif
case SQLCOM_SHOW_STATUS_PROC:
case SQLCOM_SHOW_STATUS_FUNC:
res= execute_sqlcom_select(thd, all_tables);
@@ -3483,6 +3488,7 @@ end_with_restore_list:
}
case SQLCOM_CREATE_EVENT:
case SQLCOM_ALTER_EVENT:
+ #ifdef HAVE_EVENT_SCHEDULER
do
{
DBUG_ASSERT(lex->event_parse_data);
@@ -3536,6 +3542,10 @@ end_with_restore_list:
lex->drop_if_exists)))
my_ok(thd);
break;
+#else
+ my_error(ER_NOT_SUPPORTED_YET,MYF(0),"embedded server");
+ break;
+#endif
case SQLCOM_CREATE_FUNCTION: // UDF function
{
if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0))
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index b005615ce7c..57280f39199 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -25,8 +25,10 @@
#include "sql_trigger.h"
#include "authors.h"
#include "contributors.h"
+#ifdef HAVE_EVENT_SCHEDULER
#include "events.h"
#include "event_data_objects.h"
+#endif
#include <my_dir.h>
#define STR_OR_NIL(S) ((S) ? (S) : "<nil>")
@@ -287,7 +289,9 @@ static struct show_privileges_st sys_privileges[]=
{"Create user", "Server Admin", "To create new users"},
{"Delete", "Tables", "To delete existing rows"},
{"Drop", "Databases,Tables", "To drop databases, tables, and views"},
+#ifdef HAVE_EVENT_SCHEDULER
{"Event","Server Admin","To create, alter, drop and execute events"},
+#endif
{"Execute", "Functions,Procedures", "To execute stored routines"},
{"File", "File access on server", "To read and write files on the server"},
{"Grant option", "Databases,Tables,Functions,Procedures", "To give to other users those privileges you possess"},
@@ -4959,7 +4963,7 @@ static interval_type get_real_interval_type(interval_type i_type)
#endif
-
+#ifdef HAVE_EVENT_SCHEDULER
/*
Loads an event from mysql.event and copies it's data to a row of
I_S.EVENTS
@@ -5079,14 +5083,14 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
switch (et.status)
{
- case Event_timed::ENABLED:
+ case Event_parse_data::ENABLED:
sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("ENABLED"), scs);
break;
- case Event_timed::SLAVESIDE_DISABLED:
+ case Event_parse_data::SLAVESIDE_DISABLED:
sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("SLAVESIDE_DISABLED"),
scs);
break;
- case Event_timed::DISABLED:
+ case Event_parse_data::DISABLED:
sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("DISABLED"), scs);
break;
default:
@@ -5095,7 +5099,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
sch_table->field[ISE_ORIGINATOR]->store(et.originator, TRUE);
/* on_completion */
- if (et.on_completion == Event_timed::ON_COMPLETION_DROP)
+ if (et.on_completion == Event_parse_data::ON_COMPLETION_DROP)
sch_table->field[ISE_ON_COMPLETION]->
store(STRING_WITH_LEN("NOT PRESERVE"), scs);
else
@@ -5145,7 +5149,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
DBUG_RETURN(0);
}
-
+#endif
int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond)
{
@@ -6541,8 +6545,10 @@ ST_SCHEMA_TABLE schema_tables[]=
fill_schema_column_privileges, 0, 0, -1, -1, 0, 0},
{"ENGINES", engines_fields_info, create_schema_table,
fill_schema_engines, make_old_format, 0, -1, -1, 0, 0},
+#ifdef HAVE_EVENT_SCHEDULER
{"EVENTS", events_fields_info, create_schema_table,
Events::fill_schema_events, make_old_format, 0, -1, -1, 0, 0},
+#endif
{"FILES", files_fields_info, create_schema_table,
fill_schema_files, 0, 0, -1, -1, 0, 0},
{"GLOBAL_STATUS", variables_fields_info, create_schema_table,
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index 1a522b852e9..01363714484 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -27,7 +27,9 @@
#include <sys/malloc.h>
#endif
+#ifdef HAVE_EVENT_SCHEDULER
#include "events.h"
+#endif
static const char *lock_descriptions[] =
{
@@ -539,6 +541,8 @@ Estimated memory (with thread stack): %ld\n",
(long) (thread_count * my_thread_stack_size + info.hblkhd + info.arena));
#endif
+#ifdef HAVE_EVENT_SCHEDULER
Events::dump_internal_status();
+#endif
puts("");
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 0e5240fea10..47ee742ffb5 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -42,7 +42,7 @@
#include "sp_pcontext.h"
#include "sp_rcontext.h"
#include "sp.h"
-#include "event_data_objects.h"
+#include "event_parse_data.h"
#include <myisam.h>
#include <myisammrg.h>
@@ -1783,7 +1783,6 @@ event_tail:
LEX *lex=Lex;
lex->create_info.options= $2;
-
if (!(lex->event_parse_data= Event_parse_data::new_instance(thd)))
MYSQL_YYABORT;
lex->event_parse_data->identifier= $3;
@@ -1840,17 +1839,17 @@ opt_ev_status:
/* empty */ { $$= 0; }
| ENABLE_SYM
{
- Lex->event_parse_data->status= Event_basic::ENABLED;
+ Lex->event_parse_data->status= Event_parse_data::ENABLED;
$$= 1;
}
| DISABLE_SYM ON SLAVE
{
- Lex->event_parse_data->status= Event_basic::SLAVESIDE_DISABLED;
+ Lex->event_parse_data->status= Event_parse_data::SLAVESIDE_DISABLED;
$$= 1;
}
| DISABLE_SYM
{
- Lex->event_parse_data->status= Event_basic::DISABLED;
+ Lex->event_parse_data->status= Event_parse_data::DISABLED;
$$= 1;
}
;
@@ -1883,13 +1882,13 @@ ev_on_completion:
ON COMPLETION_SYM PRESERVE_SYM
{
Lex->event_parse_data->on_completion=
- Event_basic::ON_COMPLETION_PRESERVE;
+ Event_parse_data::ON_COMPLETION_PRESERVE;
$$= 1;
}
| ON COMPLETION_SYM NOT_SYM PRESERVE_SYM
{
Lex->event_parse_data->on_completion=
- Event_basic::ON_COMPLETION_DROP;
+ Event_parse_data::ON_COMPLETION_DROP;
$$= 1;
}
;