diff options
author | unknown <andrey@lmy004.> | 2006-01-18 20:41:22 +0100 |
---|---|---|
committer | unknown <andrey@lmy004.> | 2006-01-18 20:41:22 +0100 |
commit | 6bd58a2a3ce27eb744a8d35893f5bfefd9e173dd (patch) | |
tree | 364b1773d1b0b50d5005939089eefee7bc15af75 /sql/time.cc | |
parent | ef3a610638a4d0742a8b4a33e329f5f963e55bec (diff) | |
download | mariadb-git-6bd58a2a3ce27eb744a8d35893f5bfefd9e173dd.tar.gz |
- fix bug #16435 (Weekly events execute every second) (WL#1034 Internal CRON)
Before the interval expression was considered to be in seconds, now it is
just a number and the type of interval is considered.
- this changeset introduces also fix for bug#16432 (Events: error re interval
misrepresents the facts)
the code of event_timed::set_interval() was refactored anyway so it is meaningful to
fix the bug in the same changeset.
include/my_time.h:
- move enum interval_type to include/my_time.h so it can be used by functions
in the whole server
sql/event.cc:
- don't use second_part
- fix small problem with create event xyz, when xyz exists -> make it error
instead of warning if create_if_not is false.
sql/event.h:
pass thd to mark_last_executed() to be able to call thd->end_time()
sql/event_executor.cc:
- pass thd to event_timed::compute_next_execution_time()
- a bit more DBUG info in the server log
- handle error returned by event_timed::compute_next_execution_time()
sql/event_priv.h:
- define the maximal possible value for interval_value
sql/event_timed.cc:
- more docs
- add static get_next_time() which sums a TIME with an interval
- fix bug #16435 (Weekly events execute every second)
Before the interval expression was considered to be in seconds, now it is
just a number and the type of interval is considered.
- fix for bug#16432 (Events: error re interval misrepresents the facts)
(return an error if a value is too big or is negative - errmsg changed)
sql/item_timefunc.cc:
- export get_interval_date()
- refactor Item_date_add_interval::get_date() and extract the core
to date_add_interval() in time.cc so it can be reused by the
scheduler code in event_timed.cc
sql/item_timefunc.h:
- export get_interval_value() so it can be reused in event_timed.cc in
function static get_next_time()
- move enum interval_type to include/my_time.h so it can be used by functions
in the whole server
sql/mysql_priv.h:
export the new function date_add_interval() added to time.cc
sql/share/errmsg.txt:
- change error message to be appropriate as fix for bug#16432
(Events: error re interval misrepresents the facts)
sql/sql_yacc.yy:
- change error message to be appropriate as fix for bug#16432
(Events: error re interval misrepresents the facts)
sql/time.cc:
extract the core of Item_date_add_interval::get_date()
to a function per Serg's request. The code can be reused
to add und substract interval from a date.
Diffstat (limited to 'sql/time.cc')
-rw-r--r-- | sql/time.cc | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/sql/time.cc b/sql/time.cc index 480cafaab34..efe1cbf1c09 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -724,5 +724,113 @@ void make_truncated_value_warning(THD *thd, const char *str_val, ER_TRUNCATED_WRONG_VALUE, warn_buff); } +#define MAX_DAY_NUMBER 3652424L + +bool date_add_interval(TIME *ltime, interval_type int_type, INTERVAL interval) +{ + long period, sign; + + ltime->neg= 0; + + sign= (interval.neg ? -1 : 1); + + switch (int_type) { + case INTERVAL_SECOND: + case INTERVAL_SECOND_MICROSECOND: + case INTERVAL_MICROSECOND: + case INTERVAL_MINUTE: + case INTERVAL_HOUR: + case INTERVAL_MINUTE_MICROSECOND: + case INTERVAL_MINUTE_SECOND: + case INTERVAL_HOUR_MICROSECOND: + case INTERVAL_HOUR_SECOND: + case INTERVAL_HOUR_MINUTE: + case INTERVAL_DAY_MICROSECOND: + case INTERVAL_DAY_SECOND: + case INTERVAL_DAY_MINUTE: + case INTERVAL_DAY_HOUR: + { + longlong sec, days, daynr, microseconds, extra_sec; + ltime->time_type= MYSQL_TIMESTAMP_DATETIME; // Return full date + microseconds= ltime->second_part + sign*interval.second_part; + extra_sec= microseconds/1000000L; + microseconds= microseconds%1000000L; + + sec=((ltime->day-1)*3600*24L+ltime->hour*3600+ltime->minute*60+ + ltime->second + + sign* (longlong) (interval.day*3600*24L + + interval.hour*LL(3600)+interval.minute*LL(60)+ + interval.second))+ extra_sec; + if (microseconds < 0) + { + microseconds+= LL(1000000); + sec--; + } + days= sec/(3600*LL(24)); + sec-= days*3600*LL(24); + if (sec < 0) + { + days--; + sec+= 3600*LL(24); + } + ltime->second_part= (uint) microseconds; + ltime->second= (uint) (sec % 60); + ltime->minute= (uint) (sec/60 % 60); + ltime->hour= (uint) (sec/3600); + daynr= calc_daynr(ltime->year,ltime->month,1) + days; + /* Day number from year 0 to 9999-12-31 */ + if ((ulonglong) daynr >= MAX_DAY_NUMBER) + goto invalid_date; + get_date_from_daynr((long) daynr, <ime->year, <ime->month, + <ime->day); + break; + } + case INTERVAL_DAY: + case INTERVAL_WEEK: + period= (calc_daynr(ltime->year,ltime->month,ltime->day) + + sign * (long) interval.day); + /* Daynumber from year 0 to 9999-12-31 */ + if ((ulong) period >= MAX_DAY_NUMBER) + goto invalid_date; + get_date_from_daynr((long) period,<ime->year,<ime->month,<ime->day); + break; + case INTERVAL_YEAR: + ltime->year+= sign * (long) interval.year; + if ((ulong) ltime->year >= 10000L) + goto invalid_date; + if (ltime->month == 2 && ltime->day == 29 && + calc_days_in_year(ltime->year) != 366) + ltime->day=28; // Was leap-year + break; + case INTERVAL_YEAR_MONTH: + case INTERVAL_QUARTER: + case INTERVAL_MONTH: + period= (ltime->year*12 + sign * (long) interval.year*12 + + ltime->month-1 + sign * (long) interval.month); + if ((ulong) period >= 120000L) + goto invalid_date; + ltime->year= (uint) (period / 12); + ltime->month= (uint) (period % 12L)+1; + /* Adjust day if the new month doesn't have enough days */ + if (ltime->day > days_in_month[ltime->month-1]) + { + ltime->day = days_in_month[ltime->month-1]; + if (ltime->month == 2 && calc_days_in_year(ltime->year) == 366) + ltime->day++; // Leap-year + } + break; + default: + return 1; + } + return 0; // Ok + +invalid_date: + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_DATETIME_FUNCTION_OVERFLOW, + ER(ER_DATETIME_FUNCTION_OVERFLOW), + "datetime"); + return 1; +} + #endif |