mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
Merge polly.local:/tmp/maint/bug11655/my51-bug11655
into polly.local:/home/kaa/src/maint/m51-new-maint--07OGx include/my_time.h: Auto merged mysql-test/t/func_time.test: Auto merged sql/field.cc: Auto merged sql/item_timefunc.cc: Auto merged sql/time.cc: Auto merged mysql-test/r/func_time.result: Manually merged
This commit is contained in:
commit
131d8b8645
8 changed files with 427 additions and 93 deletions
|
@ -57,6 +57,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);
|
||||
|
@ -69,7 +79,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);
|
||||
|
|
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -902,6 +904,93 @@ fmtddate field2
|
|||
Sep-4 12:00AM abcd
|
||||
DROP TABLE testBug8868;
|
||||
SET NAMES DEFAULT;
|
||||
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'
|
||||
(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%H') As H)
|
||||
union
|
||||
(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%H') As H);
|
||||
|
|
|
@ -466,6 +466,47 @@ SET NAMES DEFAULT;
|
|||
|
||||
|
||||
#
|
||||
# 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));
|
||||
# Bug #19844 time_format in Union truncates values
|
||||
#
|
||||
|
||||
|
|
|
@ -465,8 +465,10 @@ err:
|
|||
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
|
||||
|
@ -478,15 +480,16 @@ err:
|
|||
*/
|
||||
|
||||
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 == '-')
|
||||
|
@ -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 */
|
||||
|
@ -587,7 +593,7 @@ fractional:
|
|||
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
|
||||
|
@ -601,10 +607,7 @@ fractional:
|
|||
((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)
|
||||
{
|
||||
|
@ -623,12 +626,12 @@ fractional:
|
|||
}
|
||||
}
|
||||
|
||||
/* 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];
|
||||
|
@ -638,6 +641,10 @@ fractional:
|
|||
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)
|
||||
{
|
||||
|
@ -645,7 +652,7 @@ fractional:
|
|||
{
|
||||
if (!my_isspace(&my_charset_latin1,*str))
|
||||
{
|
||||
*was_cut= 1;
|
||||
*warning|= MYSQL_TIME_WARN_TRUNCATED;
|
||||
break;
|
||||
}
|
||||
} while (++str != end);
|
||||
|
@ -654,6 +661,47 @@ fractional:
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
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.
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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));
|
||||
|
@ -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,
|
||||
|
|
35
sql/field.cc
35
sql/field.cc
|
@ -4875,9 +4875,10 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
|
|||
{
|
||||
TIME ltime;
|
||||
long tmp;
|
||||
int error;
|
||||
int error= 0;
|
||||
int warning;
|
||||
|
||||
if (str_to_time(from, len, <ime, &error))
|
||||
if (str_to_time(from, len, <ime, &warning))
|
||||
{
|
||||
tmp=0L;
|
||||
error= 2;
|
||||
|
@ -4886,29 +4887,27 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (error)
|
||||
if (warning & MYSQL_TIME_WARN_TRUNCATED)
|
||||
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
WARN_DATA_TRUNCATED,
|
||||
from, len, MYSQL_TIMESTAMP_TIME, 1);
|
||||
|
||||
if (ltime.month)
|
||||
ltime.day=0;
|
||||
tmp=(ltime.day*24L+ltime.hour)*10000L+(ltime.minute*100+ltime.second);
|
||||
if (tmp > 8385959)
|
||||
if (warning & MYSQL_TIME_WARN_OUT_OF_RANGE)
|
||||
{
|
||||
tmp=8385959;
|
||||
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_WARN_DATA_OUT_OF_RANGE,
|
||||
from, len, MYSQL_TIMESTAMP_TIME, !error);
|
||||
error= 1;
|
||||
}
|
||||
if (ltime.month)
|
||||
ltime.day=0;
|
||||
tmp=(ltime.day*24L+ltime.hour)*10000L+(ltime.minute*100+ltime.second);
|
||||
if (error > 1)
|
||||
error= 2;
|
||||
}
|
||||
|
||||
if (ltime.neg)
|
||||
tmp= -tmp;
|
||||
error |= Field_time::store((longlong) tmp, FALSE);
|
||||
int3store(ptr,tmp);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -4928,16 +4927,16 @@ int Field_time::store(double nr)
|
|||
ASSERT_COLUMN_MARKED_FOR_WRITE;
|
||||
long tmp;
|
||||
int error= 0;
|
||||
if (nr > 8385959.0)
|
||||
if (nr > (double)TIME_MAX_VALUE)
|
||||
{
|
||||
tmp=8385959L;
|
||||
tmp= TIME_MAX_VALUE;
|
||||
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_WARN_DATA_OUT_OF_RANGE, nr, MYSQL_TIMESTAMP_TIME);
|
||||
error= 1;
|
||||
}
|
||||
else if (nr < -8385959.0)
|
||||
else if (nr < (double)-TIME_MAX_VALUE)
|
||||
{
|
||||
tmp= -8385959L;
|
||||
tmp= -TIME_MAX_VALUE;
|
||||
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_WARN_DATA_OUT_OF_RANGE, nr, MYSQL_TIMESTAMP_TIME);
|
||||
error= 1;
|
||||
|
@ -4966,17 +4965,17 @@ int Field_time::store(longlong nr, bool unsigned_val)
|
|||
ASSERT_COLUMN_MARKED_FOR_WRITE;
|
||||
long tmp;
|
||||
int error= 0;
|
||||
if (nr < (longlong) -8385959L && !unsigned_val)
|
||||
if (nr < (longlong) -TIME_MAX_VALUE && !unsigned_val)
|
||||
{
|
||||
tmp= -8385959L;
|
||||
tmp= -TIME_MAX_VALUE;
|
||||
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_WARN_DATA_OUT_OF_RANGE, nr,
|
||||
MYSQL_TIMESTAMP_TIME, 1);
|
||||
error= 1;
|
||||
}
|
||||
else if (nr > (longlong) 8385959 || nr < 0 && unsigned_val)
|
||||
else if (nr > (longlong) TIME_MAX_VALUE || nr < 0 && unsigned_val)
|
||||
{
|
||||
tmp=8385959L;
|
||||
tmp= TIME_MAX_VALUE;
|
||||
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_WARN_DATA_OUT_OF_RANGE, nr,
|
||||
MYSQL_TIMESTAMP_TIME, 1);
|
||||
|
|
|
@ -95,6 +95,125 @@ static bool make_datetime(date_time_format_types format, TIME *ltime,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Wrapper over make_datetime() with validation of the input TIME value
|
||||
|
||||
NOTE
|
||||
see make_datetime() for more information
|
||||
|
||||
RETURN
|
||||
1 if there was an error during converion
|
||||
0 otherwise
|
||||
*/
|
||||
|
||||
static bool make_datetime_with_warn(date_time_format_types format, TIME *ltime,
|
||||
String *str)
|
||||
{
|
||||
int warning= 0;
|
||||
bool rc;
|
||||
|
||||
if (make_datetime(format, ltime, str))
|
||||
return 1;
|
||||
if (check_time_range(ltime, &warning))
|
||||
return 1;
|
||||
if (!warning)
|
||||
return 0;
|
||||
|
||||
make_truncated_value_warning(current_thd, str->ptr(), str->length(),
|
||||
MYSQL_TIMESTAMP_TIME, NullS);
|
||||
return make_datetime(format, ltime, str);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Wrapper over make_time() with validation of the input TIME value
|
||||
|
||||
NOTE
|
||||
see make_time() for more info
|
||||
|
||||
RETURN
|
||||
1 if there was an error during conversion
|
||||
0 otherwise
|
||||
*/
|
||||
|
||||
static bool make_time_with_warn(const DATE_TIME_FORMAT *format,
|
||||
TIME *l_time, String *str)
|
||||
{
|
||||
int warning= 0;
|
||||
make_time(format, l_time, str);
|
||||
if (check_time_range(l_time, &warning))
|
||||
return 1;
|
||||
if (warning)
|
||||
{
|
||||
make_truncated_value_warning(current_thd, str->ptr(), str->length(),
|
||||
MYSQL_TIMESTAMP_TIME, NullS);
|
||||
make_time(format, l_time, str);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Convert seconds to TIME value with overflow checking
|
||||
|
||||
SYNOPSIS:
|
||||
sec_to_time()
|
||||
seconds number of seconds
|
||||
unsigned_flag 1, if 'seconds' is unsigned, 0, otherwise
|
||||
ltime output TIME value
|
||||
|
||||
DESCRIPTION
|
||||
If the 'seconds' argument is inside TIME data range, convert it to a
|
||||
corresponding value.
|
||||
Otherwise, truncate the resulting value to the nearest endpoint, and
|
||||
produce a warning message.
|
||||
|
||||
RETURN
|
||||
1 if the value was truncated during conversion
|
||||
0 otherwise
|
||||
*/
|
||||
|
||||
static bool sec_to_time(longlong seconds, bool unsigned_flag, TIME *ltime)
|
||||
{
|
||||
uint sec;
|
||||
|
||||
bzero((char *)ltime, sizeof(*ltime));
|
||||
|
||||
if (seconds < 0)
|
||||
{
|
||||
if (unsigned_flag)
|
||||
goto overflow;
|
||||
ltime->neg= 1;
|
||||
if (seconds < -3020399)
|
||||
goto overflow;
|
||||
seconds= -seconds;
|
||||
}
|
||||
else if (seconds > 3020399)
|
||||
goto overflow;
|
||||
|
||||
sec= (uint) ((ulonglong) seconds % 3600);
|
||||
ltime->hour= (uint) (seconds/3600);
|
||||
ltime->minute= sec/60;
|
||||
ltime->second= sec % 60;
|
||||
|
||||
return 0;
|
||||
|
||||
overflow:
|
||||
ltime->hour= TIME_MAX_HOUR;
|
||||
ltime->minute= TIME_MAX_MINUTE;
|
||||
ltime->second= TIME_MAX_SECOND;
|
||||
|
||||
char buf[22];
|
||||
int len= (int)(longlong10_to_str(seconds, buf, unsigned_flag ? 10 : -10)
|
||||
- buf);
|
||||
make_truncated_value_warning(current_thd, buf, len, MYSQL_TIMESTAMP_TIME,
|
||||
NullS);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Date formats corresponding to compound %r and %T conversion specifiers
|
||||
|
||||
|
@ -1546,8 +1665,6 @@ int Item_func_sysdate_local::save_in_field(Field *to, bool no_conversions)
|
|||
String *Item_func_sec_to_time::val_str(String *str)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
longlong seconds=(longlong) args[0]->val_int();
|
||||
uint sec;
|
||||
TIME ltime;
|
||||
|
||||
if ((null_value=args[0]->null_value) || str->alloc(19))
|
||||
|
@ -1556,19 +1673,8 @@ String *Item_func_sec_to_time::val_str(String *str)
|
|||
return (String*) 0;
|
||||
}
|
||||
|
||||
ltime.neg= 0;
|
||||
if (seconds < 0)
|
||||
{
|
||||
seconds= -seconds;
|
||||
ltime.neg= 1;
|
||||
}
|
||||
|
||||
sec= (uint) ((ulonglong) seconds % 3600);
|
||||
ltime.day= 0;
|
||||
ltime.hour= (uint) (seconds/3600);
|
||||
ltime.minute= sec/60;
|
||||
ltime.second= sec % 60;
|
||||
|
||||
sec_to_time(args[0]->val_int(), args[0]->unsigned_flag, <ime);
|
||||
|
||||
make_time((DATE_TIME_FORMAT *) 0, <ime, str);
|
||||
return str;
|
||||
}
|
||||
|
@ -1577,16 +1683,15 @@ String *Item_func_sec_to_time::val_str(String *str)
|
|||
longlong Item_func_sec_to_time::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
longlong seconds=args[0]->val_int();
|
||||
longlong sign=1;
|
||||
TIME ltime;
|
||||
|
||||
if ((null_value=args[0]->null_value))
|
||||
return 0;
|
||||
if (seconds < 0)
|
||||
{
|
||||
seconds= -seconds;
|
||||
sign= -1;
|
||||
}
|
||||
return sign*((seconds / 3600)*10000+((seconds/60) % 60)*100+ (seconds % 60));
|
||||
|
||||
sec_to_time(args[0]->val_int(), args[0]->unsigned_flag, <ime);
|
||||
|
||||
return (ltime.neg ? -1 : 1) *
|
||||
((ltime.hour)*10000 + ltime.minute*100 + ltime.second);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2575,7 +2680,9 @@ String *Item_func_add_time::val_str(String *str)
|
|||
}
|
||||
if (l_time1.neg != l_time2.neg)
|
||||
l_sign= -l_sign;
|
||||
|
||||
|
||||
bzero((char *)&l_time3, sizeof(l_time3));
|
||||
|
||||
l_time3.neg= calc_time_diff(&l_time1, &l_time2, -l_sign,
|
||||
&seconds, µseconds);
|
||||
|
||||
|
@ -2604,9 +2711,9 @@ String *Item_func_add_time::val_str(String *str)
|
|||
}
|
||||
|
||||
l_time3.hour+= days*24;
|
||||
if (!make_datetime(l_time1.second_part || l_time2.second_part ?
|
||||
TIME_MICROSECOND : TIME_ONLY,
|
||||
&l_time3, str))
|
||||
if (!make_datetime_with_warn(l_time1.second_part || l_time2.second_part ?
|
||||
TIME_MICROSECOND : TIME_ONLY,
|
||||
&l_time3, str))
|
||||
return str;
|
||||
|
||||
null_date:
|
||||
|
@ -2661,6 +2768,8 @@ String *Item_func_timediff::val_str(String *str)
|
|||
if (l_time1.neg != l_time2.neg)
|
||||
l_sign= -l_sign;
|
||||
|
||||
bzero((char *)&l_time3, sizeof(l_time3));
|
||||
|
||||
l_time3.neg= calc_time_diff(&l_time1, &l_time2, l_sign,
|
||||
&seconds, µseconds);
|
||||
|
||||
|
@ -2674,9 +2783,9 @@ String *Item_func_timediff::val_str(String *str)
|
|||
|
||||
calc_time_from_sec(&l_time3, (long) seconds, microseconds);
|
||||
|
||||
if (!make_datetime(l_time1.second_part || l_time2.second_part ?
|
||||
TIME_MICROSECOND : TIME_ONLY,
|
||||
&l_time3, str))
|
||||
if (!make_datetime_with_warn(l_time1.second_part || l_time2.second_part ?
|
||||
TIME_MICROSECOND : TIME_ONLY,
|
||||
&l_time3, str))
|
||||
return str;
|
||||
|
||||
null_date:
|
||||
|
@ -2694,29 +2803,58 @@ String *Item_func_maketime::val_str(String *str)
|
|||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
TIME ltime;
|
||||
bool overflow= 0;
|
||||
|
||||
long hour= (long) args[0]->val_int();
|
||||
long minute= (long) args[1]->val_int();
|
||||
long second= (long) args[2]->val_int();
|
||||
longlong hour= args[0]->val_int();
|
||||
longlong minute= args[1]->val_int();
|
||||
longlong second= args[2]->val_int();
|
||||
|
||||
if ((null_value=(args[0]->null_value ||
|
||||
args[1]->null_value ||
|
||||
args[2]->null_value ||
|
||||
minute > 59 || minute < 0 ||
|
||||
second > 59 || second < 0 ||
|
||||
str->alloc(19))))
|
||||
args[1]->null_value ||
|
||||
args[2]->null_value ||
|
||||
minute < 0 || minute > 59 ||
|
||||
second < 0 || second > 59 ||
|
||||
str->alloc(19))))
|
||||
return 0;
|
||||
|
||||
bzero((char *)<ime, sizeof(ltime));
|
||||
ltime.neg= 0;
|
||||
|
||||
/* Check for integer overflows */
|
||||
if (hour < 0)
|
||||
{
|
||||
ltime.neg= 1;
|
||||
hour= -hour;
|
||||
if (args[0]->unsigned_flag)
|
||||
overflow= 1;
|
||||
else
|
||||
ltime.neg= 1;
|
||||
}
|
||||
if (-hour > UINT_MAX || hour > UINT_MAX)
|
||||
overflow= 1;
|
||||
|
||||
if (!overflow)
|
||||
{
|
||||
ltime.hour= (uint) ((hour < 0 ? -hour : hour));
|
||||
ltime.minute= (uint) minute;
|
||||
ltime.second= (uint) second;
|
||||
}
|
||||
else
|
||||
{
|
||||
ltime.hour= TIME_MAX_HOUR;
|
||||
ltime.minute= TIME_MAX_MINUTE;
|
||||
ltime.second= TIME_MAX_SECOND;
|
||||
char buf[28];
|
||||
char *ptr= longlong10_to_str(hour, buf, args[0]->unsigned_flag ? 10 : -10);
|
||||
int len = (int)(ptr - buf) +
|
||||
my_sprintf(ptr, (ptr, ":%02u:%02u", (uint)minute, (uint)second));
|
||||
make_truncated_value_warning(current_thd, buf, len, MYSQL_TIMESTAMP_TIME,
|
||||
NullS);
|
||||
}
|
||||
|
||||
if (make_time_with_warn((DATE_TIME_FORMAT *) 0, <ime, str))
|
||||
{
|
||||
null_value= 1;
|
||||
return 0;
|
||||
}
|
||||
ltime.hour= (ulong) hour;
|
||||
ltime.minute= (ulong) minute;
|
||||
ltime.second= (ulong) second;
|
||||
make_time((DATE_TIME_FORMAT *) 0, <ime, str);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
@ -3060,7 +3198,7 @@ bool Item_func_str_to_date::get_date(TIME *ltime, uint fuzzy_date)
|
|||
goto null_date;
|
||||
|
||||
null_value= 0;
|
||||
bzero((char*) ltime, sizeof(ltime));
|
||||
bzero((char*) ltime, sizeof(*ltime));
|
||||
date_time_format.format.str= (char*) format->ptr();
|
||||
date_time_format.format.length= format->length();
|
||||
if (extract_date_time(&date_time_format, val->ptr(), val->length(),
|
||||
|
|
|
@ -289,9 +289,9 @@ my_time_t TIME_to_timestamp(THD *thd, const TIME *t, my_bool *in_dst_time_gap)
|
|||
bool
|
||||
str_to_time_with_warn(const char *str, uint length, TIME *l_time)
|
||||
{
|
||||
int was_cut;
|
||||
bool ret_val= str_to_time(str, length, l_time, &was_cut);
|
||||
if (was_cut)
|
||||
int warning;
|
||||
bool ret_val= str_to_time(str, length, l_time, &warning);
|
||||
if (ret_val || warning)
|
||||
make_truncated_value_warning(current_thd, str, length,
|
||||
MYSQL_TIMESTAMP_TIME, NullS);
|
||||
return ret_val;
|
||||
|
|
Loading…
Reference in a new issue