Fix for bug #7458 "Microseconds are gobbled from the string result of
STR_TO_DATE() function if there is another format specifier after %f in format string". Also small cleanup of STR_TO_DATE() implementation. (After review version.)
This commit is contained in:
parent
2d1458ea5b
commit
7b9fd879f6
@ -296,6 +296,9 @@ Tuesday 52 2001 %W %V %X 00:00:00
|
|||||||
15-01-2001 %d-%m-%Y %H:%i:%S 00:00:00
|
15-01-2001 %d-%m-%Y %H:%i:%S 00:00:00
|
||||||
15-01-20 %d-%m-%y 00:00:00
|
15-01-20 %d-%m-%y 00:00:00
|
||||||
15-2001-1 %d-%Y-%c 00:00:00
|
15-2001-1 %d-%Y-%c 00:00:00
|
||||||
|
select concat('',str_to_date('8:11:2.123456 03-01-02','%H:%i:%S.%f %y-%m-%d'));
|
||||||
|
concat('',str_to_date('8:11:2.123456 03-01-02','%H:%i:%S.%f %y-%m-%d'))
|
||||||
|
2003-01-02 08:11:02.123456
|
||||||
truncate table t1;
|
truncate table t1;
|
||||||
insert into t1 values
|
insert into t1 values
|
||||||
('2003-01-02 10:11:12 PM', '%Y-%m-%d %H:%i:%S %p'),
|
('2003-01-02 10:11:12 PM', '%Y-%m-%d %H:%i:%S %p'),
|
||||||
|
@ -166,6 +166,8 @@ select date,format,cast(str_to_date(date, format) as datetime) as datetime from
|
|||||||
select date,format,DATE(str_to_date(date, format)) as date2 from t1;
|
select date,format,DATE(str_to_date(date, format)) as date2 from t1;
|
||||||
select date,format,TIME(str_to_date(date, format)) as time from t1;
|
select date,format,TIME(str_to_date(date, format)) as time from t1;
|
||||||
select date,format,concat(TIME(str_to_date(date, format))) as time2 from t1;
|
select date,format,concat(TIME(str_to_date(date, format))) as time2 from t1;
|
||||||
|
# Test small bug in %f handling
|
||||||
|
select concat('',str_to_date('8:11:2.123456 03-01-02','%H:%i:%S.%f %y-%m-%d'));
|
||||||
|
|
||||||
# Test wrong dates or converion specifiers
|
# Test wrong dates or converion specifiers
|
||||||
|
|
||||||
|
@ -149,6 +149,9 @@ static DATE_TIME_FORMAT time_24hrs_format= {{0}, '\0', 0,
|
|||||||
conversion specifiers that can be used in such sub-patterns is limited.
|
conversion specifiers that can be used in such sub-patterns is limited.
|
||||||
Also most of checks are skipped in this case.
|
Also most of checks are skipped in this case.
|
||||||
|
|
||||||
|
If one adds new format specifiers to this function he should also
|
||||||
|
consider adding them to get_date_time_result_type() function.
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
0 ok
|
0 ok
|
||||||
1 error
|
1 error
|
||||||
@ -2595,25 +2598,31 @@ void Item_func_get_format::print(String *str)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
check_result_type(s, l) returns DATE/TIME type
|
Get type of datetime value (DATE/TIME/...) which will be produced
|
||||||
according to format string
|
according to format string.
|
||||||
|
|
||||||
s: DATE/TIME format string
|
SYNOPSIS
|
||||||
l: length of s
|
get_date_time_result_type()
|
||||||
Result: date_time_format_types value:
|
format - format string
|
||||||
DATE_TIME_MICROSECOND, DATE_TIME,
|
length - length of format string
|
||||||
TIME_MICROSECOND, TIME_ONLY
|
|
||||||
|
|
||||||
We don't process day format's characters('D', 'd', 'e')
|
NOTE
|
||||||
because day may be a member of all date/time types.
|
We don't process day format's characters('D', 'd', 'e') because day
|
||||||
If only day format's character and no time part present
|
may be a member of all date/time types.
|
||||||
the result type is MYSQL_TYPE_DATE
|
|
||||||
|
Format specifiers supported by this function should be in sync with
|
||||||
|
specifiers supported by extract_date_time() function.
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
One of date_time_format_types values:
|
||||||
|
DATE_TIME_MICROSECOND, DATE_TIME, DATE_ONLY, TIME_MICROSECOND, TIME_ONLY
|
||||||
*/
|
*/
|
||||||
|
|
||||||
date_time_format_types check_result_type(const char *format, uint length)
|
static date_time_format_types
|
||||||
|
get_date_time_result_type(const char *format, uint length)
|
||||||
{
|
{
|
||||||
const char *time_part_frms= "HISThiklrs";
|
const char *time_part_frms= "HISThiklrs";
|
||||||
const char *date_part_frms= "MUYWabcjmuyw";
|
const char *date_part_frms= "MVUXYWabcjmvuxyw";
|
||||||
bool date_part_used= 0, time_part_used= 0, frac_second_used= 0;
|
bool date_part_used= 0, time_part_used= 0, frac_second_used= 0;
|
||||||
|
|
||||||
const char *val= format;
|
const char *val= format;
|
||||||
@ -2624,22 +2633,30 @@ date_time_format_types check_result_type(const char *format, uint length)
|
|||||||
if (*val == '%' && val+1 != end)
|
if (*val == '%' && val+1 != end)
|
||||||
{
|
{
|
||||||
val++;
|
val++;
|
||||||
if ((frac_second_used= (*val == 'f')) ||
|
if (*val == 'f')
|
||||||
(!time_part_used && strchr(time_part_frms, *val)))
|
frac_second_used= time_part_used= 1;
|
||||||
|
else if (!time_part_used && strchr(time_part_frms, *val))
|
||||||
time_part_used= 1;
|
time_part_used= 1;
|
||||||
else if (!date_part_used && strchr(date_part_frms, *val))
|
else if (!date_part_used && strchr(date_part_frms, *val))
|
||||||
date_part_used= 1;
|
date_part_used= 1;
|
||||||
if (time_part_used && date_part_used && frac_second_used)
|
if (date_part_used && frac_second_used)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
frac_second_used implies time_part_used, and thus we already
|
||||||
|
have all types of date-time components and can end our search.
|
||||||
|
*/
|
||||||
return DATE_TIME_MICROSECOND;
|
return DATE_TIME_MICROSECOND;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We don't have all three types of date-time components */
|
||||||
|
if (frac_second_used)
|
||||||
|
return TIME_MICROSECOND;
|
||||||
if (time_part_used)
|
if (time_part_used)
|
||||||
{
|
{
|
||||||
if (date_part_used)
|
if (date_part_used)
|
||||||
return DATE_TIME;
|
return DATE_TIME;
|
||||||
if (frac_second_used)
|
|
||||||
return TIME_MICROSECOND;
|
|
||||||
return TIME_ONLY;
|
return TIME_ONLY;
|
||||||
}
|
}
|
||||||
return DATE_ONLY;
|
return DATE_ONLY;
|
||||||
@ -2670,7 +2687,8 @@ void Item_func_str_to_date::fix_length_and_dec()
|
|||||||
if ((const_item= args[1]->const_item()))
|
if ((const_item= args[1]->const_item()))
|
||||||
{
|
{
|
||||||
format= args[1]->val_str(&format_str);
|
format= args[1]->val_str(&format_str);
|
||||||
cached_format_type= check_result_type(format->ptr(), format->length());
|
cached_format_type= get_date_time_result_type(format->ptr(),
|
||||||
|
format->length());
|
||||||
switch (cached_format_type) {
|
switch (cached_format_type) {
|
||||||
case DATE_ONLY:
|
case DATE_ONLY:
|
||||||
cached_timestamp_type= MYSQL_TIMESTAMP_DATE;
|
cached_timestamp_type= MYSQL_TIMESTAMP_DATE;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user