mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +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
|
очень_очень_очень_очень_очень_очень_очень_очень_длинная_строка_66
|
||||||
on schedule every 2 year do select 1;
|
on schedule every 2 year do select 1;
|
||||||
ERROR 42000: Identifier name 'очень_очень_очень_очень_очень_очень_очень_очень_длинна' is too long
|
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;
|
drop database events_test;
|
||||||
|
@ -411,6 +411,108 @@ create event
|
|||||||
очень_очень_очень_очень_очень_очень_очень_очень_длинная_строка_66
|
очень_очень_очень_очень_очень_очень_очень_очень_длинная_строка_66
|
||||||
on schedule every 2 year do select 1;
|
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
|
# End of tests
|
||||||
#
|
#
|
||||||
|
@ -185,6 +185,8 @@ mysql_event_fill_row(THD *thd,
|
|||||||
DBUG_PRINT("info", ("dbname=[%s]", et->dbname.str));
|
DBUG_PRINT("info", ("dbname=[%s]", et->dbname.str));
|
||||||
DBUG_PRINT("info", ("name =[%s]", et->name.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)
|
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]);
|
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. */
|
/* Don't update create on row update. */
|
||||||
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
|
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()
|
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),
|
status(Event_parse_data::ENABLED),
|
||||||
do_not_create(FALSE),
|
do_not_create(FALSE),
|
||||||
body_changed(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())
|
if (ltime_utc >= (my_time_t) thd->query_start())
|
||||||
return;
|
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)
|
if (on_completion == Event_parse_data::ON_COMPLETION_DROP)
|
||||||
{
|
{
|
||||||
switch (thd->lex->sql_command) {
|
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.
|
Sets time for execution for one-time event.
|
||||||
|
|
||||||
|
@ -38,7 +38,12 @@ public:
|
|||||||
|
|
||||||
enum enum_on_completion
|
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
|
ON_COMPLETION_PRESERVE
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -80,6 +85,9 @@ public:
|
|||||||
bool
|
bool
|
||||||
check_parse_data(THD *thd);
|
check_parse_data(THD *thd);
|
||||||
|
|
||||||
|
bool
|
||||||
|
check_dates(THD *thd, int previous_on_completion);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1786,6 +1786,8 @@ event_tail:
|
|||||||
if (!(lex->event_parse_data= Event_parse_data::new_instance(thd)))
|
if (!(lex->event_parse_data= Event_parse_data::new_instance(thd)))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
lex->event_parse_data->identifier= $3;
|
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
|
We have to turn of CLIENT_MULTI_QUERIES while parsing a
|
||||||
|
Reference in New Issue
Block a user