Loading mysql-test/r/date_formats.result +3 −0 Original line number Diff line number Diff line Loading @@ -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-20 %d-%m-%y 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; insert into t1 values ('2003-01-02 10:11:12 PM', '%Y-%m-%d %H:%i:%S %p'), Loading mysql-test/t/date_formats.test +2 −0 Original line number Diff line number Diff line Loading @@ -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,TIME(str_to_date(date, format)) as time 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 Loading sql/item_timefunc.cc +39 −21 Original line number Diff line number Diff line Loading @@ -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. 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 0 ok 1 error Loading Loading @@ -2595,25 +2598,31 @@ void Item_func_get_format::print(String *str) /* check_result_type(s, l) returns DATE/TIME type according to format string s: DATE/TIME format string l: length of s Result: date_time_format_types value: DATE_TIME_MICROSECOND, DATE_TIME, TIME_MICROSECOND, TIME_ONLY We don't process day format's characters('D', 'd', 'e') because day may be a member of all date/time types. If only day format's character and no time part present the result type is MYSQL_TYPE_DATE Get type of datetime value (DATE/TIME/...) which will be produced according to format string. SYNOPSIS get_date_time_result_type() format - format string length - length of format string NOTE We don't process day format's characters('D', 'd', 'e') because day may be a member of all date/time types. 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 *date_part_frms= "MUYWabcjmuyw"; const char *date_part_frms= "MVUXYWabcjmvuxyw"; bool date_part_used= 0, time_part_used= 0, frac_second_used= 0; const char *val= format; Loading @@ -2624,22 +2633,30 @@ date_time_format_types check_result_type(const char *format, uint length) if (*val == '%' && val+1 != end) { val++; if ((frac_second_used= (*val == 'f')) || (!time_part_used && strchr(time_part_frms, *val))) if (*val == 'f') frac_second_used= time_part_used= 1; else if (!time_part_used && strchr(time_part_frms, *val)) time_part_used= 1; else if (!date_part_used && strchr(date_part_frms, *val)) 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; } } } /* We don't have all three types of date-time components */ if (frac_second_used) return TIME_MICROSECOND; if (time_part_used) { if (date_part_used) return DATE_TIME; if (frac_second_used) return TIME_MICROSECOND; return TIME_ONLY; } return DATE_ONLY; Loading Loading @@ -2670,7 +2687,8 @@ void Item_func_str_to_date::fix_length_and_dec() if ((const_item= args[1]->const_item())) { 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) { case DATE_ONLY: cached_timestamp_type= MYSQL_TIMESTAMP_DATE; Loading Loading
mysql-test/r/date_formats.result +3 −0 Original line number Diff line number Diff line Loading @@ -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-20 %d-%m-%y 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; insert into t1 values ('2003-01-02 10:11:12 PM', '%Y-%m-%d %H:%i:%S %p'), Loading
mysql-test/t/date_formats.test +2 −0 Original line number Diff line number Diff line Loading @@ -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,TIME(str_to_date(date, format)) as time 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 Loading
sql/item_timefunc.cc +39 −21 Original line number Diff line number Diff line Loading @@ -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. 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 0 ok 1 error Loading Loading @@ -2595,25 +2598,31 @@ void Item_func_get_format::print(String *str) /* check_result_type(s, l) returns DATE/TIME type according to format string s: DATE/TIME format string l: length of s Result: date_time_format_types value: DATE_TIME_MICROSECOND, DATE_TIME, TIME_MICROSECOND, TIME_ONLY We don't process day format's characters('D', 'd', 'e') because day may be a member of all date/time types. If only day format's character and no time part present the result type is MYSQL_TYPE_DATE Get type of datetime value (DATE/TIME/...) which will be produced according to format string. SYNOPSIS get_date_time_result_type() format - format string length - length of format string NOTE We don't process day format's characters('D', 'd', 'e') because day may be a member of all date/time types. 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 *date_part_frms= "MUYWabcjmuyw"; const char *date_part_frms= "MVUXYWabcjmvuxyw"; bool date_part_used= 0, time_part_used= 0, frac_second_used= 0; const char *val= format; Loading @@ -2624,22 +2633,30 @@ date_time_format_types check_result_type(const char *format, uint length) if (*val == '%' && val+1 != end) { val++; if ((frac_second_used= (*val == 'f')) || (!time_part_used && strchr(time_part_frms, *val))) if (*val == 'f') frac_second_used= time_part_used= 1; else if (!time_part_used && strchr(time_part_frms, *val)) time_part_used= 1; else if (!date_part_used && strchr(date_part_frms, *val)) 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; } } } /* We don't have all three types of date-time components */ if (frac_second_used) return TIME_MICROSECOND; if (time_part_used) { if (date_part_used) return DATE_TIME; if (frac_second_used) return TIME_MICROSECOND; return TIME_ONLY; } return DATE_ONLY; Loading Loading @@ -2670,7 +2687,8 @@ void Item_func_str_to_date::fix_length_and_dec() if ((const_item= args[1]->const_item())) { 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) { case DATE_ONLY: cached_timestamp_type= MYSQL_TIMESTAMP_DATE; Loading