#At file:///misc/mysql/forest/35981_/51-35981/
2654 Tatiana A. Nurnberg 2008-08-18
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.
modified:
mysql-test/r/events_2.result
mysql-test/t/events_2.test
sql/event_db_repository.cc
sql/event_parse_data.cc
sql/event_parse_data.h
sql/sql_yacc.yy
per-file messages:
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.
=== modified file 'mysql-test/r/events_2.result'
--- a/mysql-test/r/events_2.result 2008-05-13 12:06:32 +0000
+++ b/mysql-test/r/events_2.result 2008-08-18 11:05:51 +0000
@@ -328,4 +328,81 @@ create event
оÑенаÑ_ÑÑÑока_66
on schedule every 2 year do select 1;
ERROR 42000: Identifier name 'о_оÑенÑ_оÑенÑ_оÑенÑ_оÑенÑ_оÑенÑ_длинна' is too long
+create event event_35981 on schedule every 6 month on completion preserve
+disable
+do
+select 1;
+The following SELECTs should all give 1
+select count(*) from information_schema.events
+where event_schema = database() and event_name = 'event_35981' and
+on_completion = 'PRESERVE';
+count(*)
+1
+alter event event_35981 enable;
+select count(*) from information_schema.events
+where event_schema = database() and event_name = 'event_35981' and
+on_completion = 'PRESERVE';
+count(*)
+1
+alter event event_35981 on completion not preserve;
+select count(*) from information_schema.events
+where event_schema = database() and event_name = 'event_35981' and
+on_completion = 'NOT PRESERVE';
+count(*)
+1
+alter event event_35981 disable;
+select count(*) from information_schema.events
+where event_schema = database() and event_name = 'event_35981' and
+on_completion = 'NOT PRESERVE';
+count(*)
+1
+alter event event_35981 on completion preserve;
+select count(*) from information_schema.events
+where event_schema = database() and event_name = 'event_35981' and
+on_completion = 'PRESERVE';
+count(*)
+1
+drop event event_35981;
+create event event_35981 on schedule every 6 month disable
+do
+select 1;
+select count(*) from information_schema.events
+where event_schema = database() and event_name = 'event_35981' and
+on_completion = 'NOT PRESERVE';
+count(*)
+1
+drop event event_35981;
+create event event_35981 on schedule every 1 hour starts current_timestamp
+on completion not preserve
+do
+select 1;
+alter event event_35981 on schedule every 1 hour starts '1999-01-01 00:00:00'
+ ends '1999-01-02 00:00:00';
+ERROR HY000: Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation.
+drop event event_35981;
+create event event_35981 on schedule every 1 hour starts current_timestamp
+on completion not preserve
+do
+select 1;
+alter event event_35981 on schedule every 1 hour starts '1999-01-01 00:00:00'
+ ends '1999-01-02 00:00:00' on completion preserve;
+Warnings:
+Note 1544 Event execution time is in the past. Event has been disabled
+drop event event_35981;
+create event event_35981 on schedule every 1 hour starts current_timestamp
+on completion preserve
+do
+select 1;
+alter event event_35981 on schedule every 1 hour starts '1999-01-01 00:00:00'
+ ends '1999-01-02 00:00:00';
+Warnings:
+Note 1544 Event execution time is in the past. Event has been disabled
+alter event event_35981 on schedule every 1 hour starts '1999-01-01 00:00:00'
+ ends '1999-01-02 00:00:00' on completion not preserve;
+ERROR HY000: Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation.
+alter event event_35981 on schedule every 1 hour starts '1999-01-01 00:00:00'
+ ends '1999-01-02 00:00:00' on completion preserve;
+Warnings:
+Note 1544 Event execution time is in the past. Event has been disabled
+drop event event_35981;
drop database events_test;
=== modified file 'mysql-test/t/events_2.test'
--- a/mysql-test/t/events_2.test 2008-05-13 12:06:32 +0000
+++ b/mysql-test/t/events_2.test 2008-08-18 11:05:51 +0000
@@ -411,6 +411,108 @@ create event
оÑенÑ_оÑенÑ_оÑенÑ_оÑенÑ_оÑенÑ_оÑенÑ_оÑенÑ_оÑеа_66
on schedule every 2 year do select 1;
+#
+# Bug#35981: ALTER EVENT causes the server to change the PRESERVE option.
+#
+
+create event event_35981 on schedule every 6 month on completion preserve
+disable
+do
+ select 1;
+
+echo The following SELECTs should all give 1;
+
+# show current ON_COMPLETION
+select count(*) from information_schema.events
+where event_schema = database() and event_name = 'event_35981' and
+ on_completion = 'PRESERVE';
+
+# show ON_COMPLETION remains "PRESERVE" when not given in ALTER EVENT
+alter event event_35981 enable;
+select count(*) from information_schema.events
+where event_schema = database() and event_name = 'event_35981' and
+ on_completion = 'PRESERVE';
+
+# show we can change ON_COMPLETION
+alter event event_35981 on completion not preserve;
+select count(*) from information_schema.events
+where event_schema = database() and event_name = 'event_35981' and
+ on_completion = 'NOT PRESERVE';
+
+# show ON_COMPLETION remains "NOT PRESERVE" when not given in ALTER EVENT
+alter event event_35981 disable;
+select count(*) from information_schema.events
+where event_schema = database() and event_name = 'event_35981' and
+ on_completion = 'NOT PRESERVE';
+
+# show we can change ON_COMPLETION
+alter event event_35981 on completion preserve;
+select count(*) from information_schema.events
+where event_schema = database() and event_name = 'event_35981' and
+ on_completion = 'PRESERVE';
+
+
+drop event event_35981;
+
+create event event_35981 on schedule every 6 month disable
+do
+ select 1;
+
+# show that the defaults for CREATE EVENT are still correct (NOT PRESERVE)
+select count(*) from information_schema.events
+where event_schema = database() and event_name = 'event_35981' and
+ on_completion = 'NOT PRESERVE';
+
+drop event event_35981;
+
+
+# show that backdating doesn't break
+
+create event event_35981 on schedule every 1 hour starts current_timestamp
+ on completion not preserve
+do
+ select 1;
+
+# should fail thanks to above's NOT PRESERVE
+--error ER_EVENT_CANNOT_ALTER_IN_THE_PAST
+alter event event_35981 on schedule every 1 hour starts '1999-01-01 00:00:00'
+ ends '1999-01-02 00:00:00';
+
+drop event event_35981;
+
+create event event_35981 on schedule every 1 hour starts current_timestamp
+ on completion not preserve
+do
+ select 1;
+
+# succeed with warning
+alter event event_35981 on schedule every 1 hour starts '1999-01-01 00:00:00'
+ ends '1999-01-02 00:00:00' on completion preserve;
+
+drop event event_35981;
+
+
+
+create event event_35981 on schedule every 1 hour starts current_timestamp
+ on completion preserve
+do
+ select 1;
+
+# this should succeed thanks to above PRESERVE! give a warning though.
+alter event event_35981 on schedule every 1 hour starts '1999-01-01 00:00:00'
+ ends '1999-01-02 00:00:00';
+
+# this should fail, as the event would have passed already
+--error ER_EVENT_CANNOT_ALTER_IN_THE_PAST
+alter event event_35981 on schedule every 1 hour starts '1999-01-01 00:00:00'
+ ends '1999-01-02 00:00:00' on completion not preserve;
+
+# should succeed giving a warning
+alter event event_35981 on schedule every 1 hour starts '1999-01-01 00:00:00'
+ ends '1999-01-02 00:00:00' on completion preserve;
+
+drop event event_35981;
+
#
# End of tests
#
=== modified file 'sql/event_db_repository.cc'
--- a/sql/event_db_repository.cc 2008-02-07 10:47:39 +0000
+++ b/sql/event_db_repository.cc 2008-08-18 11:05:51 +0000
@@ -185,6 +185,8 @@ mysql_event_fill_row(THD *thd,
DBUG_PRINT("info", ("dbname=[%s]", et->dbname.str));
DBUG_PRINT("info", ("name =[%s]", et->name.str));
+ DBUG_ASSERT(et->on_completion != Event_parse_data::ON_COMPLETION_DEFAULT);
+
if (table->s->fields < ET_FIELD_COUNT)
{
/*
@@ -745,6 +747,18 @@ Event_db_repository::update_event(THD *t
store_record(table,record[1]);
+ /*
+ 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. The
+ check is deferred to this point because by now we have the previous
+ setting (from the event-table) to fall back on if nothing was specified
+ in the ALTER EVENT-statement.
+ */
+
+ if (parse_data->check_dates(thd,
+ table->field[ET_FIELD_ON_COMPLETION]->val_int()))
+ goto end;
+
/* Don't update create on row update. */
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
=== modified file 'sql/event_parse_data.cc'
--- a/sql/event_parse_data.cc 2008-05-09 07:43:02 +0000
+++ b/sql/event_parse_data.cc 2008-08-18 11:05:51 +0000
@@ -45,7 +45,7 @@ Event_parse_data::new_instance(THD *thd)
*/
Event_parse_data::Event_parse_data()
- :on_completion(Event_parse_data::ON_COMPLETION_DROP),
+ :on_completion(Event_parse_data::ON_COMPLETION_DEFAULT),
status(Event_parse_data::ENABLED),
do_not_create(FALSE),
body_changed(FALSE),
@@ -114,6 +114,12 @@ Event_parse_data::check_if_in_the_past(T
if (ltime_utc >= (my_time_t) thd->query_start())
return;
+ /*
+ We'll come back later when we have the real on_completion value
+ */
+ if (on_completion == Event_parse_data::ON_COMPLETION_DEFAULT)
+ return;
+
if (on_completion == Event_parse_data::ON_COMPLETION_DROP)
{
switch (thd->lex->sql_command) {
@@ -142,6 +148,42 @@ Event_parse_data::check_if_in_the_past(T
/*
+ 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;
+}
+
+
+
+/*
Sets time for execution for one-time event.
SYNOPSIS
=== modified file 'sql/event_parse_data.h'
--- a/sql/event_parse_data.h 2008-05-09 07:43:02 +0000
+++ b/sql/event_parse_data.h 2008-08-18 11:05:51 +0000
@@ -38,7 +38,12 @@ public:
enum enum_on_completion
{
- ON_COMPLETION_DROP = 1,
+ /*
+ On CREATE EVENT, DROP is the DEFAULT as per the docs.
+ On ALTER EVENT, "no change" is the DEFAULT.
+ */
+ ON_COMPLETION_DEFAULT = 0,
+ ON_COMPLETION_DROP,
ON_COMPLETION_PRESERVE
};
@@ -80,6 +85,9 @@ public:
bool
check_parse_data(THD *thd);
+ bool
+ check_dates(THD *thd, int previous_on_completion);
+
private:
void
=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy 2008-05-20 07:38:17 +0000
+++ b/sql/sql_yacc.yy 2008-08-18 11:05:51 +0000
@@ -1786,6 +1786,8 @@ event_tail:
if (!(lex->event_parse_data= Event_parse_data::new_instance(thd)))
MYSQL_YYABORT;
lex->event_parse_data->identifier= $3;
+ lex->event_parse_data->on_completion=
+ Event_parse_data::ON_COMPLETION_DROP;
/*
We have to turn of CLIENT_MULTI_QUERIES while parsing a
| Thread |
|---|
| • bzr commit into mysql-5.1 branch (azundris:2654) Bug#35981 | Tatiana A. Nurnberg | 18 Aug |