Commit c75a277a authored by Alexander Barkov's avatar Alexander Barkov

A cleanup for "MDEV-17477 Wrong result for TIME('-2001-01-01 10:20:30')"

modified:   ../sql-common/my_time.c

Moving the logic that mixes warnings of two kinds:
- those came from truncating garbage before the actual parsing of date/time
- those came during the actual parsing
from outside to inside of str_to_datetime_or_date_body().
This makes the caller code easier and removes some code duplication.
We'll be adding more parsing functions for time intervals soon,
so this change helps to avoid more duplicate code in the coming functions.
parent b9a90557
...@@ -456,6 +456,7 @@ str_to_datetime_or_date_body(const char *str, size_t length, MYSQL_TIME *l_time, ...@@ -456,6 +456,7 @@ str_to_datetime_or_date_body(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;
int warn= 0;
DBUG_ENTER("str_to_datetime_or_date_body"); DBUG_ENTER("str_to_datetime_or_date_body");
DBUG_ASSERT(C_FLAGS_OK(flags)); DBUG_ASSERT(C_FLAGS_OK(flags));
bzero(l_time, sizeof(*l_time)); bzero(l_time, sizeof(*l_time));
...@@ -493,16 +494,16 @@ str_to_datetime_or_date_body(const char *str, size_t length, MYSQL_TIME *l_time, ...@@ -493,16 +494,16 @@ str_to_datetime_or_date_body(const char *str, size_t length, MYSQL_TIME *l_time,
|| get_digits(&l_time->hour, &number_of_fields, &str, end, 2) || get_digits(&l_time->hour, &number_of_fields, &str, end, 2)
|| get_digits(&l_time->minute, &number_of_fields, &str, end, 2) || get_digits(&l_time->minute, &number_of_fields, &str, end, 2)
|| get_digits(&l_time->second, &number_of_fields, &str, end, 2)) || get_digits(&l_time->second, &number_of_fields, &str, end, 2))
status->warnings|= MYSQL_TIME_WARN_TRUNCATED; warn|= MYSQL_TIME_WARN_TRUNCATED;
} }
else else
{ {
const char *start= str; const char *start= str;
if (get_number(&l_time->year, &number_of_fields, &str, end)) if (get_number(&l_time->year, &number_of_fields, &str, end))
status->warnings|= MYSQL_TIME_WARN_TRUNCATED; warn|= MYSQL_TIME_WARN_TRUNCATED;
year_length= (uint)(str - start); year_length= (uint)(str - start);
if (!status->warnings && if (!warn &&
(get_punct(&str, end) (get_punct(&str, end)
|| 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)
...@@ -514,8 +515,9 @@ str_to_datetime_or_date_body(const char *str, size_t length, MYSQL_TIME *l_time, ...@@ -514,8 +515,9 @@ str_to_datetime_or_date_body(const char *str, size_t length, MYSQL_TIME *l_time,
|| get_number(&l_time->minute, &number_of_fields, &str, end) || get_number(&l_time->minute, &number_of_fields, &str, end)
|| get_punct(&str, end) || get_punct(&str, end)
|| get_number(&l_time->second, &number_of_fields, &str, end))) || get_number(&l_time->second, &number_of_fields, &str, end)))
status->warnings|= MYSQL_TIME_WARN_TRUNCATED; warn|= MYSQL_TIME_WARN_TRUNCATED;
} }
status->warnings|= warn;
/* we're ok if date part is correct. even if the rest is truncated */ /* we're ok if date part is correct. even if the rest is truncated */
if (number_of_fields < 3) if (number_of_fields < 3)
...@@ -525,7 +527,7 @@ str_to_datetime_or_date_body(const char *str, size_t length, MYSQL_TIME *l_time, ...@@ -525,7 +527,7 @@ str_to_datetime_or_date_body(const char *str, size_t length, MYSQL_TIME *l_time,
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
if (!status->warnings && str < end && *str == '.') if (!warn && str < end && *str == '.')
{ {
str++; str++;
get_microseconds(&l_time->second_part, status, get_microseconds(&l_time->second_part, status,
...@@ -604,11 +606,12 @@ my_bool str_to_datetime_or_date_or_time_body(const char *str, size_t length, ...@@ -604,11 +606,12 @@ my_bool str_to_datetime_or_date_or_time_body(const char *str, size_t length,
/* Check first if this is a full TIMESTAMP */ /* Check first if this is a full TIMESTAMP */
if (is_datetime_body_candidate(str, length)) if (is_datetime_body_candidate(str, length))
{ /* Probably full timestamp */ { /* Probably full timestamp */
int warn_copy= status->warnings; /* could already be set by find_body() */
(void) str_to_datetime_or_date_body(str, length, l_time, (void) str_to_datetime_or_date_body(str, length, l_time,
fuzzydate, FALSE, status); fuzzydate, FALSE, 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); status->warnings= warn_copy;
} }
if (!str_to_DDhhmmssff_internal(FALSE, str, length, l_time, TIME_MAX_HOUR, if (!str_to_DDhhmmssff_internal(FALSE, str, length, l_time, TIME_MAX_HOUR,
...@@ -631,14 +634,10 @@ my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *ltime, ...@@ -631,14 +634,10 @@ my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *ltime,
{ {
my_bool neg; my_bool neg;
const char *endptr; const char *endptr;
int warn;
my_time_status_init(status); my_time_status_init(status);
if (find_body(&neg, str, length, ltime, &warn, &str, &length)) if (find_body(&neg, str, length, ltime, &status->warnings, &str, &length))
{
status->warnings= warn;
return TRUE; return TRUE;
}
/* Reject anything that might be parsed as a full TIMESTAMP */ /* Reject anything that might be parsed as a full TIMESTAMP */
if (is_datetime_body_candidate(str, length)) if (is_datetime_body_candidate(str, length))
...@@ -663,7 +662,6 @@ my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *ltime, ...@@ -663,7 +662,6 @@ my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *ltime,
status, &endptr) || status, &endptr) ||
(endptr < str + length && endptr[0] == '-')) (endptr < str + length && endptr[0] == '-'))
return TRUE; return TRUE;
status->warnings|= warn;
return FALSE; return FALSE;
} }
...@@ -675,21 +673,16 @@ str_to_datetime_or_date_or_time(const char *str, size_t length, ...@@ -675,21 +673,16 @@ str_to_datetime_or_date_or_time(const char *str, size_t length,
MYSQL_TIME_STATUS *status) MYSQL_TIME_STATUS *status)
{ {
my_bool neg, rc; my_bool neg, rc;
int warn;
DBUG_ASSERT(C_FLAGS_OK(fuzzydate)); DBUG_ASSERT(C_FLAGS_OK(fuzzydate));
my_time_status_init(status); my_time_status_init(status);
if (find_body(&neg, str, length, l_time, &warn, &str, &length)) if (find_body(&neg, str, length, l_time, &status->warnings, &str, &length))
{
status->warnings= warn;
return TRUE; return TRUE;
}
/* /*
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.
*/ */
rc= 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);
status->warnings|= warn;
if (rc) if (rc)
return rc; return rc;
if ((l_time->neg= neg) && l_time->time_type != MYSQL_TIMESTAMP_TIME) if ((l_time->neg= neg) && l_time->time_type != MYSQL_TIMESTAMP_TIME)
...@@ -706,16 +699,11 @@ str_to_datetime_or_date(const char *str, size_t length, MYSQL_TIME *l_time, ...@@ -706,16 +699,11 @@ str_to_datetime_or_date(const char *str, size_t length, MYSQL_TIME *l_time,
ulonglong flags, MYSQL_TIME_STATUS *status) ulonglong flags, MYSQL_TIME_STATUS *status)
{ {
my_bool neg, rc; my_bool neg, rc;
int warn;
DBUG_ASSERT(C_FLAGS_OK(flags)); DBUG_ASSERT(C_FLAGS_OK(flags));
my_time_status_init(status); my_time_status_init(status);
if (find_body(&neg, str, length, l_time, &warn, &str, &length)) if (find_body(&neg, str, length, l_time, &status->warnings, &str, &length))
{
status->warnings= warn;
return TRUE; return TRUE;
}
rc= str_to_datetime_or_date_body(str, length, l_time, flags, TRUE, status); rc= str_to_datetime_or_date_body(str, length, l_time, flags, TRUE, status);
status->warnings|= warn;
if (rc) if (rc)
return rc; return rc;
if ((l_time->neg= neg)) if ((l_time->neg= neg))
...@@ -838,7 +826,7 @@ str_to_DDhhmmssff_internal(my_bool neg, const char *str, size_t length, ...@@ -838,7 +826,7 @@ str_to_DDhhmmssff_internal(my_bool neg, const char *str, size_t length,
fractional: fractional:
/* Get fractional second part */ /* Get fractional second part */
if (!status->warnings && str < end && *str == '.') if (str < end && *str == '.')
{ {
uint number_of_fields= 0; uint number_of_fields= 0;
str++; str++;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment