Bug#18997: DATE_ADD and DATE_SUB perform year2K autoconversion magic on 4-digit year value
if input year for date_add() / date_sub() with INTERVAL is low enough for calc_daynr() to possibly return incorrect results (calc_daynr() has no information on whether the year is low because it was a two-digit year ('77) or because it was a really low four-digit year (0077) and will indiscriminately try to turn the value into a four-digit year by adding 1900 or 2000 respectively), the functions will now throw NULL. include/my_time.h: new define YY_MAGIC_BELOW: if year is below this threshold, magic kicks in in calc_daynr(). the idea is to convert two-digit years to four-digit ones, adding 1900 to values >= YY_PART_YEAR or adding 2000 otherwise. current value of YY_MAGIC_BELOW derived from original code in calc_daynr() mysql-test/r/func_time.result: test where 2 digit -> 4 digit year magic kicks in, and whether we throw NULL when it happens mysql-test/t/func_time.test: test where 2 digit -> 4 digit year magic kicks in, and whether we throw NULL when it happens sql-common/my_time.c: use new const YY_MAGIC_BELOW, apply 2-digit -> 4-digit magic only to years below this threshold. sql/item_timefunc.cc: throw NULL when year in date_add() / date_sub() would be affected by 2 digit -> 4 digit magic.
This commit is contained in:
parent
e8c981c7a5
commit
b41b0fd62b
@ -38,7 +38,10 @@ typedef long my_time_t;
|
||||
#define MY_TIME_T_MAX LONG_MAX
|
||||
#define MY_TIME_T_MIN LONG_MIN
|
||||
|
||||
/* two-digit years < this are 20..; >= this are 19.. */
|
||||
#define YY_PART_YEAR 70
|
||||
/* apply above magic to years < this */
|
||||
#define YY_MAGIC_BELOW 200
|
||||
|
||||
/* Flags to str_to_datetime */
|
||||
#define TIME_FUZZY_DATE 1
|
||||
|
@ -736,31 +736,6 @@ select last_day('2005-00-00');
|
||||
last_day('2005-00-00')
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect datetime value: '2005-00-00'
|
||||
select last_day('2005-00-01');
|
||||
last_day('2005-00-01')
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect datetime value: '2005-00-01'
|
||||
select last_day('2005-01-00');
|
||||
last_day('2005-01-00')
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect datetime value: '2005-01-00'
|
||||
select monthname(str_to_date(null, '%m')), monthname(str_to_date(null, '%m')),
|
||||
monthname(str_to_date(1, '%m')), monthname(str_to_date(0, '%m'));
|
||||
monthname(str_to_date(null, '%m')) monthname(str_to_date(null, '%m')) monthname(str_to_date(1, '%m')) monthname(str_to_date(0, '%m'))
|
||||
NULL NULL January NULL
|
||||
explain extended select timestampdiff(SQL_TSI_WEEK, '2001-02-01', '2001-05-01') as a1,
|
||||
timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a2;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Warnings:
|
||||
Note 1003 select timestampdiff(WEEK,_latin1'2001-02-01',_latin1'2001-05-01') AS `a1`,timestampdiff(SECOND_FRAC,_latin1'2001-02-01 12:59:59.120000',_latin1'2001-05-01 12:58:58.119999') AS `a2`
|
||||
select last_day('2005-00-00');
|
||||
last_day('2005-00-00')
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1292 Incorrect datetime value: '2005-00-00'
|
||||
select last_day('2005-00-01');
|
||||
last_day('2005-00-01')
|
||||
@ -772,6 +747,17 @@ last_day('2005-01-00')
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1292 Incorrect datetime value: '2005-01-00'
|
||||
select monthname(str_to_date(null, '%m')), monthname(str_to_date(null, '%m')),
|
||||
monthname(str_to_date(1, '%m')), monthname(str_to_date(0, '%m'));
|
||||
monthname(str_to_date(null, '%m')) monthname(str_to_date(null, '%m')) monthname(str_to_date(1, '%m')) monthname(str_to_date(0, '%m'))
|
||||
NULL NULL January NULL
|
||||
End of 4.1 tests
|
||||
explain extended select timestampdiff(SQL_TSI_WEEK, '2001-02-01', '2001-05-01') as a1,
|
||||
timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a2;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Warnings:
|
||||
Note 1003 select timestampdiff(WEEK,_latin1'2001-02-01',_latin1'2001-05-01') AS `a1`,timestampdiff(SECOND_FRAC,_latin1'2001-02-01 12:59:59.120000',_latin1'2001-05-01 12:58:58.119999') AS `a2`
|
||||
select time_format('100:00:00', '%H %k %h %I %l');
|
||||
time_format('100:00:00', '%H %k %h %I %l')
|
||||
100 100 04 04 4
|
||||
@ -891,3 +877,38 @@ id day id day
|
||||
1 2005-06-01 3 2005-07-15
|
||||
3 2005-07-01 3 2005-07-15
|
||||
DROP TABLE t1,t2;
|
||||
End of 5.0 tests
|
||||
select date_sub("0050-01-01 00:00:01",INTERVAL 2 SECOND);
|
||||
date_sub("0050-01-01 00:00:01",INTERVAL 2 SECOND)
|
||||
NULL
|
||||
select date_sub("0199-01-01 00:00:01",INTERVAL 2 SECOND);
|
||||
date_sub("0199-01-01 00:00:01",INTERVAL 2 SECOND)
|
||||
NULL
|
||||
select date_add("0199-12-31 23:59:59",INTERVAL 2 SECOND);
|
||||
date_add("0199-12-31 23:59:59",INTERVAL 2 SECOND)
|
||||
NULL
|
||||
select date_sub("0200-01-01 00:00:01",INTERVAL 2 SECOND);
|
||||
date_sub("0200-01-01 00:00:01",INTERVAL 2 SECOND)
|
||||
0199-12-31 23:59:59
|
||||
select date_sub("0200-01-01 00:00:01",INTERVAL 1 SECOND);
|
||||
date_sub("0200-01-01 00:00:01",INTERVAL 1 SECOND)
|
||||
0200-01-01 00:00:00
|
||||
select date_sub("0200-01-01 00:00:01",INTERVAL 2 SECOND);
|
||||
date_sub("0200-01-01 00:00:01",INTERVAL 2 SECOND)
|
||||
0199-12-31 23:59:59
|
||||
select date_add("2001-01-01 23:59:59",INTERVAL -2000 YEAR);
|
||||
date_add("2001-01-01 23:59:59",INTERVAL -2000 YEAR)
|
||||
0001-01-01 23:59:59
|
||||
select date_sub("50-01-01 00:00:01",INTERVAL 2 SECOND);
|
||||
date_sub("50-01-01 00:00:01",INTERVAL 2 SECOND)
|
||||
2049-12-31 23:59:59
|
||||
select date_sub("90-01-01 00:00:01",INTERVAL 2 SECOND);
|
||||
date_sub("90-01-01 00:00:01",INTERVAL 2 SECOND)
|
||||
1989-12-31 23:59:59
|
||||
select date_sub("0069-01-01 00:00:01",INTERVAL 2 SECOND);
|
||||
date_sub("0069-01-01 00:00:01",INTERVAL 2 SECOND)
|
||||
NULL
|
||||
select date_sub("0169-01-01 00:00:01",INTERVAL 2 SECOND);
|
||||
date_sub("0169-01-01 00:00:01",INTERVAL 2 SECOND)
|
||||
NULL
|
||||
End of 5.1 tests
|
||||
|
@ -367,19 +367,11 @@ select last_day('2005-01-00');
|
||||
select monthname(str_to_date(null, '%m')), monthname(str_to_date(null, '%m')),
|
||||
monthname(str_to_date(1, '%m')), monthname(str_to_date(0, '%m'));
|
||||
|
||||
# End of 4.1 tests
|
||||
--echo End of 4.1 tests
|
||||
|
||||
explain extended select timestampdiff(SQL_TSI_WEEK, '2001-02-01', '2001-05-01') as a1,
|
||||
timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a2;
|
||||
|
||||
#
|
||||
# Bug #10568
|
||||
#
|
||||
|
||||
select last_day('2005-00-00');
|
||||
select last_day('2005-00-01');
|
||||
select last_day('2005-01-00');
|
||||
|
||||
#
|
||||
# Bug #10590: %h, %I, and %l format specifies should all return results in
|
||||
# the 0-11 range
|
||||
@ -482,4 +474,23 @@ SELECT * FROM t1, t2
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
# End of 5.0 tests
|
||||
--echo End of 5.0 tests
|
||||
|
||||
#
|
||||
# Bug #18997
|
||||
#
|
||||
|
||||
select date_sub("0050-01-01 00:00:01",INTERVAL 2 SECOND);
|
||||
select date_sub("0199-01-01 00:00:01",INTERVAL 2 SECOND);
|
||||
select date_add("0199-12-31 23:59:59",INTERVAL 2 SECOND);
|
||||
select date_sub("0200-01-01 00:00:01",INTERVAL 2 SECOND);
|
||||
select date_sub("0200-01-01 00:00:01",INTERVAL 1 SECOND);
|
||||
select date_sub("0200-01-01 00:00:01",INTERVAL 2 SECOND);
|
||||
select date_add("2001-01-01 23:59:59",INTERVAL -2000 YEAR);
|
||||
select date_sub("50-01-01 00:00:01",INTERVAL 2 SECOND);
|
||||
select date_sub("90-01-01 00:00:01",INTERVAL 2 SECOND);
|
||||
select date_sub("0069-01-01 00:00:01",INTERVAL 2 SECOND);
|
||||
select date_sub("0169-01-01 00:00:01",INTERVAL 2 SECOND);
|
||||
|
||||
|
||||
--echo End of 5.1 tests
|
||||
|
@ -689,7 +689,7 @@ long calc_daynr(uint year,uint month,uint day)
|
||||
|
||||
if (year == 0 && month == 0 && day == 0)
|
||||
DBUG_RETURN(0); /* Skip errors */
|
||||
if (year < 200)
|
||||
if (year < YY_MAGIC_BELOW)
|
||||
{
|
||||
if ((year=year+1900) < 1900+YY_PART_YEAR)
|
||||
year+=100;
|
||||
|
@ -1963,6 +1963,9 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date)
|
||||
if (date_sub_interval)
|
||||
interval.neg = !interval.neg;
|
||||
|
||||
if (ltime->year < YY_MAGIC_BELOW)
|
||||
return (null_value=1);
|
||||
|
||||
return (null_value= date_add_interval(ltime, int_type, interval));
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user