mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03: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.
This commit is contained in:
@ -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;
|
||||
|
@ -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
|
||||
#
|
||||
|
@ -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 *thd, Event_parse_data *parse_data,
|
||||
|
||||
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;
|
||||
|
||||
|
@ -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(THD *thd, my_time_t ltime_utc)
|
||||
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) {
|
||||
@ -141,6 +147,42 @@ Event_parse_data::check_if_in_the_past(THD *thd, my_time_t ltime_utc)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
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.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user