2011-07-04 01:25:49 +02:00
|
|
|
/*
|
2011-11-21 18:13:14 +01:00
|
|
|
Copyright (c) 2008, 2011, Oracle and/or its affiliates.
|
2008-05-09 09:43:02 +02:00
|
|
|
|
|
|
|
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
|
2011-06-30 17:46:53 +02:00
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
2008-05-09 09:43:02 +02:00
|
|
|
|
2017-06-18 05:42:16 +02:00
|
|
|
#include "mariadb.h"
|
2010-03-31 16:05:33 +02:00
|
|
|
#include "sql_priv.h"
|
|
|
|
#include "unireg.h"
|
2008-05-09 09:43:02 +02:00
|
|
|
#include "sp_head.h"
|
|
|
|
#include "event_parse_data.h"
|
2010-03-31 16:05:33 +02:00
|
|
|
#include "sql_time.h" // TIME_to_timestamp
|
2008-05-09 09:43:02 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
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()
|
Bug#35981: ALTER EVENT causes the server to change the PRESERVE option.
If [NOT] PRESERVE was not given, parser always defaulted to NOT
PRESERVE, making it impossible for the "not given = no change"
rule to work in ALTER EVENT. Leaving out the PRESERVE-clause
defaults to NOT PRESERVE on CREATE now, and to "no change" in
ALTER.
mysql-test/r/events_2.result:
show that giving no PRESERVE-clause to ALTER EVENT
results in no change. show that giving no PRESERVE-clause
to CREATE EVENT defaults to NOT PRESERVE as per the docs.
Show specifically that this is also handled correctly when
trying to ALTER EVENTs into the past.
mysql-test/t/events_2.test:
show that giving no PRESERVE-clause to ALTER EVENT
results in no change. show that giving no PRESERVE-clause
to CREATE EVENT defaults to NOT PRESERVE as per the docs.
Show specifically that this is also handled correctly when
trying to ALTER EVENTs into the past.
sql/event_db_repository.cc:
If ALTER EVENT was given no PRESERVE-clause (meaning "no change"),
we don't know the previous PRESERVE-setting by the time we check
the parse-data. If ALTER EVENT was given dates that are in the past,
we don't know how to react, lacking the PRESERVE-setting. Heal this
by running the check later when we have actually read the previous
EVENT-data.
sql/event_parse_data.cc:
Change default for ON COMPLETION to indicate, "not specified."
Also defer throwing errors when ALTER EVENT is given dates in
the past but not PRESERVE-clause until we know the previous
PRESERVE-value.
sql/event_parse_data.h:
Add third state for ON COMPLETION [NOT] PRESERVE (preserve,
don't, not specified).
Make check_dates() public so we can defer this check until
deeper in the callstack where we have all the required data.
sql/sql_yacc.yy:
If CREATE EVENT is not given ON COMPLETION [NOT] PRESERVE,
we default to NOT, as per the docs.
2008-08-18 13:05:51 +02:00
|
|
|
:on_completion(Event_parse_data::ON_COMPLETION_DEFAULT),
|
2011-06-09 19:03:17 +02:00
|
|
|
status(Event_parse_data::ENABLED), status_changed(false),
|
|
|
|
do_not_create(FALSE), body_changed(FALSE),
|
2008-05-09 09:43:02 +02:00
|
|
|
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);
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
wl#173 - temporal types with sub-second resolution
and collateral changes.
* introduce my_hrtime_t, my_timediff_t, and conversion macros
* inroduce TIME_RESULT, but it can only be returned from Item::cmp_type(),
never from Item::result_type()
* pack_time/unpack_time function for "packed" representation of
MYSQL_TIME in a longlong that can be compared
* ADDTIME()/SUBTIME()/+- INTERVAL now work with TIME values
* numbers aren't quoted in EXPLAIN EXTENDED
* new column I_S.COLUMNS.DATETIME_PRECISION
* date/time values are compares to anything as date/time, not as strings or numbers.
* old timestamp(X) is no longer supported
* MYSQL_TIME to string conversion functions take precision as an argument
* unified the warnings from Field_timestamp/datetime/time/date/newdate store methods
* Field_timestamp_hires, Field_datetime_hires, Field_time_hires
* Field_temporal
* Lazy_string class to pass a value (string, number, time) polymorphically down the stack
* make_truncated_value_warning and Field::set_datetime_warning use Lazy_string as an argument, removed char*/int/double variants
* removed Field::can_be_compared_as_longlong(). Use Field::cmp_type() == INT_RESULT instead
* introduced Item::cmp_result() instead of Item::is_datetime() and Item::result_as_longlong()
* in many cases date/time types are treated like other types, not as special cases
* greatly simplified Arg_comparator (regarding date/time/year code)
* SEC_TO_TIME is real function, not integer.
* microsecond precision in NOW, CURTIME, etc
* Item_temporal. All items derived from it only provide get_date, but no val* methods
* replication of NOW(6)
* Protocol::store(time) now takes the precision as an argument
* @@TIMESTAMP is a double
client/mysqlbinlog.cc:
remove unneded casts
include/my_sys.h:
introduce my_hrtime_t, my_timediff_t, and conversion macros
include/my_time.h:
pack_time/unpack_time, etc.
convenience functions to work with MYSQL_TIME::second_part
libmysql/libmysql.c:
str_to_time() is gone. str_to_datetime() does it now.
my_TIME_to_str() takes the precision as an argument
mysql-test/include/ps_conv.inc:
time is not equal to datetime anymore
mysql-test/r/distinct.result:
a test for an old MySQL bug
mysql-test/r/explain.result:
numbers aren't quoted in EXPLAIN EXTENDED
mysql-test/r/func_default.result:
numbers aren't quoted in EXPLAIN EXTENDED
mysql-test/r/func_sapdb.result:
when decimals=NOT_FIXED_DEC it means "not fixed" indeed
mysql-test/r/func_test.result:
numbers aren't quoted in EXPLAIN EXTENDED
mysql-test/r/func_time.result:
ADDTIME()/SUBTIME()/+- INTERVAL now work with TIME values
mysql-test/r/having.result:
numbers aren't quoted in EXPLAIN EXTENDED
mysql-test/r/information_schema.result:
new column I_S.COLUMNS.DATETIME_PRECISION
mysql-test/r/join_outer.result:
numbers aren't quoted in EXPLAIN EXTENDED
mysql-test/r/metadata.result:
TIMESTAMP no longer has zerofill flag
mysql-test/r/range.result:
invalid datetime is not compared with as a string
mysql-test/r/select.result:
NO_ZERO_IN_DATE, etc only affect storage - according to the manual
numbers aren't quoted in EXPLAIN EXTENDED
mysql-test/r/subselect.result:
numbers aren't quoted in EXPLAIN EXTENDED
mysql-test/r/sysdate_is_now.result:
when decimals=NOT_FIXED_DEC it means "not fixed" indeed
mysql-test/r/type_blob.result:
TIMESTAMP(N) is not deprecated
mysql-test/r/type_timestamp.result:
old TIMESTAMP(X) semantics is not supported anymore
mysql-test/r/union.result:
numbers aren't quoted in EXPLAIN EXTENDED
mysql-test/r/varbinary.result:
numbers aren't quoted in EXPLAIN EXTENDED
mysql-test/t/distinct.test:
test for an old MySQL bug
mysql-test/t/func_time.test:
+- INTERVAL now works with TIME values
mysql-test/t/select.test:
typo
mysql-test/t/subselect.test:
only one error per statement, please
mysql-test/t/system_mysql_db_fix40123.test:
old timestamp(X) is no longer supported
mysql-test/t/system_mysql_db_fix50030.test:
old timestamp(X) is no longer supported
mysql-test/t/system_mysql_db_fix50117.test:
old timestamp(X) is no longer supported
mysql-test/t/type_blob.test:
old timestamp(X) is no longer supported
mysql-test/t/type_timestamp.test:
old timestamp(X) is no longer supported
mysys/my_getsystime.c:
functions to get the time with microsecond precision
mysys/my_init.c:
move the my_getsystime.c initialization code to my_getsystime.c
mysys/my_static.c:
no need to make these variables extern
mysys/my_static.h:
no need to make these variables extern
scripts/mysql_system_tables.sql:
old timestamp(X) is no longer supported
scripts/mysql_system_tables_fix.sql:
old timestamp(X) is no longer supported
scripts/mysqlhotcopy.sh:
old timestamp(X) is no longer supported
sql-common/my_time.c:
* call str_to_time from str_to_datetime, as appropriate
* date/time to string conversions take precision as an argument
* number_to_time()
* TIME_to_double()
* pack_time() and unpack_time()
sql/event_data_objects.cc:
cast is not needed
my_datetime_to_str() takes precision as an argument
sql/event_db_repository.cc:
avoid dangerous downcast (because the pointer is
not always Field_timestamp, see events_1.test)
sql/event_queue.cc:
avoid silly double-work for cond_wait
(having an endpoint of wait, subtract the current time to get the timeout,
and use set_timespec() macro to fill in struct timespec, by adding the current
time to the timeout)
sql/field.cc:
* remove virtual Field::get_time(), everyone should use only Field::get_date()
* remove lots of #ifdef WORDS_BIGENDIAN
* unified the warnings from Field_timestamp/datetime/time/date/newdate store methods
* Field_timestamp_hires, Field_datetime_hires, Field_time_hires
* Field_temporal
* make_truncated_value_warning and Field::set_datetime_warning use Lazy_string as an argument, removed char*/int/double variants
sql/field.h:
* remove virtual Field::get_time(), everyone should use only Field::get_date()
* remove lots of #ifdef WORDS_BIGENDIAN
* unified the warnings from Field_timestamp/datetime/time/date/newdate store methods
* Field_timestamp_hires, Field_datetime_hires, Field_time_hires
* Field_temporal
* make_truncated_value_warning and Field::set_datetime_warning use Lazy_string as an argument, removed char*/int/double variants
* removed Field::can_be_compared_as_longlong(). Use Field::cmp_type() == INT_RESULT instead
sql/filesort.cc:
TIME_RESULT, cmp_time()
sql/item.cc:
* numbers aren't quoted in EXPLAIN EXTENDED
* Item::cmp_result() instead of Item::is_datetime() and Item::result_as_longlong()
* virtual Item::get_time() is gone
* Item_param::field_type() is set correctly
* Item_datetime, for a datetime constant
* time to anything is compared as a time
* Item_cache::print() prints the value is available
* bug fixed in Item_cache_int::val_str()
sql/item.h:
* Item::print_value(), to be used from Item_xxx::print() when needed
* Item::cmp_result() instead of Item::is_datetime() and Item::result_as_longlong()
* virtual Item::get_time() is gone
* Item_datetime, for a datetime constant
* better default for cast_to_int_type()
* Item_cache objects now *always* have the field_type() set
sql/item_cmpfunc.cc:
* get_year_value, get_time_value are gone. get_datetime_value does it all
* get_value_a_func, get_value_b_func are gone
* can_compare_as_dates() is gone too, TIME_RESULT is used instead
* cmp_type() instead or result_type() when doing a comparison
* compare_datetime and compate_e_datetime in the comparator_matrix, is_nulls_eq is gone
* Item::cmp_result() instead of Item::is_datetime() and Item::result_as_longlong()
sql/item_cmpfunc.h:
greatly simplified Arg_comparator
sql/item_create.cc:
* fix a bug in error messages in CAST
sql/item_func.cc:
Item::cmp_result() instead of Item::is_datetime() and Item::result_as_longlong()
mention all possibitiles in switch over Item_result values, or use default:
sql/item_row.h:
overwrite the default cmp_type() for Item_row,
as no MYSQL_TYPE_xxx value corresponds to ROW_RESULT
sql/item_timefunc.cc:
rewrite make_datetime to support precision argument
SEC_TO_TIME is real function, not integer.
many functions that returned temporal values had duplicate code in val_* methods,
some of them did not have get_date() which resulted in unnecessary date->str->date conversions.
Now they all are derived from Item_temporal_func and *only* provide get_date, not val* methods.
many fixes to set decimals (datetime precision) correctly.
sql/item_timefunc.h:
SEC_TO_TIME is real function, not integer.
many functions that returned temporal values had duplicate code in val_* methods,
some of them did not have get_date() which resulted in unnecessary date->str->date conversions.
Now they all are derived from Item_temporal_func and *only* provide get_date, not val* methods.
many fixes to set decimals (datetime precision) correctly.
sql/log_event.cc:
replication of NOW(6)
sql/log_event.h:
replication of NOW(6)
sql/mysql_priv.h:
Lazy_string class to pass a value (string, number, time) polymorphically down the stack.
make_truncated_value_warning() that uses it.
sql/mysqld.cc:
datetime in Arg_comparator::comparator_matrix
sql/opt_range.cc:
cleanup: don't disable warnings before calling save_in_field_no_warnings()
sql/protocol.cc:
Protocol::store(time) now takes the precision as an argument
sql/protocol.h:
Protocol::store(time) now takes the precision as an argument
sql/rpl_rli.cc:
small cleanup
sql/set_var.cc:
SET TIMESTAMP=double
sql/set_var.h:
@@TIMESTAMP is a double
sql/share/errmsg.txt:
precision and scale are unsigned
sql/slave.cc:
replication of NOW(6)
sql/sp_head.cc:
cleanup
sql/sql_class.cc:
support for NOW(6)
sql/sql_class.h:
support for NOW(6)
sql/sql_insert.cc:
support for NOW(6)
sql/sql_select.cc:
use item->cmp_type().
move a comment where it belongs
sql/sql_show.cc:
new column I_S.COLUMNS.DATETIME_PRECISION
sql/sql_yacc.yy:
TIME(X), DATETIME(X), cast, NOW(X), CURTIME(X), etc
sql/time.cc:
fix date_add_interval() to support MYSQL_TIMESTAMP_TIME argument
storage/myisam/ha_myisam.cc:
TIMESTAMP no longer carries ZEROFIELD flag, still we keep MYI file compatible.
strings/my_vsnprintf.c:
warnings
tests/mysql_client_test.c:
old timestamp(X) does not work anymore
datetime is no longer equal to time
2011-03-01 13:24:36 +01:00
|
|
|
if (ltime_utc >= thd->query_start())
|
2008-05-09 09:43:02 +02:00
|
|
|
return;
|
|
|
|
|
Bug#35981: ALTER EVENT causes the server to change the PRESERVE option.
If [NOT] PRESERVE was not given, parser always defaulted to NOT
PRESERVE, making it impossible for the "not given = no change"
rule to work in ALTER EVENT. Leaving out the PRESERVE-clause
defaults to NOT PRESERVE on CREATE now, and to "no change" in
ALTER.
mysql-test/r/events_2.result:
show that giving no PRESERVE-clause to ALTER EVENT
results in no change. show that giving no PRESERVE-clause
to CREATE EVENT defaults to NOT PRESERVE as per the docs.
Show specifically that this is also handled correctly when
trying to ALTER EVENTs into the past.
mysql-test/t/events_2.test:
show that giving no PRESERVE-clause to ALTER EVENT
results in no change. show that giving no PRESERVE-clause
to CREATE EVENT defaults to NOT PRESERVE as per the docs.
Show specifically that this is also handled correctly when
trying to ALTER EVENTs into the past.
sql/event_db_repository.cc:
If ALTER EVENT was given no PRESERVE-clause (meaning "no change"),
we don't know the previous PRESERVE-setting by the time we check
the parse-data. If ALTER EVENT was given dates that are in the past,
we don't know how to react, lacking the PRESERVE-setting. Heal this
by running the check later when we have actually read the previous
EVENT-data.
sql/event_parse_data.cc:
Change default for ON COMPLETION to indicate, "not specified."
Also defer throwing errors when ALTER EVENT is given dates in
the past but not PRESERVE-clause until we know the previous
PRESERVE-value.
sql/event_parse_data.h:
Add third state for ON COMPLETION [NOT] PRESERVE (preserve,
don't, not specified).
Make check_dates() public so we can defer this check until
deeper in the callstack where we have all the required data.
sql/sql_yacc.yy:
If CREATE EVENT is not given ON COMPLETION [NOT] PRESERVE,
we default to NOT, as per the docs.
2008-08-18 13:05:51 +02:00
|
|
|
/*
|
|
|
|
We'll come back later when we have the real on_completion value
|
|
|
|
*/
|
|
|
|
if (on_completion == Event_parse_data::ON_COMPLETION_DEFAULT)
|
|
|
|
return;
|
|
|
|
|
2008-05-09 09:43:02 +02:00
|
|
|
if (on_completion == Event_parse_data::ON_COMPLETION_DROP)
|
|
|
|
{
|
|
|
|
switch (thd->lex->sql_command) {
|
|
|
|
case SQLCOM_CREATE_EVENT:
|
2013-06-15 17:32:08 +02:00
|
|
|
push_warning(thd, Sql_condition::WARN_LEVEL_NOTE,
|
2008-05-09 09:43:02 +02:00
|
|
|
ER_EVENT_CANNOT_CREATE_IN_THE_PAST,
|
2015-07-06 19:24:14 +02:00
|
|
|
ER_THD(thd, ER_EVENT_CANNOT_CREATE_IN_THE_PAST));
|
2008-05-09 09:43:02 +02:00
|
|
|
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;
|
2011-06-09 19:03:17 +02:00
|
|
|
status_changed= true;
|
2013-06-15 17:32:08 +02:00
|
|
|
push_warning(thd, Sql_condition::WARN_LEVEL_NOTE,
|
2008-05-09 09:43:02 +02:00
|
|
|
ER_EVENT_EXEC_TIME_IN_THE_PAST,
|
2015-07-06 19:24:14 +02:00
|
|
|
ER_THD(thd, ER_EVENT_EXEC_TIME_IN_THE_PAST));
|
2008-05-09 09:43:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Bug#35981: ALTER EVENT causes the server to change the PRESERVE option.
If [NOT] PRESERVE was not given, parser always defaulted to NOT
PRESERVE, making it impossible for the "not given = no change"
rule to work in ALTER EVENT. Leaving out the PRESERVE-clause
defaults to NOT PRESERVE on CREATE now, and to "no change" in
ALTER.
mysql-test/r/events_2.result:
show that giving no PRESERVE-clause to ALTER EVENT
results in no change. show that giving no PRESERVE-clause
to CREATE EVENT defaults to NOT PRESERVE as per the docs.
Show specifically that this is also handled correctly when
trying to ALTER EVENTs into the past.
mysql-test/t/events_2.test:
show that giving no PRESERVE-clause to ALTER EVENT
results in no change. show that giving no PRESERVE-clause
to CREATE EVENT defaults to NOT PRESERVE as per the docs.
Show specifically that this is also handled correctly when
trying to ALTER EVENTs into the past.
sql/event_db_repository.cc:
If ALTER EVENT was given no PRESERVE-clause (meaning "no change"),
we don't know the previous PRESERVE-setting by the time we check
the parse-data. If ALTER EVENT was given dates that are in the past,
we don't know how to react, lacking the PRESERVE-setting. Heal this
by running the check later when we have actually read the previous
EVENT-data.
sql/event_parse_data.cc:
Change default for ON COMPLETION to indicate, "not specified."
Also defer throwing errors when ALTER EVENT is given dates in
the past but not PRESERVE-clause until we know the previous
PRESERVE-value.
sql/event_parse_data.h:
Add third state for ON COMPLETION [NOT] PRESERVE (preserve,
don't, not specified).
Make check_dates() public so we can defer this check until
deeper in the callstack where we have all the required data.
sql/sql_yacc.yy:
If CREATE EVENT is not given ON COMPLETION [NOT] PRESERVE,
we default to NOT, as per the docs.
2008-08-18 13:05:51 +02:00
|
|
|
/*
|
|
|
|
Check time/dates in ALTER EVENT
|
|
|
|
|
|
|
|
We check whether ALTER EVENT was given dates that are in the past.
|
|
|
|
However to know how to react, we need the ON COMPLETION type. Hence,
|
|
|
|
the check is deferred until we have the previous ON COMPLETION type
|
|
|
|
from the event-db to fall back on if nothing was specified in the
|
|
|
|
ALTER EVENT-statement.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
Event_parse_data::check_dates()
|
|
|
|
thd Thread
|
|
|
|
on_completion ON COMPLETION value currently in event-db.
|
|
|
|
Will be overridden by value in ALTER EVENT if given.
|
|
|
|
|
|
|
|
RETURN VALUE
|
|
|
|
TRUE an error occurred, do not ALTER
|
|
|
|
FALSE OK
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool
|
|
|
|
Event_parse_data::check_dates(THD *thd, int previous_on_completion)
|
|
|
|
{
|
|
|
|
if (on_completion == Event_parse_data::ON_COMPLETION_DEFAULT)
|
|
|
|
{
|
|
|
|
on_completion= previous_on_completion;
|
|
|
|
if (!ends_null)
|
|
|
|
check_if_in_the_past(thd, ends);
|
|
|
|
if (!execute_at_null)
|
|
|
|
check_if_in_the_past(thd, execute_at);
|
|
|
|
}
|
|
|
|
return do_not_create;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-05-09 09:43:02 +02:00
|
|
|
/*
|
|
|
|
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)
|
|
|
|
{
|
2011-05-19 19:16:17 +02:00
|
|
|
uint not_used;
|
2008-05-09 09:43:02 +02:00
|
|
|
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);
|
|
|
|
|
2011-05-19 19:16:17 +02:00
|
|
|
if (item_execute_at->get_date(<ime, TIME_NO_ZERO_DATE))
|
2008-05-09 09:43:02 +02:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2011-10-19 21:45:18 +02:00
|
|
|
if (get_interval_value(item_expression, interval, &interval_tmp))
|
2008-05-09 09:43:02 +02:00
|
|
|
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)
|
|
|
|
{
|
2011-05-19 19:16:17 +02:00
|
|
|
uint not_used;
|
2008-05-09 09:43:02 +02:00
|
|
|
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;
|
|
|
|
|
2011-05-19 19:16:17 +02:00
|
|
|
if (item_starts->get_date(<ime, TIME_NO_ZERO_DATE))
|
2008-05-09 09:43:02 +02:00
|
|
|
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)
|
|
|
|
{
|
2011-05-19 19:16:17 +02:00
|
|
|
uint not_used;
|
2008-05-09 09:43:02 +02:00
|
|
|
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"));
|
2011-05-19 19:16:17 +02:00
|
|
|
if (item_ends->get_date(<ime, TIME_NO_ZERO_DATE))
|
2008-05-09 09:43:02 +02:00
|
|
|
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");
|
2017-09-19 19:45:17 +02:00
|
|
|
DBUG_PRINT("info", ("execute_at: %p expr=%p starts=%p ends=%p",
|
|
|
|
item_execute_at, item_expression,
|
|
|
|
item_starts, item_ends));
|
2008-05-09 09:43:02 +02:00
|
|
|
|
|
|
|
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;
|
2009-02-13 17:41:47 +01:00
|
|
|
size_t definer_user_len= thd->lex->definer->user.length;
|
|
|
|
size_t definer_host_len= thd->lex->definer->host.length;
|
2017-04-23 18:39:57 +02:00
|
|
|
char *tmp;
|
2017-09-19 19:45:17 +02:00
|
|
|
DBUG_PRINT("info",("init definer_user thd->mem_root: %p "
|
|
|
|
"definer_user: %p", thd->mem_root,
|
|
|
|
definer_user));
|
2008-05-09 09:43:02 +02:00
|
|
|
|
|
|
|
/* + 1 for @ */
|
|
|
|
DBUG_PRINT("info",("init definer as whole"));
|
|
|
|
definer.length= definer_user_len + definer_host_len + 1;
|
2017-04-23 18:39:57 +02:00
|
|
|
definer.str= tmp= (char*) thd->alloc(definer.length + 1);
|
2008-05-09 09:43:02 +02:00
|
|
|
|
|
|
|
DBUG_PRINT("info",("copy the user"));
|
2017-04-23 18:39:57 +02:00
|
|
|
strmake(tmp, definer_user, definer_user_len);
|
|
|
|
tmp[definer_user_len]= '@';
|
2008-05-09 09:43:02 +02:00
|
|
|
|
|
|
|
DBUG_PRINT("info",("copy the host"));
|
2017-04-23 18:39:57 +02:00
|
|
|
strmake(tmp + definer_user_len + 1, definer_host, definer_host_len);
|
2008-05-09 09:43:02 +02:00
|
|
|
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. */
|
2014-10-15 12:59:13 +02:00
|
|
|
if ((WSREP(thd) && IF_WSREP(thd->wsrep_applier, 0)) ||
|
2014-10-08 18:47:16 +02:00
|
|
|
(thd->system_thread == SYSTEM_THREAD_SLAVE_SQL) ||
|
2008-05-09 09:43:02 +02:00
|
|
|
(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))
|
2011-06-09 19:03:17 +02:00
|
|
|
{
|
|
|
|
status= Event_parse_data::SLAVESIDE_DISABLED;
|
|
|
|
status_changed= true;
|
|
|
|
}
|
2012-10-23 12:46:29 +02:00
|
|
|
originator = thd->variables.server_id;
|
2008-05-09 09:43:02 +02:00
|
|
|
}
|
|
|
|
else
|
2012-10-23 12:46:29 +02:00
|
|
|
originator = global_system_variables.server_id;
|
2008-05-09 09:43:02 +02:00
|
|
|
}
|