Commit 8fe55c09 authored by andrey@lmy004's avatar andrey@lmy004

manual merge

parents 91d09f46 483a6d06
...@@ -37,6 +37,54 @@ alter event event3 rename to event2; ...@@ -37,6 +37,54 @@ alter event event3 rename to event2;
drop event event2; drop event event2;
create event event2 on schedule every 2 second starts now() ends date_add(now(), interval 5 hour) comment "some" DO begin end; create event event2 on schedule every 2 second starts now() ends date_add(now(), interval 5 hour) comment "some" DO begin end;
drop event event2; drop event event2;
CREATE EVENT event_starts_test ON SCHEDULE EVERY 10 SECOND COMMENT "" DO SELECT 1;
SHOW EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
events_test event_starts_test root@localhost RECURRING NULL 10 INTERVAL_SECOND # # ENABLED
SELECT starts IS NULL, ends IS NULL, comment FROM mysql.event WHERE db='events_test' AND name='event_starts_test';
starts IS NULL ends IS NULL comment
0 1
ALTER EVENT event_starts_test ON SCHEDULE AT '2020-02-02 20:00:02';
SHOW EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
events_test event_starts_test root@localhost ONE TIME 2020-02-02 17:00:02 NULL NULL # # ENABLED
SELECT starts IS NULL, ends IS NULL, comment FROM mysql.event WHERE db='events_test' AND name='event_starts_test';
starts IS NULL ends IS NULL comment
1 1
ALTER EVENT event_starts_test COMMENT "non-empty comment";
SHOW EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
events_test event_starts_test root@localhost ONE TIME 2020-02-02 17:00:02 NULL NULL # # ENABLED
SELECT starts IS NULL, ends IS NULL, comment FROM mysql.event WHERE db='events_test' AND name='event_starts_test';
starts IS NULL ends IS NULL comment
1 1 non-empty comment
ALTER EVENT event_starts_test COMMENT "";
SHOW EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
events_test event_starts_test root@localhost ONE TIME 2020-02-02 17:00:02 NULL NULL # # ENABLED
SELECT starts IS NULL, ends IS NULL, comment FROM mysql.event WHERE db='events_test' AND name='event_starts_test';
starts IS NULL ends IS NULL comment
1 1
DROP EVENT event_starts_test;
CREATE EVENT event_starts_test ON SCHEDULE EVERY 20 SECOND STARTS '2020-02-02 20:00:02' ENDS '2022-02-02 20:00:02' DO SELECT 2;
SHOW EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
events_test event_starts_test root@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
SELECT starts IS NULL, ends IS NULL, comment FROM mysql.event WHERE db='events_test' AND name='event_starts_test';
starts IS NULL ends IS NULL comment
0 0
ALTER EVENT event_starts_test COMMENT "non-empty comment";
SHOW EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
events_test event_starts_test root@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
SELECT starts IS NULL, ends IS NULL, comment FROM mysql.event WHERE db='events_test' AND name='event_starts_test';
starts IS NULL ends IS NULL comment
0 0 non-empty comment
ALTER EVENT event_starts_test COMMENT "";
SHOW EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
events_test event_starts_test root@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
DROP EVENT event_starts_test;
create event e_43 on schedule every 1 second do set @a = 5; create event e_43 on schedule every 1 second do set @a = 5;
set global event_scheduler = 1; set global event_scheduler = 1;
alter event e_43 do alter event e_43 do set @a = 4; alter event e_43 do alter event e_43 do set @a = 4;
......
...@@ -48,6 +48,38 @@ drop event event2; ...@@ -48,6 +48,38 @@ drop event event2;
create event event2 on schedule every 2 second starts now() ends date_add(now(), interval 5 hour) comment "some" DO begin end; create event event2 on schedule every 2 second starts now() ends date_add(now(), interval 5 hour) comment "some" DO begin end;
drop event event2; drop event event2;
# BUG #16537 (Events: mysql.event.starts is null)
CREATE EVENT event_starts_test ON SCHEDULE EVERY 10 SECOND COMMENT "" DO SELECT 1;
--replace_column 8 # 9 #
SHOW EVENTS;
SELECT starts IS NULL, ends IS NULL, comment FROM mysql.event WHERE db='events_test' AND name='event_starts_test';
ALTER EVENT event_starts_test ON SCHEDULE AT '2020-02-02 20:00:02';
--replace_column 8 # 9 #
SHOW EVENTS;
SELECT starts IS NULL, ends IS NULL, comment FROM mysql.event WHERE db='events_test' AND name='event_starts_test';
ALTER EVENT event_starts_test COMMENT "non-empty comment";
--replace_column 8 # 9 #
SHOW EVENTS;
SELECT starts IS NULL, ends IS NULL, comment FROM mysql.event WHERE db='events_test' AND name='event_starts_test';
ALTER EVENT event_starts_test COMMENT "";
--replace_column 8 # 9 #
SHOW EVENTS;
SELECT starts IS NULL, ends IS NULL, comment FROM mysql.event WHERE db='events_test' AND name='event_starts_test';
DROP EVENT event_starts_test;
CREATE EVENT event_starts_test ON SCHEDULE EVERY 20 SECOND STARTS '2020-02-02 20:00:02' ENDS '2022-02-02 20:00:02' DO SELECT 2;
--replace_column 8 # 9 #
SHOW EVENTS;
SELECT starts IS NULL, ends IS NULL, comment FROM mysql.event WHERE db='events_test' AND name='event_starts_test';
ALTER EVENT event_starts_test COMMENT "non-empty comment";
--replace_column 8 # 9 #
SHOW EVENTS;
SELECT starts IS NULL, ends IS NULL, comment FROM mysql.event WHERE db='events_test' AND name='event_starts_test';
ALTER EVENT event_starts_test COMMENT "";
--replace_column 8 # 9 #
SHOW EVENTS;
DROP EVENT event_starts_test;
#
#
create event e_43 on schedule every 1 second do set @a = 5; create event e_43 on schedule every 1 second do set @a = 5;
set global event_scheduler = 1; set global event_scheduler = 1;
--sleep 2 --sleep 2
......
...@@ -637,20 +637,6 @@ evex_fill_row(THD *thd, TABLE *table, event_timed *et, my_bool is_update) ...@@ -637,20 +637,6 @@ evex_fill_row(THD *thd, TABLE *table, event_timed *et, my_bool is_update)
goto trunc_err; goto trunc_err;
} }
if (et->starts.year)
{
table->field[EVEX_FIELD_STARTS]->set_notnull();// set NULL flag to OFF
table->field[EVEX_FIELD_STARTS]->
store_time(&et->starts, MYSQL_TIMESTAMP_DATETIME);
}
if (et->ends.year)
{
table->field[EVEX_FIELD_ENDS]->set_notnull();
table->field[EVEX_FIELD_ENDS]->
store_time(&et->ends, MYSQL_TIMESTAMP_DATETIME);
}
if (et->expression) if (et->expression)
{ {
table->field[EVEX_FIELD_INTERVAL_EXPR]->set_notnull(); table->field[EVEX_FIELD_INTERVAL_EXPR]->set_notnull();
...@@ -664,18 +650,31 @@ evex_fill_row(THD *thd, TABLE *table, event_timed *et, my_bool is_update) ...@@ -664,18 +650,31 @@ evex_fill_row(THD *thd, TABLE *table, event_timed *et, my_bool is_update)
table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->store((longlong)et->interval+1); table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->store((longlong)et->interval+1);
table->field[EVEX_FIELD_EXECUTE_AT]->set_null(); table->field[EVEX_FIELD_EXECUTE_AT]->set_null();
if (!et->starts_null)
{
table->field[EVEX_FIELD_STARTS]->set_notnull();// set NULL flag to OFF
table->field[EVEX_FIELD_STARTS]->
store_time(&et->starts, MYSQL_TIMESTAMP_DATETIME);
}
if (!et->ends_null)
{
table->field[EVEX_FIELD_ENDS]->set_notnull();
table->field[EVEX_FIELD_ENDS]->
store_time(&et->ends, MYSQL_TIMESTAMP_DATETIME);
}
} }
else if (et->execute_at.year) else if (et->execute_at.year)
{ {
// fix_fields already called in init_execute_at
table->field[EVEX_FIELD_INTERVAL_EXPR]->set_null(); table->field[EVEX_FIELD_INTERVAL_EXPR]->set_null();
table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->set_null(); table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->set_null();
table->field[EVEX_FIELD_STARTS]->set_null();
table->field[EVEX_FIELD_ENDS]->set_null();
table->field[EVEX_FIELD_EXECUTE_AT]->set_notnull(); table->field[EVEX_FIELD_EXECUTE_AT]->set_notnull();
table->field[EVEX_FIELD_EXECUTE_AT]->store_time(&et->execute_at, table->field[EVEX_FIELD_EXECUTE_AT]->store_time(&et->execute_at,
MYSQL_TIMESTAMP_DATETIME); MYSQL_TIMESTAMP_DATETIME);
table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->set_null();
} }
else else
{ {
...@@ -686,14 +685,17 @@ evex_fill_row(THD *thd, TABLE *table, event_timed *et, my_bool is_update) ...@@ -686,14 +685,17 @@ evex_fill_row(THD *thd, TABLE *table, event_timed *et, my_bool is_update)
((Field_timestamp *)table->field[EVEX_FIELD_MODIFIED])->set_time(); ((Field_timestamp *)table->field[EVEX_FIELD_MODIFIED])->set_time();
if (et->comment.length) if (et->comment.str)
if (table->field[field_num= EVEX_FIELD_COMMENT]-> {
store(et->comment.str, et->comment.length, system_charset_info)) if (table->field[field_num= EVEX_FIELD_COMMENT]->store(et->comment.str,
et->comment.length,
system_charset_info))
goto trunc_err; goto trunc_err;
}
DBUG_RETURN(0); DBUG_RETURN(0);
trunc_err: trunc_err:
my_error(ER_EVENT_DATA_TOO_LONG, MYF(0)); my_error(ER_EVENT_DATA_TOO_LONG, MYF(0), table->field[field_num]->field_name);
DBUG_RETURN(EVEX_GENERAL_ERROR); DBUG_RETURN(EVEX_GENERAL_ERROR);
} }
...@@ -806,14 +808,16 @@ db_create_event(THD *thd, event_timed *et, my_bool create_if_not, ...@@ -806,14 +808,16 @@ db_create_event(THD *thd, event_timed *et, my_bool create_if_not,
my_error(ER_EVENT_STORE_FAILED, MYF(0), et->name.str, ret); my_error(ER_EVENT_STORE_FAILED, MYF(0), et->name.str, ret);
goto err; goto err;
} }
#ifdef USE_THIS_CODE_AS_TEMPLATE_WHEN_EVENT_REPLICATION_IS_AGREED
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open())
{ {
thd->clear_error(); thd->clear_error();
/* Such a statement can always go directly to binlog, no trans cache */ // Such a statement can always go directly to binlog, no trans cache
thd->binlog_query(THD::MYSQL_QUERY_TYPE, thd->binlog_query(THD::MYSQL_QUERY_TYPE,
thd->query, thd->query_length, FALSE, FALSE); thd->query, thd->query_length, FALSE, FALSE);
} }
#endif
*rows_affected= 1; *rows_affected= 1;
ok: ok:
......
...@@ -103,6 +103,9 @@ public: ...@@ -103,6 +103,9 @@ public:
TIME starts; TIME starts;
TIME ends; TIME ends;
TIME execute_at; TIME execute_at;
my_bool starts_null;
my_bool ends_null;
my_bool execute_at_null;
longlong expression; longlong expression;
interval_type interval; interval_type interval;
......
...@@ -523,8 +523,7 @@ restart_ticking: ...@@ -523,8 +523,7 @@ restart_ticking:
et= evex_queue_first_element(&EVEX_EQ_NAME, event_timed*); et= evex_queue_first_element(&EVEX_EQ_NAME, event_timed*);
DBUG_PRINT("evex main thread",("got event from the queue")); DBUG_PRINT("evex main thread",("got event from the queue"));
if (et->execute_at.year > 1969 && if (!et->execute_at_null && my_time_compare(&time_now,&et->execute_at) == -1)
my_time_compare(&time_now, &et->execute_at) == -1)
{ {
DBUG_PRINT("evex main thread",("still not the time for execution")); DBUG_PRINT("evex main thread",("still not the time for execution"));
VOID(pthread_mutex_unlock(&LOCK_event_arrays)); VOID(pthread_mutex_unlock(&LOCK_event_arrays));
...@@ -571,8 +570,11 @@ restart_ticking: ...@@ -571,8 +570,11 @@ restart_ticking:
#else #else
event_executor_worker((void *) et); event_executor_worker((void *) et);
#endif #endif
if ((et->execute_at.year && !et->expression) || /*
TIME_to_ulonglong_datetime(&et->execute_at) == 0) 1. For one-time event : year is > 0 and expression is 0
2. For recurring, expression is != -=> check execute_at_null in this case
*/
if ((et->execute_at.year && !et->expression) || et->execute_at_null)
et->flags |= EVENT_EXEC_NO_MORE; et->flags |= EVENT_EXEC_NO_MORE;
if ((et->flags & EVENT_EXEC_NO_MORE) || et->status == MYSQL_EVENT_DISABLED) if ((et->flags & EVENT_EXEC_NO_MORE) || et->status == MYSQL_EVENT_DISABLED)
......
...@@ -41,6 +41,7 @@ event_timed::init() ...@@ -41,6 +41,7 @@ event_timed::init()
set_zero_time(&ends, MYSQL_TIMESTAMP_DATETIME); set_zero_time(&ends, MYSQL_TIMESTAMP_DATETIME);
set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME); set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
set_zero_time(&last_executed, MYSQL_TIMESTAMP_DATETIME); set_zero_time(&last_executed, MYSQL_TIMESTAMP_DATETIME);
starts_null= ends_null= execute_at_null= TRUE;
definer_user.str= definer_host.str= 0; definer_user.str= definer_host.str= 0;
definer_user.length= definer_host.length= 0; definer_user.length= definer_host.length= 0;
...@@ -157,10 +158,15 @@ event_timed::init_execute_at(THD *thd, Item *expr) ...@@ -157,10 +158,15 @@ event_timed::init_execute_at(THD *thd, Item *expr)
if (expr->fix_fields(thd, &expr)) if (expr->fix_fields(thd, &expr))
DBUG_RETURN(EVEX_PARSE_ERROR); DBUG_RETURN(EVEX_PARSE_ERROR);
/* Let's check whether time is in the past */ /* no starts and/or ends in case of execute_at */
thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, DBUG_PRINT("info", ("starts_null && ends_null should be 1 is %d",
(my_time_t) thd->query_start()); (starts_null && ends_null)))
DBUG_ASSERT(starts_null && ends_null);
// let's check whether time is in the past
thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp,
(my_time_t) thd->query_start());
if ((not_used= expr->get_date(&ltime, TIME_NO_ZERO_DATE))) if ((not_used= expr->get_date(&ltime, TIME_NO_ZERO_DATE)))
...@@ -177,7 +183,7 @@ event_timed::init_execute_at(THD *thd, Item *expr) ...@@ -177,7 +183,7 @@ event_timed::init_execute_at(THD *thd, Item *expr)
*/ */
my_tz_UTC->gmt_sec_to_TIME(&ltime, TIME_to_timestamp(thd,&ltime, &not_used)); my_tz_UTC->gmt_sec_to_TIME(&ltime, TIME_to_timestamp(thd,&ltime, &not_used));
execute_at_null= FALSE;
execute_at= ltime; execute_at= ltime;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -332,6 +338,7 @@ event_timed::init_starts(THD *thd, Item *new_starts) ...@@ -332,6 +338,7 @@ event_timed::init_starts(THD *thd, Item *new_starts)
my_tz_UTC->gmt_sec_to_TIME(&ltime, TIME_to_timestamp(thd, &ltime, &not_used)); my_tz_UTC->gmt_sec_to_TIME(&ltime, TIME_to_timestamp(thd, &ltime, &not_used));
starts= ltime; starts= ltime;
starts_null= FALSE;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -361,8 +368,7 @@ event_timed::init_starts(THD *thd, Item *new_starts) ...@@ -361,8 +368,7 @@ event_timed::init_starts(THD *thd, Item *new_starts)
int int
event_timed::init_ends(THD *thd, Item *new_ends) event_timed::init_ends(THD *thd, Item *new_ends)
{ {
TIME ltime; TIME ltime, ltime_now;
my_time_t my_time_tmp;
my_bool not_used; my_bool not_used;
DBUG_ENTER("event_timed::init_ends"); DBUG_ENTER("event_timed::init_ends");
...@@ -370,20 +376,34 @@ event_timed::init_ends(THD *thd, Item *new_ends) ...@@ -370,20 +376,34 @@ event_timed::init_ends(THD *thd, Item *new_ends)
if (new_ends->fix_fields(thd, &new_ends)) if (new_ends->fix_fields(thd, &new_ends))
DBUG_RETURN(EVEX_PARSE_ERROR); DBUG_RETURN(EVEX_PARSE_ERROR);
/* The field was already fixed in init_ends */ DBUG_PRINT("info", ("convert to TIME"));
if ((not_used= new_ends->get_date(&ltime, TIME_NO_ZERO_DATE))) if ((not_used= new_ends->get_date(&ltime, TIME_NO_ZERO_DATE)))
DBUG_RETURN(EVEX_BAD_PARAMS); DBUG_RETURN(EVEX_BAD_PARAMS);
/* /*
This may result in a 1970-01-01 date if ltime is > 2037-xx-xx. This may result in a 1970-01-01 date if ltime is > 2037-xx-xx ?
CONVERT_TZ has similar problem. CONVERT_TZ has similar problem ?
*/ */
DBUG_PRINT("info", ("get the UTC time"));
my_tz_UTC->gmt_sec_to_TIME(&ltime, TIME_to_timestamp(thd, &ltime, &not_used)); my_tz_UTC->gmt_sec_to_TIME(&ltime, TIME_to_timestamp(thd, &ltime, &not_used));
if (starts.year && my_time_compare(&starts, &ltime) != -1) /* Check whether ends is after starts */
DBUG_PRINT("info", ("ENDS after STARTS?"));
if (!starts_null && my_time_compare(&starts, &ltime) != -1)
DBUG_RETURN(EVEX_BAD_PARAMS);
/*
The parser forces starts to be provided but one day STARTS could be
set before NOW() and in this case the following check should be done.
Check whether ENDS is not in the past.
*/
DBUG_PRINT("info", ("ENDS after NOW?"));
my_tz_UTC->gmt_sec_to_TIME(&ltime_now, thd->query_start());
if (my_time_compare(&ltime_now, &ltime) == 1)
DBUG_RETURN(EVEX_BAD_PARAMS); DBUG_RETURN(EVEX_BAD_PARAMS);
ends= ltime; ends= ltime;
ends_null= FALSE;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -403,7 +423,7 @@ event_timed::init_comment(THD *thd, LEX_STRING *set_comment) ...@@ -403,7 +423,7 @@ event_timed::init_comment(THD *thd, LEX_STRING *set_comment)
DBUG_ENTER("event_timed::init_comment"); DBUG_ENTER("event_timed::init_comment");
comment.str= strmake_root(thd->mem_root, set_comment->str, comment.str= strmake_root(thd->mem_root, set_comment->str,
comment.length= set_comment->length); comment.length= set_comment->length);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -517,29 +537,38 @@ event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table) ...@@ -517,29 +537,38 @@ event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table)
len= et->definer.length - len - 1; //1 is because of @ len= et->definer.length - len - 1; //1 is because of @
et->definer_host.str= strmake_root(mem_root, ptr + 1, len);//1: because of @ et->definer_host.str= strmake_root(mem_root, ptr + 1, len);//1: because of @
et->definer_host.length= len; et->definer_host.length= len;
et->starts_null= table->field[EVEX_FIELD_STARTS]->is_null();
res1= table->field[EVEX_FIELD_STARTS]->get_date(&et->starts,TIME_NO_ZERO_DATE);
res1= table->field[EVEX_FIELD_STARTS]-> et->ends_null= table->field[EVEX_FIELD_ENDS]->is_null();
get_date(&et->starts, TIME_NO_ZERO_DATE); res2= table->field[EVEX_FIELD_ENDS]->get_date(&et->ends, TIME_NO_ZERO_DATE);
res2= table->field[EVEX_FIELD_ENDS]-> if (!table->field[EVEX_FIELD_INTERVAL_EXPR]->is_null())
get_date(&et->ends, TIME_NO_ZERO_DATE); et->expression= table->field[EVEX_FIELD_INTERVAL_EXPR]->val_int();
else
et->expression= table->field[EVEX_FIELD_INTERVAL_EXPR]->val_int(); et->expression= 0;
/* /*
If res1 and res2 are true then both fields are empty. If res1 and res2 are true then both fields are empty.
Hence if EVEX_FIELD_EXECUTE_AT is empty there is an error. Hence if EVEX_FIELD_EXECUTE_AT is empty there is an error.
*/ */
if (res1 && res2 && !et->expression && table->field[EVEX_FIELD_EXECUTE_AT]-> et->execute_at_null= table->field[EVEX_FIELD_EXECUTE_AT]->is_null();
get_date(&et->execute_at, TIME_NO_ZERO_DATE)) DBUG_ASSERT(!(et->starts_null && et->ends_null && !et->expression &&
et->execute_at_null));
if (!et->expression &&
table->field[EVEX_FIELD_EXECUTE_AT]->get_date(&et->execute_at,
TIME_NO_ZERO_DATE))
goto error; goto error;
/* /*
In DB the values start from 1 but enum interval_type starts In DB the values start from 1 but enum interval_type starts
from 0 from 0
*/ */
et->interval= (interval_type) if (!table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->is_null())
et->interval= (interval_type)
((ulonglong) table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->val_int() - 1); ((ulonglong) table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->val_int() - 1);
else
et->interval= (interval_type) 0;
et->modified= table->field[EVEX_FIELD_CREATED]->val_int(); et->modified= table->field[EVEX_FIELD_CREATED]->val_int();
et->created= table->field[EVEX_FIELD_MODIFIED]->val_int(); et->created= table->field[EVEX_FIELD_MODIFIED]->val_int();
...@@ -698,14 +727,11 @@ event_timed::compute_next_execution_time() ...@@ -698,14 +727,11 @@ event_timed::compute_next_execution_time()
/* Let's check whether it was executed */ /* Let's check whether it was executed */
if (last_executed.year) if (last_executed.year)
{ {
DBUG_PRINT("compute_next_execution_time", DBUG_PRINT("info",("One-time event %s.%s of was already executed",
("One-time event %s was already executed", name.str)); dbname.str, name.str, definer.str));
if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP) dropped= (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP);
{ DBUG_PRINT("info",("One-time event will be dropped=%d.", dropped));
DBUG_PRINT("compute_next_execution_time",
("One-time event will be dropped."));
dropped= true;
}
status= MYSQL_EVENT_DISABLED; status= MYSQL_EVENT_DISABLED;
status_changed= true; status_changed= true;
} }
...@@ -731,11 +757,12 @@ event_timed::compute_next_execution_time() ...@@ -731,11 +757,12 @@ event_timed::compute_next_execution_time()
last_executed.second); last_executed.second);
#endif #endif
/* If time_now is after ends don't execute anymore */ /* if time_now is after ends don't execute anymore */
if (ends.year && (tmp= my_time_compare(&ends, &time_now)) == -1) if (!ends_null && (tmp= my_time_compare(&ends, &time_now)) == -1)
{ {
/* time_now is after ends. don't execute anymore */ /* time_now is after ends. don't execute anymore */
set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME); set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
execute_at_null= TRUE;
if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP) if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
dropped= true; dropped= true;
status= MYSQL_EVENT_DISABLED; status= MYSQL_EVENT_DISABLED;
...@@ -749,7 +776,7 @@ event_timed::compute_next_execution_time() ...@@ -749,7 +776,7 @@ event_timed::compute_next_execution_time()
Let's check whether time_now is before starts. Let's check whether time_now is before starts.
If so schedule for starts. If so schedule for starts.
*/ */
if (starts.year && (tmp= my_time_compare(&time_now, &starts)) < 1) if (!starts_null && (tmp= my_time_compare(&time_now, &starts)) < 1)
{ {
if (tmp == 0 && my_time_compare(&starts, &last_executed) == 0) if (tmp == 0 && my_time_compare(&starts, &last_executed) == 0)
{ {
...@@ -765,11 +792,12 @@ event_timed::compute_next_execution_time() ...@@ -765,11 +792,12 @@ event_timed::compute_next_execution_time()
time_now before starts. Scheduling for starts time_now before starts. Scheduling for starts
*/ */
execute_at= starts; execute_at= starts;
execute_at_null= FALSE;
goto ret; goto ret;
} }
} }
if (starts.year && ends.year) if (!starts_null && !ends_null)
{ {
/* /*
Both starts and m_ends are set and time_now is between them (incl.) Both starts and m_ends are set and time_now is between them (incl.)
...@@ -778,7 +806,10 @@ event_timed::compute_next_execution_time() ...@@ -778,7 +806,10 @@ event_timed::compute_next_execution_time()
If not set then schedule for now. If not set then schedule for now.
*/ */
if (!last_executed.year) if (!last_executed.year)
{
execute_at= time_now; execute_at= time_now;
execute_at_null= FALSE;
}
else else
{ {
TIME next_exec; TIME next_exec;
...@@ -791,15 +822,19 @@ event_timed::compute_next_execution_time() ...@@ -791,15 +822,19 @@ event_timed::compute_next_execution_time()
{ {
/* Next execution after ends. No more executions */ /* Next execution after ends. No more executions */
set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME); set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
execute_at_null= TRUE;
if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP) if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
dropped= true; dropped= true;
} }
else else
{
execute_at= next_exec; execute_at= next_exec;
execute_at_null= FALSE;
}
} }
goto ret; goto ret;
} }
else if (!starts.year && !ends.year) else if (starts_null && ends_null)
{ {
/* /*
Both starts and m_ends are not set, so we schedule for the next Both starts and m_ends are not set, so we schedule for the next
...@@ -815,11 +850,12 @@ event_timed::compute_next_execution_time() ...@@ -815,11 +850,12 @@ event_timed::compute_next_execution_time()
/* last_executed not set. Schedule the event for now */ /* last_executed not set. Schedule the event for now */
execute_at= time_now; execute_at= time_now;
} }
execute_at_null= FALSE;
} }
else else
{ {
/* Either starts or m_ends is set */ /* either starts or m_ends is set */
if (starts.year) if (!starts_null)
{ {
/* /*
- starts is set. - starts is set.
...@@ -834,6 +870,7 @@ event_timed::compute_next_execution_time() ...@@ -834,6 +870,7 @@ event_timed::compute_next_execution_time()
} }
else else
execute_at= starts; execute_at= starts;
execute_at_null= FALSE;
} }
else else
{ {
...@@ -856,11 +893,15 @@ event_timed::compute_next_execution_time() ...@@ -856,11 +893,15 @@ event_timed::compute_next_execution_time()
if (my_time_compare(&ends, &next_exec) == -1) if (my_time_compare(&ends, &next_exec) == -1)
{ {
set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME); set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
execute_at_null= TRUE;
if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP) if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
dropped= true; dropped= true;
} }
else else
{
execute_at= next_exec; execute_at= next_exec;
execute_at_null= FALSE;
}
} }
} }
goto ret; goto ret;
...@@ -1324,10 +1365,7 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root) ...@@ -1324,10 +1365,7 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root)
sphead= lex.et->sphead; sphead= lex.et->sphead;
sphead->m_db= dbname; sphead->m_db= dbname;
/*
Ccopy also chistics since they will vanish otherwise we get 0x0 pointer
TODO: Handle sql_mode!!
*/
sphead->set_definer(definer.str, definer.length); sphead->set_definer(definer.str, definer.length);
sphead->set_info(0, 0, &lex.sp_chistics, sql_mode); sphead->set_info(0, 0, &lex.sp_chistics, sql_mode);
sphead->optimize(); sphead->optimize();
......
...@@ -3957,7 +3957,7 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) ...@@ -3957,7 +3957,7 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
sch_table->field[3]->store(et.definer.str, et.definer.length, scs); sch_table->field[3]->store(et.definer.str, et.definer.length, scs);
sch_table->field[4]->store(et.body.str, et.body.length, scs); sch_table->field[4]->store(et.body.str, et.body.length, scs);
// [9] is SQL_MODE /* [9] is SQL_MODE */
{ {
byte *sql_mode_str; byte *sql_mode_str;
ulong sql_mode_len=0; ulong sql_mode_len=0;
...@@ -3972,9 +3972,9 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) ...@@ -3972,9 +3972,9 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
String show_str; String show_str;
//type //type
sch_table->field[5]->store(STRING_WITH_LEN("RECURRING"), scs); sch_table->field[5]->store(STRING_WITH_LEN("RECURRING"), scs);
//execute_at /* execute_at */
sch_table->field[6]->set_null(); sch_table->field[6]->set_null();
//interval_value /* interval_value */
//interval_type //interval_type
if (event_reconstruct_interval_expression(&show_str, et.interval, if (event_reconstruct_interval_expression(&show_str, et.interval,
et.expression)) et.expression))
...@@ -3986,26 +3986,24 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) ...@@ -3986,26 +3986,24 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
LEX_STRING *ival= &interval_type_to_name[et.interval]; LEX_STRING *ival= &interval_type_to_name[et.interval];
sch_table->field[8]->set_notnull(); sch_table->field[8]->set_notnull();
sch_table->field[8]->store(ival->str, ival->length, scs); sch_table->field[8]->store(ival->str, ival->length, scs);
//starts & ends
//starts & ends
sch_table->field[10]->set_notnull(); sch_table->field[10]->set_notnull();
sch_table->field[10]->store_time(&et.starts, MYSQL_TIMESTAMP_DATETIME); sch_table->field[10]->store_time(&et.starts, MYSQL_TIMESTAMP_DATETIME);
sch_table->field[11]->set_notnull();
sch_table->field[11]->store_time(&et.ends, MYSQL_TIMESTAMP_DATETIME); if (!et.ends_null)
{
sch_table->field[11]->set_notnull();
sch_table->field[11]->store_time(&et.ends, MYSQL_TIMESTAMP_DATETIME);
}
} }
else else
{ {
//type //type
sch_table->field[5]->store(STRING_WITH_LEN("ONE TIME"), scs); sch_table->field[5]->store(STRING_WITH_LEN("ONE TIME"), scs);
//execute_at
sch_table->field[6]->set_notnull(); sch_table->field[6]->set_notnull();
sch_table->field[6]->store_time(&et.execute_at, MYSQL_TIMESTAMP_DATETIME); sch_table->field[6]->store_time(&et.execute_at, MYSQL_TIMESTAMP_DATETIME);
//interval
sch_table->field[7]->set_null();
//interval_type
sch_table->field[8]->set_null();
//starts & ends
sch_table->field[10]->set_null();
sch_table->field[11]->set_null();
} }
//status //status
......
...@@ -1476,6 +1476,9 @@ opt_ev_status: /* empty */ { $$= 0; } ...@@ -1476,6 +1476,9 @@ opt_ev_status: /* empty */ { $$= 0; }
; ;
ev_starts: /* empty */ ev_starts: /* empty */
{
Lex->et->init_starts(YYTHD, new Item_func_now_local());
}
| STARTS_SYM expr | STARTS_SYM expr
{ {
LEX *lex= Lex; LEX *lex= Lex;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment