diff options
-rw-r--r-- | libmysqld/Makefile.am | 4 | ||||
-rw-r--r-- | mysql-test/r/events_embedded.result | 2 | ||||
-rw-r--r-- | mysql-test/r/is_embedded.require | 2 | ||||
-rw-r--r-- | mysql-test/t/events_embedded.test | 5 | ||||
-rw-r--r-- | mysql-test/t/events_trans.test | 2 | ||||
-rw-r--r-- | sql/Makefile.am | 5 | ||||
-rw-r--r-- | sql/event_data_objects.cc | 559 | ||||
-rw-r--r-- | sql/event_data_objects.h | 99 | ||||
-rw-r--r-- | sql/event_parse_data.cc | 535 | ||||
-rw-r--r-- | sql/event_parse_data.h | 116 | ||||
-rw-r--r-- | sql/event_queue.cc | 18 | ||||
-rw-r--r-- | sql/events.cc | 4 | ||||
-rw-r--r-- | sql/mysqld.cc | 6 | ||||
-rw-r--r-- | sql/set_var.cc | 8 | ||||
-rw-r--r-- | sql/set_var.h | 3 | ||||
-rw-r--r-- | sql/sql_db.cc | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 10 | ||||
-rw-r--r-- | sql/sql_show.cc | 18 | ||||
-rw-r--r-- | sql/sql_test.cc | 4 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 13 |
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(<ime, TIME_NO_ZERO_DATE))) - goto wrong_value; - - ltime_utc= TIME_to_timestamp(thd,<ime,¬_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(<ime, TIME_NO_ZERO_DATE))) - goto wrong_value; - - ltime_utc= TIME_to_timestamp(thd, <ime, ¬_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(<ime, TIME_NO_ZERO_DATE))) - goto error_bad_params; - - ltime_utc= TIME_to_timestamp(thd, <ime, ¬_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(<ime, TIME_NO_ZERO_DATE))) + goto wrong_value; + + ltime_utc= TIME_to_timestamp(thd,<ime,¬_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(<ime, TIME_NO_ZERO_DATE))) + goto wrong_value; + + ltime_utc= TIME_to_timestamp(thd, <ime, ¬_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(<ime, TIME_NO_ZERO_DATE))) + goto error_bad_params; + + ltime_utc= TIME_to_timestamp(thd, <ime, ¬_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; } ; |