mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-25529 Replace COMBINE macro with interval2sec() and interval2usec()
Turn the COMBINE macro of date_add_interval() into inline functions with overloads for INTERVAL and MYSQL_TIME, so that the history partition sizing can reuse the seconds part. Move the "Daynumber" comment that sat above the macro to MAX_DAY_NUMBER, which it describes. MAX_DAY_NUMBER moves to sql_time.h as a constexpr (the unused copy in item_timefunc.cc is removed), and the range check of date_add_interval() becomes the inline interval_days_out_of_range(), so that the sizing can check that the seconds do not overflow.
This commit is contained in:
@@ -51,9 +51,6 @@
|
||||
#include <m_ctype.h>
|
||||
#include <time.h>
|
||||
|
||||
/** Day number for Dec 31st, 9999. */
|
||||
#define MAX_DAY_NUMBER 3652424L
|
||||
|
||||
Func_handler_date_add_interval_datetime_arg0_time
|
||||
func_handler_date_add_interval_datetime_arg0_time;
|
||||
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
#include <m_ctype.h>
|
||||
|
||||
|
||||
#define MAX_DAY_NUMBER 3652424L
|
||||
|
||||
/* Some functions to calculate dates */
|
||||
|
||||
/*
|
||||
@@ -604,11 +602,6 @@ void make_truncated_value_warning(THD *thd,
|
||||
}
|
||||
|
||||
|
||||
/* Daynumber from year 0 to 9999-12-31 */
|
||||
#define COMBINE(X) \
|
||||
(((((X)->day * 24LL + (X)->hour) * 60LL + \
|
||||
(X)->minute) * 60LL + (X)->second)*1000000LL + \
|
||||
(X)->second_part)
|
||||
#define GET_PART(X, N) X % N ## LL; X/= N ## LL
|
||||
|
||||
bool date_add_interval(THD *thd, MYSQL_TIME *ltime, interval_type int_type,
|
||||
@@ -639,16 +632,13 @@ bool date_add_interval(THD *thd, MYSQL_TIME *ltime, interval_type int_type,
|
||||
my_bool neg= 0;
|
||||
enum enum_mysql_timestamp_type time_type= ltime->time_type;
|
||||
|
||||
if (((ulonglong) interval.day +
|
||||
(ulonglong) interval.hour / 24 +
|
||||
(ulonglong) interval.minute / 24 / 60 +
|
||||
(ulonglong) interval.second / 24 / 60 / 60) > MAX_DAY_NUMBER)
|
||||
if (interval_days_out_of_range(interval))
|
||||
goto invalid_date;
|
||||
|
||||
if (time_type != MYSQL_TIMESTAMP_TIME)
|
||||
ltime->day+= calc_daynr(ltime->year, ltime->month, 1) - 1;
|
||||
|
||||
usec= COMBINE(ltime) + sign*COMBINE(&interval);
|
||||
usec= interval2usec(ltime) + sign * interval2usec(&interval);
|
||||
|
||||
if (usec < 0)
|
||||
{
|
||||
|
||||
@@ -168,4 +168,68 @@ void unpack_time(longlong packed, MYSQL_TIME *my_time,
|
||||
enum_mysql_timestamp_type ts_type)
|
||||
__attribute__((nonnull));
|
||||
|
||||
/* Day number of 9999-12-31 */
|
||||
static constexpr longlong MAX_DAY_NUMBER= 3652424;
|
||||
|
||||
/**
|
||||
Check if the day-time part of an interval is longer than the date range
|
||||
(MAX_DAY_NUMBER days). Otherwise the interval converted with interval2sec()
|
||||
or interval2usec() does not overflow.
|
||||
*/
|
||||
inline bool interval_days_out_of_range(const INTERVAL &interval)
|
||||
{
|
||||
return (ulonglong(interval.day) +
|
||||
ulonglong(interval.hour) / 24 +
|
||||
ulonglong(interval.minute) / 24 / 60 +
|
||||
ulonglong(interval.second) / 24 / 60 / 60) > MAX_DAY_NUMBER;
|
||||
}
|
||||
|
||||
/**
|
||||
Convert an interval to a total number of seconds.
|
||||
|
||||
The @c year and @c month members must be 0 (asserted). The @c neg member
|
||||
is ignored: the caller applies the sign.
|
||||
|
||||
@param x Interval.
|
||||
|
||||
@return Total number of seconds represented by @p x.
|
||||
*/
|
||||
inline longlong interval2sec(const INTERVAL *x)
|
||||
{
|
||||
DBUG_ASSERT(!x->year && !x->month);
|
||||
return ((x->day * 24LL + x->hour) * 60LL + x->minute) * 60LL + x->second;
|
||||
}
|
||||
|
||||
/**
|
||||
Convert a time value to a total number of seconds.
|
||||
|
||||
The @c year, @c month and @c neg members are ignored: date_add_interval()
|
||||
folds year and month into day and applies the sign itself.
|
||||
|
||||
@param x Time value.
|
||||
|
||||
@return Seconds of the day, hour, minute and second members of @p x.
|
||||
*/
|
||||
inline longlong interval2sec(const MYSQL_TIME *x)
|
||||
{
|
||||
return ((x->day * 24LL + x->hour) * 60LL + x->minute) * 60LL + x->second;
|
||||
}
|
||||
|
||||
/**
|
||||
Convert an interval to a total number of microseconds:
|
||||
interval2sec() * 1000000 + @c second_part.
|
||||
*/
|
||||
inline longlong interval2usec(const INTERVAL *x)
|
||||
{
|
||||
return interval2sec(x) * 1000000LL + x->second_part;
|
||||
}
|
||||
|
||||
/**
|
||||
Convert a time value to microseconds: interval2sec() * 1000000 +
|
||||
@c second_part.
|
||||
*/
|
||||
inline longlong interval2usec(const MYSQL_TIME *x)
|
||||
{
|
||||
return interval2sec(x) * 1000000LL + x->second_part;
|
||||
}
|
||||
#endif /* SQL_TIME_INCLUDED */
|
||||
|
||||
Reference in New Issue
Block a user