mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
A cleanup for MDEV-17317 Add THD* parameter into Item::get_date() and stricter data type control to "fuzzydate"
Fixing C++ function check_date() to get the "fuzzydate" as date_mode_t rather than ulonglong, so conversion from date_time_t to ulonglong is now done inside C++ check_date(), and no conversion is needed in the callers' code. As an additional safety, modified the code not to pass TIME_FUZZY_DATE to the low level C functions: - check_date() - str_to_datetime() - str_to_time() - number_to_datetime() because TIME_FUZZY_DATE is known only on the C++ level, C functions do not know it. Soon we'll be adding more flags into the C++ level (i.e. to date_time_t), e.g. for rounding. It's a good idea to prevent passing C++ specific flags into pure C routines before this change. Asserts were added into the affected C functions to verify that the caller passed only known C level flags.
This commit is contained in:
@ -58,6 +58,20 @@ uint calc_days_in_year(uint year)
|
|||||||
366 : 365);
|
366 : 365);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
|
||||||
|
static const ulonglong C_KNOWN_FLAGS= C_TIME_NO_ZERO_IN_DATE |
|
||||||
|
C_TIME_NO_ZERO_DATE |
|
||||||
|
C_TIME_INVALID_DATES |
|
||||||
|
C_TIME_TIME_ONLY |
|
||||||
|
C_TIME_DATETIME_ONLY;
|
||||||
|
|
||||||
|
#define C_FLAGS_OK(flags) (((flags) & ~C_KNOWN_FLAGS) == 0)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Check datetime value for validity according to flags.
|
@brief Check datetime value for validity according to flags.
|
||||||
|
|
||||||
@ -82,6 +96,7 @@ uint calc_days_in_year(uint year)
|
|||||||
my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date,
|
my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date,
|
||||||
ulonglong flags, int *was_cut)
|
ulonglong flags, int *was_cut)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(C_FLAGS_OK(flags));
|
||||||
if (ltime->time_type == MYSQL_TIMESTAMP_TIME)
|
if (ltime->time_type == MYSQL_TIMESTAMP_TIME)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (not_zero_date)
|
if (not_zero_date)
|
||||||
@ -298,6 +313,7 @@ str_to_datetime(const char *str, size_t length, MYSQL_TIME *l_time,
|
|||||||
const char *end=str+length, *pos;
|
const char *end=str+length, *pos;
|
||||||
uint number_of_fields= 0, digits, year_length, not_zero_date;
|
uint number_of_fields= 0, digits, year_length, not_zero_date;
|
||||||
DBUG_ENTER("str_to_datetime");
|
DBUG_ENTER("str_to_datetime");
|
||||||
|
DBUG_ASSERT(C_FLAGS_OK(flags));
|
||||||
bzero(l_time, sizeof(*l_time));
|
bzero(l_time, sizeof(*l_time));
|
||||||
|
|
||||||
if (flags & C_TIME_TIME_ONLY)
|
if (flags & C_TIME_TIME_ONLY)
|
||||||
@ -464,6 +480,7 @@ my_bool str_to_time(const char *str, size_t length, MYSQL_TIME *l_time,
|
|||||||
const char *end=str+length, *end_of_days;
|
const char *end=str+length, *end_of_days;
|
||||||
my_bool found_days,found_hours, neg= 0;
|
my_bool found_days,found_hours, neg= 0;
|
||||||
uint UNINIT_VAR(state);
|
uint UNINIT_VAR(state);
|
||||||
|
DBUG_ASSERT(C_FLAGS_OK(fuzzydate));
|
||||||
|
|
||||||
my_time_status_init(status);
|
my_time_status_init(status);
|
||||||
for (; str != end && my_isspace(&my_charset_latin1,*str) ; str++)
|
for (; str != end && my_isspace(&my_charset_latin1,*str) ; str++)
|
||||||
@ -1209,6 +1226,7 @@ longlong number_to_datetime(longlong nr, ulong sec_part, MYSQL_TIME *time_res,
|
|||||||
ulonglong flags, int *was_cut)
|
ulonglong flags, int *was_cut)
|
||||||
{
|
{
|
||||||
long part1,part2;
|
long part1,part2;
|
||||||
|
DBUG_ASSERT(C_FLAGS_OK(flags));
|
||||||
|
|
||||||
*was_cut= 0;
|
*was_cut= 0;
|
||||||
time_res->time_type=MYSQL_TIMESTAMP_DATE;
|
time_res->time_type=MYSQL_TIMESTAMP_DATE;
|
||||||
|
@ -441,7 +441,7 @@ static bool extract_date_time(THD *thd, DATE_TIME_FORMAT *format,
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
int was_cut;
|
int was_cut;
|
||||||
if (check_date(l_time, ulonglong(fuzzydate | TIME_INVALID_DATES), &was_cut))
|
if (check_date(l_time, fuzzydate | TIME_INVALID_DATES, &was_cut))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (val != val_end)
|
if (val != val_end)
|
||||||
|
@ -98,5 +98,11 @@ const date_mode_t
|
|||||||
TIME_NO_ZERO_DATE (date_mode_t::value_t::NO_ZERO_DATE),
|
TIME_NO_ZERO_DATE (date_mode_t::value_t::NO_ZERO_DATE),
|
||||||
TIME_INVALID_DATES (date_mode_t::value_t::INVALID_DATES);
|
TIME_INVALID_DATES (date_mode_t::value_t::INVALID_DATES);
|
||||||
|
|
||||||
|
// Flags understood by str_to_datetime, str_to_time, number_to_time, check_date
|
||||||
|
static const date_mode_t
|
||||||
|
TIME_MODE_FOR_XXX_TO_DATE (date_mode_t::NO_ZERO_IN_DATE |
|
||||||
|
date_mode_t::NO_ZERO_DATE |
|
||||||
|
date_mode_t::INVALID_DATES |
|
||||||
|
date_mode_t::TIME_ONLY);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -293,7 +293,7 @@ check_date_with_warn(THD *thd, const MYSQL_TIME *ltime, date_mode_t fuzzydate,
|
|||||||
timestamp_type ts_type)
|
timestamp_type ts_type)
|
||||||
{
|
{
|
||||||
int unused;
|
int unused;
|
||||||
if (check_date(ltime, ulonglong(fuzzydate), &unused))
|
if (check_date(ltime, fuzzydate, &unused))
|
||||||
{
|
{
|
||||||
ErrConvTime str(ltime);
|
ErrConvTime str(ltime);
|
||||||
make_truncated_value_warning(thd, Sql_condition::WARN_LEVEL_WARN,
|
make_truncated_value_warning(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||||
@ -377,7 +377,9 @@ bool Temporal::str_to_time(MYSQL_TIME_STATUS *status,
|
|||||||
date_mode_t fuzzydate)
|
date_mode_t fuzzydate)
|
||||||
{
|
{
|
||||||
TemporalAsciiBuffer tmp(str, length, cs);
|
TemporalAsciiBuffer tmp(str, length, cs);
|
||||||
return ::str_to_time(tmp.str, tmp.length, this, ulonglong(fuzzydate), status);
|
return ::str_to_time(tmp.str, tmp.length, this,
|
||||||
|
ulonglong(fuzzydate & TIME_MODE_FOR_XXX_TO_DATE),
|
||||||
|
status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -387,7 +389,9 @@ bool Temporal::str_to_datetime(MYSQL_TIME_STATUS *status,
|
|||||||
date_mode_t flags)
|
date_mode_t flags)
|
||||||
{
|
{
|
||||||
TemporalAsciiBuffer tmp(str, length, cs);
|
TemporalAsciiBuffer tmp(str, length, cs);
|
||||||
return ::str_to_datetime(tmp.str, tmp.length, this, ulonglong(flags), status);
|
return ::str_to_datetime(tmp.str, tmp.length, this,
|
||||||
|
ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE),
|
||||||
|
status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -407,7 +411,8 @@ str_to_datetime_with_warn(THD *thd, CHARSET_INFO *cs,
|
|||||||
MYSQL_TIME_STATUS status;
|
MYSQL_TIME_STATUS status;
|
||||||
TemporalAsciiBuffer tmp(str, length, cs);
|
TemporalAsciiBuffer tmp(str, length, cs);
|
||||||
bool ret_val= str_to_datetime(tmp.str, tmp.length, l_time,
|
bool ret_val= str_to_datetime(tmp.str, tmp.length, l_time,
|
||||||
ulonglong(flags), &status);
|
ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE),
|
||||||
|
&status);
|
||||||
if (ret_val || status.warnings)
|
if (ret_val || status.warnings)
|
||||||
{
|
{
|
||||||
const ErrConvString err(str, length, &my_charset_bin);
|
const ErrConvString err(str, length, &my_charset_bin);
|
||||||
@ -1339,7 +1344,7 @@ time_to_datetime_with_warn(THD *thd,
|
|||||||
*/
|
*/
|
||||||
if (time_to_datetime(thd, from, to) ||
|
if (time_to_datetime(thd, from, to) ||
|
||||||
((thd->variables.old_behavior & OLD_MODE_ZERO_DATE_TIME_CAST) &&
|
((thd->variables.old_behavior & OLD_MODE_ZERO_DATE_TIME_CAST) &&
|
||||||
check_date(to, ulonglong(fuzzydate), &warn)))
|
check_date(to, fuzzydate, &warn)))
|
||||||
{
|
{
|
||||||
ErrConvTime str(from);
|
ErrConvTime str(from);
|
||||||
thd->push_warning_truncated_wrong_value("datetime", str.ptr());
|
thd->push_warning_truncated_wrong_value("datetime", str.ptr());
|
||||||
|
@ -167,9 +167,10 @@ non_zero_date(const MYSQL_TIME *ltime)
|
|||||||
non_zero_hhmmssuu(ltime));
|
non_zero_hhmmssuu(ltime));
|
||||||
}
|
}
|
||||||
static inline bool
|
static inline bool
|
||||||
check_date(const MYSQL_TIME *ltime, ulonglong flags, int *was_cut)
|
check_date(const MYSQL_TIME *ltime, date_mode_t flags, int *was_cut)
|
||||||
{
|
{
|
||||||
return check_date(ltime, non_zero_date(ltime), flags, was_cut);
|
return check_date(ltime, non_zero_date(ltime),
|
||||||
|
ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), was_cut);
|
||||||
}
|
}
|
||||||
bool check_date_with_warn(THD *thd, const MYSQL_TIME *ltime, date_mode_t fuzzy_date,
|
bool check_date_with_warn(THD *thd, const MYSQL_TIME *ltime, date_mode_t fuzzy_date,
|
||||||
timestamp_type ts_type);
|
timestamp_type ts_type);
|
||||||
|
@ -480,7 +480,8 @@ void Temporal_with_date::make_from_item(THD *thd, Item *item)
|
|||||||
|
|
||||||
void Temporal_with_date::check_date_or_invalidate(int *warn, date_mode_t flags)
|
void Temporal_with_date::check_date_or_invalidate(int *warn, date_mode_t flags)
|
||||||
{
|
{
|
||||||
if (check_date(this, pack_time(this) != 0, ulonglong(flags), warn))
|
if (check_date(this, pack_time(this) != 0,
|
||||||
|
ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), warn))
|
||||||
time_type= MYSQL_TIMESTAMP_NONE;
|
time_type= MYSQL_TIMESTAMP_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,7 +285,9 @@ public:
|
|||||||
*warn= MYSQL_TIME_WARN_OUT_OF_RANGE;
|
*warn= MYSQL_TIME_WARN_OUT_OF_RANGE;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return number_to_datetime(m_sec, m_usec, to, ulonglong(flags), warn) == -1;
|
return number_to_datetime(m_sec, m_usec, to,
|
||||||
|
ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE),
|
||||||
|
warn) == -1;
|
||||||
}
|
}
|
||||||
// Convert elapsed seconds to TIME
|
// Convert elapsed seconds to TIME
|
||||||
bool sec_to_time(MYSQL_TIME *ltime, uint dec) const
|
bool sec_to_time(MYSQL_TIME *ltime, uint dec) const
|
||||||
@ -1230,7 +1232,9 @@ public:
|
|||||||
bool check_date(date_mode_t flags, int *warnings) const
|
bool check_date(date_mode_t flags, int *warnings) const
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(is_valid_datetime_slow());
|
DBUG_ASSERT(is_valid_datetime_slow());
|
||||||
return ::check_date(this, (year || month || day), ulonglong(flags), warnings);
|
return ::check_date(this, (year || month || day),
|
||||||
|
ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE),
|
||||||
|
warnings);
|
||||||
}
|
}
|
||||||
bool check_date(date_mode_t flags) const
|
bool check_date(date_mode_t flags) const
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user