Loading include/my_time.h +13 −1 Original line number Diff line number Diff line Loading @@ -49,6 +49,16 @@ typedef long my_time_t; #define TIME_NO_ZERO_DATE (TIME_NO_ZERO_IN_DATE*2) #define TIME_INVALID_DATES (TIME_NO_ZERO_DATE*2) #define MYSQL_TIME_WARN_TRUNCATED 1 #define MYSQL_TIME_WARN_OUT_OF_RANGE 2 /* Limits for the TIME data type */ #define TIME_MAX_HOUR 838 #define TIME_MAX_MINUTE 59 #define TIME_MAX_SECOND 59 #define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + \ TIME_MAX_SECOND) enum enum_mysql_timestamp_type str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, uint flags, int *was_cut); Loading @@ -61,7 +71,9 @@ ulonglong TIME_to_ulonglong(const MYSQL_TIME *time); my_bool str_to_time(const char *str,uint length, MYSQL_TIME *l_time, int *was_cut); int *warning); int check_time_range(struct st_mysql_time *time, int *warning); long calc_daynr(uint year,uint month,uint day); uint calc_days_in_year(uint year); Loading mysql-test/r/func_sapdb.result +11 −4 Original line number Diff line number Diff line Loading @@ -107,7 +107,9 @@ subtime("02:01:01.999999", "01:01:01.999999") 01:00:00.000000 select timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002"); timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002") 8807:59:59.999999 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '8807:59:59.999999' select timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002"); timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002") 46:58:57.999999 Loading Loading @@ -219,13 +221,16 @@ SELECT TIMEDIFF(t1, t4) As ttt, TIMEDIFF(t2, t3) As qqq, TIMEDIFF(t3, t2) As eee, TIMEDIFF(t2, t4) As rrr from test; ttt qqq eee rrr -744:00:00 NULL NULL NULL 26305:01:02 22:58:58 -22:58:58 NULL -26305:01:02 -22:58:58 22:58:58 NULL 838:59:59 22:58:58 -22:58:58 NULL -838:59:59 -22:58:58 22:58:58 NULL NULL 26:02:02 -26:02:02 NULL 00:00:00 -26:02:02 26:02:02 NULL NULL NULL NULL NULL NULL NULL NULL NULL 00:00:00 -24:00:00 24:00:00 NULL Warnings: Warning 1292 Truncated incorrect time value: '26305:01:02' Warning 1292 Truncated incorrect time value: '-26305:01:02' drop table t1, test; select addtime("-01:01:01.01", "-23:59:59.1") as a; a Loading @@ -235,7 +240,9 @@ a 10000 select microsecond(19971231235959.01) as a; a 10000 0 Warnings: Warning 1292 Truncated incorrect time value: '19971231235959.01' select date_add("1997-12-31",INTERVAL "10.09" SECOND_MICROSECOND) as a; a 1997-12-31 00:00:10.090000 Loading mysql-test/r/func_time.result +90 −1 Original line number Diff line number Diff line Loading @@ -339,7 +339,9 @@ extract(DAY_MINUTE FROM "02 10:11:12") 21011 select extract(DAY_SECOND FROM "225 10:11:12"); extract(DAY_SECOND FROM "225 10:11:12") 225101112 8385959 Warnings: Warning 1292 Truncated incorrect time value: '225 10:11:12' select extract(HOUR FROM "1999-01-02 10:11:12"); extract(HOUR FROM "1999-01-02 10:11:12") 10 Loading Loading @@ -890,6 +892,93 @@ t1 CREATE TABLE `t1` ( `from_unixtime(1) + 0` double(23,6) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; SELECT SEC_TO_TIME(3300000); SEC_TO_TIME(3300000) 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '3300000' SELECT SEC_TO_TIME(3300000)+0; SEC_TO_TIME(3300000)+0 8385959.000000 Warnings: Warning 1292 Truncated incorrect time value: '3300000' SELECT SEC_TO_TIME(3600 * 4294967296); SEC_TO_TIME(3600 * 4294967296) 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '15461882265600' SELECT TIME_TO_SEC('916:40:00'); TIME_TO_SEC('916:40:00') 3020399 Warnings: Warning 1292 Truncated incorrect time value: '916:40:00' SELECT ADDTIME('500:00:00', '416:40:00'); ADDTIME('500:00:00', '416:40:00') 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '916:40:00' SELECT ADDTIME('916:40:00', '416:40:00'); ADDTIME('916:40:00', '416:40:00') 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '916:40:00' Warning 1292 Truncated incorrect time value: '1255:39:59' SELECT SUBTIME('916:40:00', '416:40:00'); SUBTIME('916:40:00', '416:40:00') 422:19:59 Warnings: Warning 1292 Truncated incorrect time value: '916:40:00' SELECT SUBTIME('-916:40:00', '416:40:00'); SUBTIME('-916:40:00', '416:40:00') -838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '-916:40:00' Warning 1292 Truncated incorrect time value: '-1255:39:59' SELECT MAKETIME(916,0,0); MAKETIME(916,0,0) 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '916:00:00' SELECT MAKETIME(4294967296, 0, 0); MAKETIME(4294967296, 0, 0) 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '4294967296:00:00' SELECT MAKETIME(-4294967296, 0, 0); MAKETIME(-4294967296, 0, 0) -838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '-4294967296:00:00' SELECT MAKETIME(0, 4294967296, 0); MAKETIME(0, 4294967296, 0) NULL SELECT MAKETIME(0, 0, 4294967296); MAKETIME(0, 0, 4294967296) NULL SELECT MAKETIME(CAST(-1 AS UNSIGNED), 0, 0); MAKETIME(CAST(-1 AS UNSIGNED), 0, 0) 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '18446744073709551615:00:00' SELECT EXTRACT(HOUR FROM '100000:02:03'); EXTRACT(HOUR FROM '100000:02:03') 838 Warnings: Warning 1292 Truncated incorrect time value: '100000:02:03' CREATE TABLE t1(f1 TIME); INSERT INTO t1 VALUES('916:00:00 a'); Warnings: Warning 1265 Data truncated for column 'f1' at row 1 Warning 1264 Out of range value adjusted for column 'f1' at row 1 SELECT * FROM t1; f1 838:59:59 DROP TABLE t1; SELECT SEC_TO_TIME(CAST(-1 AS UNSIGNED)); SEC_TO_TIME(CAST(-1 AS UNSIGNED)) 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '18446744073709551615' SET NAMES latin1; SET character_set_results = NULL; SHOW VARIABLES LIKE 'character_set_results'; Loading mysql-test/t/func_time.test +43 −0 Original line number Diff line number Diff line Loading @@ -446,6 +446,49 @@ create table t1 select now() - now(), curtime() - curtime(), show create table t1; drop table t1; # # Bug #11655: Wrong time is returning from nested selects - maximum time exists # # check if SEC_TO_TIME() handles out-of-range values correctly SELECT SEC_TO_TIME(3300000); SELECT SEC_TO_TIME(3300000)+0; SELECT SEC_TO_TIME(3600 * 4294967296); # check if TIME_TO_SEC() handles out-of-range values correctly SELECT TIME_TO_SEC('916:40:00'); # check if ADDTIME() handles out-of-range values correctly SELECT ADDTIME('500:00:00', '416:40:00'); SELECT ADDTIME('916:40:00', '416:40:00'); # check if SUBTIME() handles out-of-range values correctly SELECT SUBTIME('916:40:00', '416:40:00'); SELECT SUBTIME('-916:40:00', '416:40:00'); # check if MAKETIME() handles out-of-range values correctly SELECT MAKETIME(916,0,0); SELECT MAKETIME(4294967296, 0, 0); SELECT MAKETIME(-4294967296, 0, 0); SELECT MAKETIME(0, 4294967296, 0); SELECT MAKETIME(0, 0, 4294967296); SELECT MAKETIME(CAST(-1 AS UNSIGNED), 0, 0); # check if EXTRACT() handles out-of-range values correctly SELECT EXTRACT(HOUR FROM '100000:02:03'); # check if we get proper warnings if both input string truncation # and out-of-range value occur CREATE TABLE t1(f1 TIME); INSERT INTO t1 VALUES('916:00:00 a'); SELECT * FROM t1; DROP TABLE t1; # # Bug #20927: sec_to_time treats big unsigned as signed # # check if SEC_TO_TIME() handles BIGINT UNSIGNED values correctly SELECT SEC_TO_TIME(CAST(-1 AS UNSIGNED)); # # 21913: DATE_FORMAT() Crashes mysql server if I use it through # mysql-connector-j driver. Loading sql-common/my_time.c +69 −21 Original line number Diff line number Diff line Loading @@ -465,8 +465,10 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, There may be an optional [.second_part] after seconds length Length of str l_time Store result here was_cut Set to 1 if value was cut during conversion or to 0 otherwise. warning Set MYSQL_TIME_WARN_TRUNCATED flag if the input string was cut during conversion, and/or MYSQL_TIME_WARN_OUT_OF_RANGE flag, if the value is out of range. NOTES Because of the extra days argument, this function can only Loading @@ -478,15 +480,16 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, */ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, int *was_cut) int *warning) { long date[5],value; ulong date[5]; ulonglong value; const char *end=str+length, *end_of_days; my_bool found_days,found_hours; uint state; l_time->neg=0; *was_cut= 0; *warning= 0; for (; str != end && my_isspace(&my_charset_latin1,*str) ; str++) length--; if (str != end && *str == '-') Loading @@ -501,13 +504,16 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, /* Check first if this is a full TIMESTAMP */ if (length >= 12) { /* Probably full timestamp */ int was_cut; enum enum_mysql_timestamp_type res= str_to_datetime(str, length, l_time, (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), was_cut); (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), &was_cut); if ((int) res >= (int) MYSQL_TIMESTAMP_ERROR) { if (was_cut) *warning|= MYSQL_TIME_WARN_TRUNCATED; return res == MYSQL_TIMESTAMP_ERROR; /* We need to restore was_cut flag since str_to_datetime can modify it */ *was_cut= 0; } } /* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */ Loading Loading @@ -587,7 +593,7 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, if (field_length > 0) value*= (long) log_10_int[field_length]; else if (field_length < 0) *was_cut= 1; *warning|= MYSQL_TIME_WARN_TRUNCATED; date[4]=value; } else Loading @@ -601,10 +607,7 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, ((str[1] == '-' || str[1] == '+') && (end - str) > 2 && my_isdigit(&my_charset_latin1, str[2])))) { *was_cut= 1; return 1; } if (internal_format_positions[7] != 255) { Loading @@ -623,12 +626,12 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, } } /* Some simple checks */ if (date[2] >= 60 || date[3] >= 60) { *was_cut= 1; /* Integer overflow checks */ if (date[0] > UINT_MAX || date[1] > UINT_MAX || date[2] > UINT_MAX || date[3] > UINT_MAX || date[4] > UINT_MAX) return 1; } l_time->year= 0; /* For protocol::store_time */ l_time->month= 0; l_time->day= date[0]; Loading @@ -638,6 +641,10 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, l_time->second_part= date[4]; l_time->time_type= MYSQL_TIMESTAMP_TIME; /* Check if the value is valid and fits into TIME range */ if (check_time_range(l_time, warning)) return 1; /* Check if there is garbage at end of the TIME specification */ if (str != end) { Loading @@ -645,7 +652,7 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, { if (!my_isspace(&my_charset_latin1,*str)) { *was_cut= 1; *warning|= MYSQL_TIME_WARN_TRUNCATED; break; } } while (++str != end); Loading @@ -654,6 +661,47 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, } /* Check 'time' value to lie in the TIME range SYNOPSIS: check_time_range() time pointer to TIME value warning set MYSQL_TIME_WARN_OUT_OF_RANGE flag if the value is out of range DESCRIPTION If the time value lies outside of the range [-838:59:59, 838:59:59], set it to the closest endpoint of the range and set MYSQL_TIME_WARN_OUT_OF_RANGE flag in the 'warning' variable. RETURN 0 time value is valid, but was possibly truncated 1 time value is invalid */ int check_time_range(struct st_mysql_time *time, int *warning) { longlong hour; if (time->minute >= 60 || time->second >= 60) return 1; hour= time->hour + (24*time->day); if (hour <= TIME_MAX_HOUR && (hour != TIME_MAX_HOUR || time->minute != TIME_MAX_MINUTE || time->second != TIME_MAX_SECOND || !time->second_part)) return 0; time->day= 0; time->hour= TIME_MAX_HOUR; time->minute= TIME_MAX_MINUTE; time->second= TIME_MAX_SECOND; time->second_part= 0; *warning|= MYSQL_TIME_WARN_OUT_OF_RANGE; return 0; } /* Prepare offset of system time zone from UTC for my_system_gmt_sec() func. Loading Loading @@ -840,7 +888,7 @@ void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type) int my_time_to_str(const MYSQL_TIME *l_time, char *to) { uint extra_hours= 0; return my_sprintf(to, (to, "%s%02d:%02d:%02d", return my_sprintf(to, (to, "%s%02u:%02u:%02u", (l_time->neg ? "-" : ""), extra_hours+ l_time->hour, l_time->minute, Loading @@ -849,7 +897,7 @@ int my_time_to_str(const MYSQL_TIME *l_time, char *to) int my_date_to_str(const MYSQL_TIME *l_time, char *to) { return my_sprintf(to, (to, "%04d-%02d-%02d", return my_sprintf(to, (to, "%04u-%02u-%02u", l_time->year, l_time->month, l_time->day)); Loading @@ -857,7 +905,7 @@ int my_date_to_str(const MYSQL_TIME *l_time, char *to) int my_datetime_to_str(const MYSQL_TIME *l_time, char *to) { return my_sprintf(to, (to, "%04d-%02d-%02d %02d:%02d:%02d", return my_sprintf(to, (to, "%04u-%02u-%02u %02u:%02u:%02u", l_time->year, l_time->month, l_time->day, Loading Loading
include/my_time.h +13 −1 Original line number Diff line number Diff line Loading @@ -49,6 +49,16 @@ typedef long my_time_t; #define TIME_NO_ZERO_DATE (TIME_NO_ZERO_IN_DATE*2) #define TIME_INVALID_DATES (TIME_NO_ZERO_DATE*2) #define MYSQL_TIME_WARN_TRUNCATED 1 #define MYSQL_TIME_WARN_OUT_OF_RANGE 2 /* Limits for the TIME data type */ #define TIME_MAX_HOUR 838 #define TIME_MAX_MINUTE 59 #define TIME_MAX_SECOND 59 #define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + \ TIME_MAX_SECOND) enum enum_mysql_timestamp_type str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, uint flags, int *was_cut); Loading @@ -61,7 +71,9 @@ ulonglong TIME_to_ulonglong(const MYSQL_TIME *time); my_bool str_to_time(const char *str,uint length, MYSQL_TIME *l_time, int *was_cut); int *warning); int check_time_range(struct st_mysql_time *time, int *warning); long calc_daynr(uint year,uint month,uint day); uint calc_days_in_year(uint year); Loading
mysql-test/r/func_sapdb.result +11 −4 Original line number Diff line number Diff line Loading @@ -107,7 +107,9 @@ subtime("02:01:01.999999", "01:01:01.999999") 01:00:00.000000 select timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002"); timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002") 8807:59:59.999999 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '8807:59:59.999999' select timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002"); timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002") 46:58:57.999999 Loading Loading @@ -219,13 +221,16 @@ SELECT TIMEDIFF(t1, t4) As ttt, TIMEDIFF(t2, t3) As qqq, TIMEDIFF(t3, t2) As eee, TIMEDIFF(t2, t4) As rrr from test; ttt qqq eee rrr -744:00:00 NULL NULL NULL 26305:01:02 22:58:58 -22:58:58 NULL -26305:01:02 -22:58:58 22:58:58 NULL 838:59:59 22:58:58 -22:58:58 NULL -838:59:59 -22:58:58 22:58:58 NULL NULL 26:02:02 -26:02:02 NULL 00:00:00 -26:02:02 26:02:02 NULL NULL NULL NULL NULL NULL NULL NULL NULL 00:00:00 -24:00:00 24:00:00 NULL Warnings: Warning 1292 Truncated incorrect time value: '26305:01:02' Warning 1292 Truncated incorrect time value: '-26305:01:02' drop table t1, test; select addtime("-01:01:01.01", "-23:59:59.1") as a; a Loading @@ -235,7 +240,9 @@ a 10000 select microsecond(19971231235959.01) as a; a 10000 0 Warnings: Warning 1292 Truncated incorrect time value: '19971231235959.01' select date_add("1997-12-31",INTERVAL "10.09" SECOND_MICROSECOND) as a; a 1997-12-31 00:00:10.090000 Loading
mysql-test/r/func_time.result +90 −1 Original line number Diff line number Diff line Loading @@ -339,7 +339,9 @@ extract(DAY_MINUTE FROM "02 10:11:12") 21011 select extract(DAY_SECOND FROM "225 10:11:12"); extract(DAY_SECOND FROM "225 10:11:12") 225101112 8385959 Warnings: Warning 1292 Truncated incorrect time value: '225 10:11:12' select extract(HOUR FROM "1999-01-02 10:11:12"); extract(HOUR FROM "1999-01-02 10:11:12") 10 Loading Loading @@ -890,6 +892,93 @@ t1 CREATE TABLE `t1` ( `from_unixtime(1) + 0` double(23,6) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; SELECT SEC_TO_TIME(3300000); SEC_TO_TIME(3300000) 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '3300000' SELECT SEC_TO_TIME(3300000)+0; SEC_TO_TIME(3300000)+0 8385959.000000 Warnings: Warning 1292 Truncated incorrect time value: '3300000' SELECT SEC_TO_TIME(3600 * 4294967296); SEC_TO_TIME(3600 * 4294967296) 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '15461882265600' SELECT TIME_TO_SEC('916:40:00'); TIME_TO_SEC('916:40:00') 3020399 Warnings: Warning 1292 Truncated incorrect time value: '916:40:00' SELECT ADDTIME('500:00:00', '416:40:00'); ADDTIME('500:00:00', '416:40:00') 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '916:40:00' SELECT ADDTIME('916:40:00', '416:40:00'); ADDTIME('916:40:00', '416:40:00') 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '916:40:00' Warning 1292 Truncated incorrect time value: '1255:39:59' SELECT SUBTIME('916:40:00', '416:40:00'); SUBTIME('916:40:00', '416:40:00') 422:19:59 Warnings: Warning 1292 Truncated incorrect time value: '916:40:00' SELECT SUBTIME('-916:40:00', '416:40:00'); SUBTIME('-916:40:00', '416:40:00') -838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '-916:40:00' Warning 1292 Truncated incorrect time value: '-1255:39:59' SELECT MAKETIME(916,0,0); MAKETIME(916,0,0) 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '916:00:00' SELECT MAKETIME(4294967296, 0, 0); MAKETIME(4294967296, 0, 0) 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '4294967296:00:00' SELECT MAKETIME(-4294967296, 0, 0); MAKETIME(-4294967296, 0, 0) -838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '-4294967296:00:00' SELECT MAKETIME(0, 4294967296, 0); MAKETIME(0, 4294967296, 0) NULL SELECT MAKETIME(0, 0, 4294967296); MAKETIME(0, 0, 4294967296) NULL SELECT MAKETIME(CAST(-1 AS UNSIGNED), 0, 0); MAKETIME(CAST(-1 AS UNSIGNED), 0, 0) 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '18446744073709551615:00:00' SELECT EXTRACT(HOUR FROM '100000:02:03'); EXTRACT(HOUR FROM '100000:02:03') 838 Warnings: Warning 1292 Truncated incorrect time value: '100000:02:03' CREATE TABLE t1(f1 TIME); INSERT INTO t1 VALUES('916:00:00 a'); Warnings: Warning 1265 Data truncated for column 'f1' at row 1 Warning 1264 Out of range value adjusted for column 'f1' at row 1 SELECT * FROM t1; f1 838:59:59 DROP TABLE t1; SELECT SEC_TO_TIME(CAST(-1 AS UNSIGNED)); SEC_TO_TIME(CAST(-1 AS UNSIGNED)) 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '18446744073709551615' SET NAMES latin1; SET character_set_results = NULL; SHOW VARIABLES LIKE 'character_set_results'; Loading
mysql-test/t/func_time.test +43 −0 Original line number Diff line number Diff line Loading @@ -446,6 +446,49 @@ create table t1 select now() - now(), curtime() - curtime(), show create table t1; drop table t1; # # Bug #11655: Wrong time is returning from nested selects - maximum time exists # # check if SEC_TO_TIME() handles out-of-range values correctly SELECT SEC_TO_TIME(3300000); SELECT SEC_TO_TIME(3300000)+0; SELECT SEC_TO_TIME(3600 * 4294967296); # check if TIME_TO_SEC() handles out-of-range values correctly SELECT TIME_TO_SEC('916:40:00'); # check if ADDTIME() handles out-of-range values correctly SELECT ADDTIME('500:00:00', '416:40:00'); SELECT ADDTIME('916:40:00', '416:40:00'); # check if SUBTIME() handles out-of-range values correctly SELECT SUBTIME('916:40:00', '416:40:00'); SELECT SUBTIME('-916:40:00', '416:40:00'); # check if MAKETIME() handles out-of-range values correctly SELECT MAKETIME(916,0,0); SELECT MAKETIME(4294967296, 0, 0); SELECT MAKETIME(-4294967296, 0, 0); SELECT MAKETIME(0, 4294967296, 0); SELECT MAKETIME(0, 0, 4294967296); SELECT MAKETIME(CAST(-1 AS UNSIGNED), 0, 0); # check if EXTRACT() handles out-of-range values correctly SELECT EXTRACT(HOUR FROM '100000:02:03'); # check if we get proper warnings if both input string truncation # and out-of-range value occur CREATE TABLE t1(f1 TIME); INSERT INTO t1 VALUES('916:00:00 a'); SELECT * FROM t1; DROP TABLE t1; # # Bug #20927: sec_to_time treats big unsigned as signed # # check if SEC_TO_TIME() handles BIGINT UNSIGNED values correctly SELECT SEC_TO_TIME(CAST(-1 AS UNSIGNED)); # # 21913: DATE_FORMAT() Crashes mysql server if I use it through # mysql-connector-j driver. Loading
sql-common/my_time.c +69 −21 Original line number Diff line number Diff line Loading @@ -465,8 +465,10 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, There may be an optional [.second_part] after seconds length Length of str l_time Store result here was_cut Set to 1 if value was cut during conversion or to 0 otherwise. warning Set MYSQL_TIME_WARN_TRUNCATED flag if the input string was cut during conversion, and/or MYSQL_TIME_WARN_OUT_OF_RANGE flag, if the value is out of range. NOTES Because of the extra days argument, this function can only Loading @@ -478,15 +480,16 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, */ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, int *was_cut) int *warning) { long date[5],value; ulong date[5]; ulonglong value; const char *end=str+length, *end_of_days; my_bool found_days,found_hours; uint state; l_time->neg=0; *was_cut= 0; *warning= 0; for (; str != end && my_isspace(&my_charset_latin1,*str) ; str++) length--; if (str != end && *str == '-') Loading @@ -501,13 +504,16 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, /* Check first if this is a full TIMESTAMP */ if (length >= 12) { /* Probably full timestamp */ int was_cut; enum enum_mysql_timestamp_type res= str_to_datetime(str, length, l_time, (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), was_cut); (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), &was_cut); if ((int) res >= (int) MYSQL_TIMESTAMP_ERROR) { if (was_cut) *warning|= MYSQL_TIME_WARN_TRUNCATED; return res == MYSQL_TIMESTAMP_ERROR; /* We need to restore was_cut flag since str_to_datetime can modify it */ *was_cut= 0; } } /* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */ Loading Loading @@ -587,7 +593,7 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, if (field_length > 0) value*= (long) log_10_int[field_length]; else if (field_length < 0) *was_cut= 1; *warning|= MYSQL_TIME_WARN_TRUNCATED; date[4]=value; } else Loading @@ -601,10 +607,7 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, ((str[1] == '-' || str[1] == '+') && (end - str) > 2 && my_isdigit(&my_charset_latin1, str[2])))) { *was_cut= 1; return 1; } if (internal_format_positions[7] != 255) { Loading @@ -623,12 +626,12 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, } } /* Some simple checks */ if (date[2] >= 60 || date[3] >= 60) { *was_cut= 1; /* Integer overflow checks */ if (date[0] > UINT_MAX || date[1] > UINT_MAX || date[2] > UINT_MAX || date[3] > UINT_MAX || date[4] > UINT_MAX) return 1; } l_time->year= 0; /* For protocol::store_time */ l_time->month= 0; l_time->day= date[0]; Loading @@ -638,6 +641,10 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, l_time->second_part= date[4]; l_time->time_type= MYSQL_TIMESTAMP_TIME; /* Check if the value is valid and fits into TIME range */ if (check_time_range(l_time, warning)) return 1; /* Check if there is garbage at end of the TIME specification */ if (str != end) { Loading @@ -645,7 +652,7 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, { if (!my_isspace(&my_charset_latin1,*str)) { *was_cut= 1; *warning|= MYSQL_TIME_WARN_TRUNCATED; break; } } while (++str != end); Loading @@ -654,6 +661,47 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, } /* Check 'time' value to lie in the TIME range SYNOPSIS: check_time_range() time pointer to TIME value warning set MYSQL_TIME_WARN_OUT_OF_RANGE flag if the value is out of range DESCRIPTION If the time value lies outside of the range [-838:59:59, 838:59:59], set it to the closest endpoint of the range and set MYSQL_TIME_WARN_OUT_OF_RANGE flag in the 'warning' variable. RETURN 0 time value is valid, but was possibly truncated 1 time value is invalid */ int check_time_range(struct st_mysql_time *time, int *warning) { longlong hour; if (time->minute >= 60 || time->second >= 60) return 1; hour= time->hour + (24*time->day); if (hour <= TIME_MAX_HOUR && (hour != TIME_MAX_HOUR || time->minute != TIME_MAX_MINUTE || time->second != TIME_MAX_SECOND || !time->second_part)) return 0; time->day= 0; time->hour= TIME_MAX_HOUR; time->minute= TIME_MAX_MINUTE; time->second= TIME_MAX_SECOND; time->second_part= 0; *warning|= MYSQL_TIME_WARN_OUT_OF_RANGE; return 0; } /* Prepare offset of system time zone from UTC for my_system_gmt_sec() func. Loading Loading @@ -840,7 +888,7 @@ void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type) int my_time_to_str(const MYSQL_TIME *l_time, char *to) { uint extra_hours= 0; return my_sprintf(to, (to, "%s%02d:%02d:%02d", return my_sprintf(to, (to, "%s%02u:%02u:%02u", (l_time->neg ? "-" : ""), extra_hours+ l_time->hour, l_time->minute, Loading @@ -849,7 +897,7 @@ int my_time_to_str(const MYSQL_TIME *l_time, char *to) int my_date_to_str(const MYSQL_TIME *l_time, char *to) { return my_sprintf(to, (to, "%04d-%02d-%02d", return my_sprintf(to, (to, "%04u-%02u-%02u", l_time->year, l_time->month, l_time->day)); Loading @@ -857,7 +905,7 @@ int my_date_to_str(const MYSQL_TIME *l_time, char *to) int my_datetime_to_str(const MYSQL_TIME *l_time, char *to) { return my_sprintf(to, (to, "%04d-%02d-%02d %02d:%02d:%02d", return my_sprintf(to, (to, "%04u-%02u-%02u %02u:%02u:%02u", l_time->year, l_time->month, l_time->day, Loading