MDEV-17712 Remove C_TIME_FUZZY_DATES, C_TIME_DATETIME_ONLY, C_TIME_TIME_ONLY

This commit is contained in:
Alexander Barkov 2018-11-14 16:00:38 +04:00
parent 62bcd74712
commit b9a9055793
11 changed files with 155 additions and 104 deletions

View File

@ -1893,7 +1893,7 @@ static my_time_t convert_str_to_timestamp(const char* str)
uint dummy_in_dst_time_gap; uint dummy_in_dst_time_gap;
/* We require a total specification (date AND time) */ /* We require a total specification (date AND time) */
if (str_to_datetime(str, (uint) strlen(str), &l_time, 0, &status) || if (str_to_datetime_or_date(str, (uint) strlen(str), &l_time, 0, &status) ||
l_time.time_type != MYSQL_TIMESTAMP_DATETIME || status.warnings) l_time.time_type != MYSQL_TIMESTAMP_DATETIME || status.warnings)
{ {
error("Incorrect date and time argument: %s", str); error("Incorrect date and time argument: %s", str);

View File

@ -57,13 +57,6 @@ extern uchar days_in_month[];
/* Flags to str_to_datetime */ /* Flags to str_to_datetime */
/*
TIME_FUZZY_DATES is used for the result will only be used for comparison
purposes. Conversion is as relaxed as possible.
*/
#define C_TIME_FUZZY_DATES 1U
#define C_TIME_DATETIME_ONLY 2U
#define C_TIME_TIME_ONLY 4U
#define C_TIME_NO_ZERO_IN_DATE (1UL << 23) /* == MODE_NO_ZERO_IN_DATE */ #define C_TIME_NO_ZERO_IN_DATE (1UL << 23) /* == MODE_NO_ZERO_IN_DATE */
#define C_TIME_NO_ZERO_DATE (1UL << 24) /* == MODE_NO_ZERO_DATE */ #define C_TIME_NO_ZERO_DATE (1UL << 24) /* == MODE_NO_ZERO_DATE */
#define C_TIME_INVALID_DATES (1UL << 25) /* == MODE_INVALID_DATES */ #define C_TIME_INVALID_DATES (1UL << 25) /* == MODE_INVALID_DATES */
@ -117,15 +110,18 @@ my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date,
ulonglong flags, int *was_cut); ulonglong flags, int *was_cut);
my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *l_time, my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *l_time,
ulong max_hour, MYSQL_TIME_STATUS *status); ulong max_hour, MYSQL_TIME_STATUS *status);
my_bool str_to_time(const char *str, size_t length, MYSQL_TIME *l_time, my_bool str_to_datetime_or_date_or_time(const char *str, size_t length,
ulonglong flag, MYSQL_TIME_STATUS *status); MYSQL_TIME *to, ulonglong flag,
my_bool str_to_datetime(const char *str, size_t length, MYSQL_TIME *l_time, MYSQL_TIME_STATUS *status);
ulonglong flags, MYSQL_TIME_STATUS *status); my_bool str_to_datetime_or_date(const char *str, size_t length, MYSQL_TIME *to,
longlong number_to_datetime(longlong nr, ulong sec_part, MYSQL_TIME *time_res, ulonglong flags, MYSQL_TIME_STATUS *status);
ulonglong flags, int *was_cut);
longlong number_to_datetime_or_date(longlong nr, ulong sec_part,
MYSQL_TIME *time_res,
ulonglong flags, int *was_cut);
int number_to_time_only(my_bool neg, ulonglong nr, ulong sec_part,
MYSQL_TIME *ltime, int *was_cut);
int number_to_time(my_bool neg, ulonglong nr, ulong sec_part,
MYSQL_TIME *ltime, int *was_cut);
ulonglong TIME_to_ulonglong_datetime(const MYSQL_TIME *); ulonglong TIME_to_ulonglong_datetime(const MYSQL_TIME *);
ulonglong TIME_to_ulonglong_date(const MYSQL_TIME *); ulonglong TIME_to_ulonglong_date(const MYSQL_TIME *);
ulonglong TIME_to_ulonglong_time(const MYSQL_TIME *); ulonglong TIME_to_ulonglong_time(const MYSQL_TIME *);

View File

@ -3215,7 +3215,7 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value, size_t
{ {
MYSQL_TIME *tm= (MYSQL_TIME *)buffer; MYSQL_TIME *tm= (MYSQL_TIME *)buffer;
MYSQL_TIME_STATUS status; MYSQL_TIME_STATUS status;
str_to_time(value, length, tm, 0, &status); str_to_datetime_or_date_or_time(value, length, tm, 0, &status);
err= status.warnings; err= status.warnings;
*param->error= MY_TEST(err); *param->error= MY_TEST(err);
break; break;
@ -3226,7 +3226,7 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value, size_t
{ {
MYSQL_TIME *tm= (MYSQL_TIME *)buffer; MYSQL_TIME *tm= (MYSQL_TIME *)buffer;
MYSQL_TIME_STATUS status; MYSQL_TIME_STATUS status;
(void) str_to_datetime(value, length, tm, 0, &status); (void) str_to_datetime_or_date(value, length, tm, 0, &status);
err= status.warnings; err= status.warnings;
*param->error= MY_TEST(err) && (param->buffer_type == MYSQL_TYPE_DATE && *param->error= MY_TEST(err) && (param->buffer_type == MYSQL_TYPE_DATE &&
tm->time_type != MYSQL_TIMESTAMP_DATE); tm->time_type != MYSQL_TIMESTAMP_DATE);
@ -3350,7 +3350,7 @@ static void fetch_long_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
case MYSQL_TYPE_DATETIME: case MYSQL_TYPE_DATETIME:
{ {
int error; int error;
value= number_to_datetime(value, 0, (MYSQL_TIME *) buffer, 0, &error); value= number_to_datetime_or_date(value, 0, (MYSQL_TIME *) buffer, 0, &error);
*param->error= MY_TEST(error); *param->error= MY_TEST(error);
break; break;
} }

View File

@ -63,9 +63,7 @@ uint calc_days_in_year(uint year)
static const ulonglong C_KNOWN_FLAGS= C_TIME_NO_ZERO_IN_DATE | static const ulonglong C_KNOWN_FLAGS= C_TIME_NO_ZERO_IN_DATE |
C_TIME_NO_ZERO_DATE | C_TIME_NO_ZERO_DATE |
C_TIME_INVALID_DATES | C_TIME_INVALID_DATES;
C_TIME_TIME_ONLY |
C_TIME_DATETIME_ONLY;
#define C_FLAGS_OK(flags) (((flags) & ~C_KNOWN_FLAGS) == 0) #define C_FLAGS_OK(flags) (((flags) & ~C_KNOWN_FLAGS) == 0)
@ -161,7 +159,8 @@ static int get_punct(const char **str, const char *end)
return 1; return 1;
} }
static int get_date_time_separator(uint *number_of_fields, ulonglong flags, static int get_date_time_separator(uint *number_of_fields,
my_bool punct_is_date_time_separator,
const char **str, const char *end) const char **str, const char *end)
{ {
const char *s= *str; const char *s= *str;
@ -180,11 +179,11 @@ static int get_date_time_separator(uint *number_of_fields, ulonglong flags,
but but
cast("11:11:11.12.12.12" as time) should give 11:11:11.12 cast("11:11:11.12.12.12" as time) should give 11:11:11.12
that is, a punctuation character can be accepted as a date/time separator that is, a punctuation character can be accepted as a date/time separator
only if TIME_DATETIME_ONLY (see str_to_time) is not set. only if "punct_is_date_time_separator" is set.
*/ */
if (my_ispunct(&my_charset_latin1, *s)) if (my_ispunct(&my_charset_latin1, *s))
{ {
if (flags & C_TIME_DATETIME_ONLY) if (!punct_is_date_time_separator)
{ {
/* see above, returning 1 is not enough, we need hard abort here */ /* see above, returning 1 is not enough, we need hard abort here */
*number_of_fields= 0; *number_of_fields= 0;
@ -414,6 +413,9 @@ str_to_DDhhmmssff_internal(my_bool neg, const char *str, size_t length,
TIME_NO_ZERO_IN_DATE Don't allow partial dates TIME_NO_ZERO_IN_DATE Don't allow partial dates
TIME_NO_ZERO_DATE Don't allow 0000-00-00 date TIME_NO_ZERO_DATE Don't allow 0000-00-00 date
TIME_INVALID_DATES Allow 2000-02-31 TIME_INVALID_DATES Allow 2000-02-31
punct_is_date_time_separator
Allow punctuation as a date/time separator,
or return a hard error.
status Conversion status status Conversion status
@ -448,7 +450,9 @@ str_to_DDhhmmssff_internal(my_bool neg, const char *str, size_t length,
static my_bool static my_bool
str_to_datetime_or_date_body(const char *str, size_t length, MYSQL_TIME *l_time, str_to_datetime_or_date_body(const char *str, size_t length, MYSQL_TIME *l_time,
ulonglong flags, MYSQL_TIME_STATUS *status) ulonglong flags,
my_bool punct_is_date_time_separator,
MYSQL_TIME_STATUS *status)
{ {
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;
@ -503,7 +507,8 @@ str_to_datetime_or_date_body(const char *str, size_t length, MYSQL_TIME *l_time,
|| get_number(&l_time->month, &number_of_fields, &str, end) || get_number(&l_time->month, &number_of_fields, &str, end)
|| get_punct(&str, end) || get_punct(&str, end)
|| get_number(&l_time->day, &number_of_fields, &str, end) || get_number(&l_time->day, &number_of_fields, &str, end)
|| get_date_time_separator(&number_of_fields, flags, &str, end) || get_date_time_separator(&number_of_fields,
punct_is_date_time_separator, &str, end)
|| get_number(&l_time->hour, &number_of_fields, &str, end) || get_number(&l_time->hour, &number_of_fields, &str, end)
|| get_punct(&str, end) || get_punct(&str, end)
|| get_number(&l_time->minute, &number_of_fields, &str, end) || get_number(&l_time->minute, &number_of_fields, &str, end)
@ -587,6 +592,7 @@ err:
TRUE on error TRUE on error
*/ */
static
my_bool str_to_datetime_or_date_or_time_body(const char *str, size_t length, my_bool str_to_datetime_or_date_or_time_body(const char *str, size_t length,
MYSQL_TIME *l_time, MYSQL_TIME *l_time,
ulonglong fuzzydate, ulonglong fuzzydate,
@ -599,9 +605,7 @@ my_bool str_to_datetime_or_date_or_time_body(const char *str, size_t length,
if (is_datetime_body_candidate(str, length)) if (is_datetime_body_candidate(str, length))
{ /* Probably full timestamp */ { /* Probably full timestamp */
(void) str_to_datetime_or_date_body(str, length, l_time, (void) str_to_datetime_or_date_body(str, length, l_time,
(fuzzydate & ~C_TIME_TIME_ONLY) | fuzzydate, FALSE, status);
C_TIME_DATETIME_ONLY,
status);
if (l_time->time_type >= MYSQL_TIMESTAMP_ERROR) if (l_time->time_type >= MYSQL_TIMESTAMP_ERROR)
return l_time->time_type == MYSQL_TIMESTAMP_ERROR; return l_time->time_type == MYSQL_TIMESTAMP_ERROR;
my_time_status_init(status); my_time_status_init(status);
@ -616,6 +620,12 @@ my_bool str_to_datetime_or_date_or_time_body(const char *str, size_t length,
} }
/*
Convert a string with INTERVAL DAY TO SECOND to MYSQL_TIME.
Input format: [-][DD ]hh:mm:ss.ffffff
If the input string appears to be a DATETIME, error is returned.
*/
my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *ltime, my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *ltime,
ulong max_hour, MYSQL_TIME_STATUS *status) ulong max_hour, MYSQL_TIME_STATUS *status)
{ {
@ -634,7 +644,7 @@ my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *ltime,
if (is_datetime_body_candidate(str, length)) if (is_datetime_body_candidate(str, length))
{ {
(void) str_to_datetime_or_date_body(str, length, ltime, (void) str_to_datetime_or_date_body(str, length, ltime,
C_TIME_DATETIME_ONLY, status); 0, FALSE, status);
if (ltime->time_type > MYSQL_TIMESTAMP_ERROR) if (ltime->time_type > MYSQL_TIMESTAMP_ERROR)
{ {
status->warnings|= MYSQL_TIME_WARN_TRUNCATED; status->warnings|= MYSQL_TIME_WARN_TRUNCATED;
@ -650,7 +660,7 @@ my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *ltime,
will scan only '2001'. will scan only '2001'.
*/ */
if (str_to_DDhhmmssff_internal(neg, str, length, ltime, max_hour, if (str_to_DDhhmmssff_internal(neg, str, length, ltime, max_hour,
status, &endptr) || status, &endptr) ||
(endptr < str + length && endptr[0] == '-')) (endptr < str + length && endptr[0] == '-'))
return TRUE; return TRUE;
status->warnings|= warn; status->warnings|= warn;
@ -658,10 +668,13 @@ my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *ltime,
} }
my_bool str_to_time(const char *str, size_t length, MYSQL_TIME *l_time, my_bool
ulonglong fuzzydate, MYSQL_TIME_STATUS *status) str_to_datetime_or_date_or_time(const char *str, size_t length,
MYSQL_TIME *l_time,
ulonglong fuzzydate,
MYSQL_TIME_STATUS *status)
{ {
my_bool neg; my_bool neg, rc;
int warn; int warn;
DBUG_ASSERT(C_FLAGS_OK(fuzzydate)); DBUG_ASSERT(C_FLAGS_OK(fuzzydate));
my_time_status_init(status); my_time_status_init(status);
@ -674,31 +687,8 @@ my_bool str_to_time(const char *str, size_t length, MYSQL_TIME *l_time,
QQ: Perhaps we should modify xxx_body() to return endptr. QQ: Perhaps we should modify xxx_body() to return endptr.
If endptr points to '-', return an error. If endptr points to '-', return an error.
*/ */
if (str_to_datetime_or_date_or_time_body(str, length, l_time, rc= str_to_datetime_or_date_or_time_body(str, length, l_time,
fuzzydate, status)) fuzzydate, status);
return TRUE;
status->warnings|= warn;
l_time->neg= neg;
return FALSE;
}
my_bool
str_to_datetime(const char *str, size_t length, MYSQL_TIME *l_time,
ulonglong flags, MYSQL_TIME_STATUS *status)
{
my_bool neg, rc;
int warn;
DBUG_ASSERT(C_FLAGS_OK(flags));
my_time_status_init(status);
if (find_body(&neg, str, length, l_time, &warn, &str, &length))
{
status->warnings= warn;
return TRUE;
}
rc= (flags & C_TIME_TIME_ONLY) ?
str_to_datetime_or_date_or_time_body(str, length, l_time, flags, status) :
str_to_datetime_or_date_body(str, length, l_time, flags, status);
status->warnings|= warn; status->warnings|= warn;
if (rc) if (rc)
return rc; return rc;
@ -711,6 +701,53 @@ str_to_datetime(const char *str, size_t length, MYSQL_TIME *l_time,
} }
my_bool
str_to_datetime_or_date(const char *str, size_t length, MYSQL_TIME *l_time,
ulonglong flags, MYSQL_TIME_STATUS *status)
{
my_bool neg, rc;
int warn;
DBUG_ASSERT(C_FLAGS_OK(flags));
my_time_status_init(status);
if (find_body(&neg, str, length, l_time, &warn, &str, &length))
{
status->warnings= warn;
return TRUE;
}
rc= str_to_datetime_or_date_body(str, length, l_time, flags, TRUE, status);
status->warnings|= warn;
if (rc)
return rc;
if ((l_time->neg= neg))
{
status->warnings|= MYSQL_TIME_WARN_OUT_OF_RANGE;
return TRUE;
}
return FALSE;
}
/**
Convert a string to INTERVAL DAY TO SECOND.
Input format: [DD ]hh:mm:ss.ffffff
Datetime or date formats are not understood.
Optional leading spaces and signs must be scanned by the caller.
"str" should point to the first digit.
@param neg - set the value to be negative
@param str - the input string
@param length - length of "str"
@param[OUT] l_time - write the result here
@param max_hour - if the result hour value appears to be greater than
max_hour, then cut to result to 'max_hour:59:59.999999'
@param err_hour - if the hour appears to be greater than err_hour,
return an error (without cut)
@param status
@param endptr
*/
static my_bool static my_bool
str_to_DDhhmmssff_internal(my_bool neg, const char *str, size_t length, str_to_DDhhmmssff_internal(my_bool neg, const char *str, size_t length,
MYSQL_TIME *l_time, ulong max_hour, MYSQL_TIME *l_time, ulong max_hour,
@ -1428,7 +1465,7 @@ int my_timeval_to_str(const struct timeval *tm, char *to, uint dec)
representation and form value of DATETIME type as side-effect. representation and form value of DATETIME type as side-effect.
SYNOPSIS SYNOPSIS
number_to_datetime() number_to_datetime_or_date()
nr - datetime value as number nr - datetime value as number
time_res - pointer for structure for broken-down representation time_res - pointer for structure for broken-down representation
flags - flags to use in validating date, as in str_to_datetime() flags - flags to use in validating date, as in str_to_datetime()
@ -1449,8 +1486,9 @@ int my_timeval_to_str(const struct timeval *tm, char *to, uint dec)
Datetime value in YYYYMMDDHHMMSS format. Datetime value in YYYYMMDDHHMMSS format.
*/ */
longlong number_to_datetime(longlong nr, ulong sec_part, MYSQL_TIME *time_res, longlong number_to_datetime_or_date(longlong nr, ulong sec_part,
ulonglong flags, int *was_cut) MYSQL_TIME *time_res,
ulonglong flags, int *was_cut)
{ {
long part1,part2; long part1,part2;
DBUG_ASSERT(C_FLAGS_OK(flags)); DBUG_ASSERT(C_FLAGS_OK(flags));
@ -1554,13 +1592,9 @@ longlong number_to_datetime(longlong nr, ulong sec_part, MYSQL_TIME *time_res,
0 time value is valid, but was possibly truncated 0 time value is valid, but was possibly truncated
-1 time value is invalid -1 time value is invalid
*/ */
int number_to_time(my_bool neg, ulonglong nr, ulong sec_part, int number_to_time_only(my_bool neg, ulonglong nr, ulong sec_part,
MYSQL_TIME *ltime, int *was_cut) MYSQL_TIME *ltime, int *was_cut)
{ {
if (nr > 9999999 && nr <= 99991231235959ULL && neg == 0)
return number_to_datetime(nr, sec_part, ltime,
C_TIME_INVALID_DATES, was_cut) < 0 ? -1 : 0;
*was_cut= 0; *was_cut= 0;
ltime->year= ltime->month= ltime->day= 0; ltime->year= ltime->month= ltime->day= 0;
ltime->time_type= MYSQL_TIMESTAMP_TIME; ltime->time_type= MYSQL_TIMESTAMP_TIME;

View File

@ -33,8 +33,12 @@ class date_mode_t
public: public:
enum value_t enum value_t
{ {
FUZZY_DATES= 1U, // C_TIME_FUZZY_DATES /*
TIME_ONLY= 4U, // C_TIME_TIME_ONLY FUZZY_DATES is used for the result will only be used for comparison
purposes. Conversion is as relaxed as possible.
*/
FUZZY_DATES= 1U,
TIME_ONLY= 4U,
NO_ZERO_IN_DATE= (1UL << 23), // MODE_NO_ZERO_IN_DATE NO_ZERO_IN_DATE= (1UL << 23), // MODE_NO_ZERO_IN_DATE
NO_ZERO_DATE= (1UL << 24), // MODE_NO_ZERO_DATE NO_ZERO_DATE= (1UL << 24), // MODE_NO_ZERO_DATE
INVALID_DATES= (1UL << 25) // MODE_INVALID_DATES INVALID_DATES= (1UL << 25) // MODE_INVALID_DATES
@ -98,11 +102,10 @@ 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 // Flags understood by str_to_xxx, number_to_xxx, check_date
static const date_mode_t static const date_mode_t
TIME_MODE_FOR_XXX_TO_DATE (date_mode_t::NO_ZERO_IN_DATE | TIME_MODE_FOR_XXX_TO_DATE (date_mode_t::NO_ZERO_IN_DATE |
date_mode_t::NO_ZERO_DATE | date_mode_t::NO_ZERO_DATE |
date_mode_t::INVALID_DATES | date_mode_t::INVALID_DATES);
date_mode_t::TIME_ONLY);
#endif #endif

View File

@ -4955,9 +4955,6 @@ my_eof(THD *thd)
inline date_mode_t sql_mode_for_dates(THD *thd) inline date_mode_t sql_mode_for_dates(THD *thd)
{ {
static_assert(C_TIME_FUZZY_DATES == date_mode_t::FUZZY_DATES &&
C_TIME_TIME_ONLY == date_mode_t::TIME_ONLY,
"sql_mode_t and pure C library date flags must be equal");
static_assert(MODE_NO_ZERO_DATE == date_mode_t::NO_ZERO_DATE && static_assert(MODE_NO_ZERO_DATE == date_mode_t::NO_ZERO_DATE &&
MODE_NO_ZERO_IN_DATE == date_mode_t::NO_ZERO_IN_DATE && MODE_NO_ZERO_IN_DATE == date_mode_t::NO_ZERO_IN_DATE &&
MODE_INVALID_DATES == date_mode_t::INVALID_DATES, MODE_INVALID_DATES == date_mode_t::INVALID_DATES,

View File

@ -7685,11 +7685,11 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
sch_table->field[ISE_ON_COMPLETION]-> sch_table->field[ISE_ON_COMPLETION]->
store(STRING_WITH_LEN("PRESERVE"), scs); store(STRING_WITH_LEN("PRESERVE"), scs);
number_to_datetime(et.created, 0, &time, 0, &not_used); number_to_datetime_or_date(et.created, 0, &time, 0, &not_used);
DBUG_ASSERT(not_used==0); DBUG_ASSERT(not_used==0);
sch_table->field[ISE_CREATED]->store_time(&time); sch_table->field[ISE_CREATED]->store_time(&time);
number_to_datetime(et.modified, 0, &time, 0, &not_used); number_to_datetime_or_date(et.modified, 0, &time, 0, &not_used);
DBUG_ASSERT(not_used==0); DBUG_ASSERT(not_used==0);
sch_table->field[ISE_LAST_ALTERED]->store_time(&time); sch_table->field[ISE_LAST_ALTERED]->store_time(&time);

View File

@ -371,13 +371,14 @@ public:
}; };
/* Character set-aware version of str_to_time() */ /* Character set-aware version of str_to_datetime_or_date_or_time() */
bool Temporal::str_to_time(MYSQL_TIME_STATUS *status, bool Temporal::str_to_datetime_or_date_or_time(MYSQL_TIME_STATUS *status,
const char *str, size_t length, CHARSET_INFO *cs, const char *str, size_t length,
date_mode_t fuzzydate) CHARSET_INFO *cs,
date_mode_t fuzzydate)
{ {
TemporalAsciiBuffer tmp(str, length, cs); TemporalAsciiBuffer tmp(str, length, cs);
bool rc= ::str_to_time(tmp.str, tmp.length, this, bool rc= ::str_to_datetime_or_date_or_time(tmp.str, tmp.length, this,
ulonglong(fuzzydate & TIME_MODE_FOR_XXX_TO_DATE), ulonglong(fuzzydate & TIME_MODE_FOR_XXX_TO_DATE),
status); status);
DBUG_ASSERT(status->warnings || !rc); DBUG_ASSERT(status->warnings || !rc);
@ -385,13 +386,14 @@ bool Temporal::str_to_time(MYSQL_TIME_STATUS *status,
} }
/* Character set-aware version of str_to_datetime() */ /* Character set-aware version of str_to_datetime_or_date() */
bool Temporal::str_to_datetime(MYSQL_TIME_STATUS *status, bool Temporal::str_to_datetime_or_date(MYSQL_TIME_STATUS *status,
const char *str, size_t length, CHARSET_INFO *cs, const char *str, size_t length,
date_mode_t flags) CHARSET_INFO *cs,
date_mode_t flags)
{ {
TemporalAsciiBuffer tmp(str, length, cs); TemporalAsciiBuffer tmp(str, length, cs);
bool rc= ::str_to_datetime(tmp.str, tmp.length, this, bool rc= ::str_to_datetime_or_date(tmp.str, tmp.length, this,
ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE),
status); status);
DBUG_ASSERT(status->warnings || !rc); DBUG_ASSERT(status->warnings || !rc);
@ -416,7 +418,7 @@ bool Interval_DDhhmmssff::str_to_DDhhmmssff(MYSQL_TIME_STATUS *status,
if string was truncated during conversion. if string was truncated during conversion.
NOTE NOTE
See description of str_to_datetime() for more information. See description of str_to_datetime_xxx() for more information.
*/ */
bool bool

View File

@ -180,7 +180,10 @@ void Temporal::make_from_str(THD *thd, Warn *warn,
DBUG_EXECUTE_IF("str_to_datetime_warn", DBUG_EXECUTE_IF("str_to_datetime_warn",
push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, push_warning(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_YES, ErrConvString(str, length,cs).ptr());); ER_YES, ErrConvString(str, length,cs).ptr()););
if (str_to_datetime(warn, str, length, cs, fuzzydate))
if (fuzzydate & TIME_TIME_ONLY ?
str_to_datetime_or_date_or_time(warn, str, length, cs, fuzzydate) :
str_to_datetime_or_date(warn, str, length, cs, fuzzydate))
make_fuzzy_date(&warn->warnings, fuzzydate); make_fuzzy_date(&warn->warnings, fuzzydate);
if (warn->warnings) if (warn->warnings)
warn->set_str(str, length, &my_charset_bin); warn->set_str(str, length, &my_charset_bin);

View File

@ -267,7 +267,10 @@ public:
// Convert a number in format hhhmmss.ff to TIME'hhh:mm:ss.ff' // Convert a number in format hhhmmss.ff to TIME'hhh:mm:ss.ff'
bool to_time(MYSQL_TIME *to, int *warn) const bool to_time(MYSQL_TIME *to, int *warn) const
{ {
bool rc= number_to_time(m_neg, m_sec, m_usec, to, warn); bool rc= (m_sec > 9999999 && m_sec <= 99991231235959ULL && !neg()) ?
number_to_datetime_or_date(m_sec, m_usec, to,
C_TIME_INVALID_DATES, warn) < 0 :
number_to_time_only(m_neg, m_sec, m_usec, to, warn);
DBUG_ASSERT(*warn || !rc); DBUG_ASSERT(*warn || !rc);
return rc; return rc;
} }
@ -282,7 +285,7 @@ public:
*warn= MYSQL_TIME_WARN_OUT_OF_RANGE; *warn= MYSQL_TIME_WARN_OUT_OF_RANGE;
return true; return true;
} }
bool rc= number_to_datetime(m_sec, m_usec, to, bool rc= number_to_datetime_or_date(m_sec, m_usec, to,
ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE),
warn) == -1; warn) == -1;
DBUG_ASSERT(*warn || !rc); DBUG_ASSERT(*warn || !rc);
@ -576,10 +579,13 @@ protected:
if (warn->warnings) if (warn->warnings)
warn->set_decimal(nr); warn->set_decimal(nr);
} }
bool str_to_time(MYSQL_TIME_STATUS *st, const char *str, size_t length, bool str_to_datetime_or_date_or_time(MYSQL_TIME_STATUS *st,
CHARSET_INFO *cs, date_mode_t fuzzydate); const char *str, size_t length,
bool str_to_datetime(MYSQL_TIME_STATUS *st, const char *str, size_t length, CHARSET_INFO *cs, date_mode_t fuzzydate);
CHARSET_INFO *cs, date_mode_t fuzzydate); bool str_to_datetime_or_date(MYSQL_TIME_STATUS *st,
const char *str, size_t length,
CHARSET_INFO *cs, date_mode_t fuzzydate);
bool has_valid_mmssff() const bool has_valid_mmssff() const
{ {
return minute <= TIME_MAX_MINUTE && return minute <= TIME_MAX_MINUTE &&
@ -990,7 +996,7 @@ private:
/* /*
Convert a valid DATE or DATETIME to TIME. Convert a valid DATE or DATETIME to TIME.
Before this call, "this" must be a valid DATE or DATETIME value, Before this call, "this" must be a valid DATE or DATETIME value,
e.g. returned from Item::get_date(), str_to_time(), number_to_time(). e.g. returned from Item::get_date(), str_to_xxx(), number_to_xxx().
After this call, "this" is a valid TIME value. After this call, "this" is a valid TIME value.
*/ */
void valid_datetime_to_valid_time(THD *thd, int *warn, const Options opt) void valid_datetime_to_valid_time(THD *thd, int *warn, const Options opt)
@ -999,7 +1005,7 @@ private:
time_type == MYSQL_TIMESTAMP_DATETIME); time_type == MYSQL_TIMESTAMP_DATETIME);
/* /*
We're dealing with a DATE or DATETIME returned from We're dealing with a DATE or DATETIME returned from
str_to_time(), number_to_time() or unpack_time(). str_to_xxx(), number_to_xxx() or unpack_time().
Do some asserts to make sure the result hour value Do some asserts to make sure the result hour value
after mixing days to hours does not go out of the valid TIME range. after mixing days to hours does not go out of the valid TIME range.
The maximum hour value after mixing days will be 31*24+23=767, The maximum hour value after mixing days will be 31*24+23=767,
@ -1025,7 +1031,7 @@ private:
/** /**
Convert valid DATE/DATETIME to valid TIME if needed. Convert valid DATE/DATETIME to valid TIME if needed.
This method is called after Item::get_date(), This method is called after Item::get_date(),
str_to_time(), number_to_time(). str_to_xxx(), number_to_xxx().
which can return only valid TIME/DATE/DATETIME values. which can return only valid TIME/DATE/DATETIME values.
Before this call, "this" is: Before this call, "this" is:
- either a valid TIME/DATE/DATETIME value - either a valid TIME/DATE/DATETIME value
@ -1061,14 +1067,14 @@ private:
} }
/* /*
This method is called after number_to_time() and str_to_time(), This method is called after number_to_xxx() and str_to_xxx(),
which can return DATE or DATETIME values. Convert to TIME if needed. which can return DATE or DATETIME values. Convert to TIME if needed.
We trust that xxx_to_time() returns a valid TIME/DATE/DATETIME value, We trust that xxx_to_time() returns a valid TIME/DATE/DATETIME value,
so here we need to do only simple validation. so here we need to do only simple validation.
*/ */
void xxx_to_time_result_to_valid_value(THD *thd, int *warn, const Options opt) void xxx_to_time_result_to_valid_value(THD *thd, int *warn, const Options opt)
{ {
// str_to_time(), number_to_time() never return MYSQL_TIMESTAMP_ERROR // str_to_xxx(), number_to_xxx() never return MYSQL_TIMESTAMP_ERROR
DBUG_ASSERT(time_type != MYSQL_TIMESTAMP_ERROR); DBUG_ASSERT(time_type != MYSQL_TIMESTAMP_ERROR);
valid_MYSQL_TIME_to_valid_value(thd, warn, opt); valid_MYSQL_TIME_to_valid_value(thd, warn, opt);
} }
@ -1106,7 +1112,8 @@ public:
const char *str, size_t len, CHARSET_INFO *cs, const char *str, size_t len, CHARSET_INFO *cs,
const Options opt) const Options opt)
{ {
if (str_to_time(status, str, len, cs, opt.get_date_flags())) if (str_to_datetime_or_date_or_time(status, str, len, cs,
opt.get_date_flags()))
time_type= MYSQL_TIMESTAMP_NONE; time_type= MYSQL_TIMESTAMP_NONE;
// The below call will optionally add notes to already collected warnings: // The below call will optionally add notes to already collected warnings:
xxx_to_time_result_to_valid_value(thd, &status->warnings, opt); xxx_to_time_result_to_valid_value(thd, &status->warnings, opt);
@ -1306,7 +1313,7 @@ protected:
date_mode_t flags) date_mode_t flags)
{ {
DBUG_ASSERT(bool(flags & TIME_TIME_ONLY) == false); DBUG_ASSERT(bool(flags & TIME_TIME_ONLY) == false);
if (str_to_datetime(status, str, len, cs, flags)) if (str_to_datetime_or_date(status, str, len, cs, flags))
time_type= MYSQL_TIMESTAMP_NONE; time_type= MYSQL_TIMESTAMP_NONE;
} }
public: public:

View File

@ -618,6 +618,15 @@ SPIDER_DB_ROW *spider_db_mysql_result::fetch_row_from_tmp_table(
DBUG_RETURN((SPIDER_DB_ROW *) &row); DBUG_RETURN((SPIDER_DB_ROW *) &row);
} }
static my_bool str_to_datetime(const char *str, size_t length,
MYSQL_TIME *l_time,
ulonglong flags, MYSQL_TIME_STATUS *status)
{
return str_to_datetime_or_date(str, length, l_time, flags, status);
}
int spider_db_mysql_result::fetch_table_status( int spider_db_mysql_result::fetch_table_status(
int mode, int mode,
ha_rows &records, ha_rows &records,