1
0
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:
Aleksey Midenkov
2026-06-29 14:00:02 +03:00
parent 1d2978a3f6
commit a78a6c2b0c
3 changed files with 66 additions and 15 deletions

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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 */