diff --git a/mysql-test/main/func_time.result b/mysql-test/main/func_time.result index 8dcb7e36fcd..4b134388ce8 100644 --- a/mysql-test/main/func_time.result +++ b/mysql-test/main/func_time.result @@ -3140,7 +3140,7 @@ def EXTRACT(YEAR_MONTH FROM a) 3 6 6 Y 32896 0 63 def EXTRACT(QUARTER FROM a) 3 2 1 Y 32896 0 63 def EXTRACT(MONTH FROM a) 3 2 2 Y 32896 0 63 def EXTRACT(WEEK FROM a) 3 2 2 Y 32896 0 63 -def EXTRACT(DAY FROM a) 3 2 2 Y 32896 0 63 +def EXTRACT(DAY FROM a) 3 3 2 Y 32896 0 63 def EXTRACT(DAY_HOUR FROM a) 3 5 4 Y 32896 0 63 def EXTRACT(DAY_MINUTE FROM a) 3 7 6 Y 32896 0 63 def EXTRACT(DAY_SECOND FROM a) 3 9 8 Y 32896 0 63 @@ -3230,7 +3230,7 @@ t2 CREATE TABLE `t2` ( `EXTRACT(QUARTER FROM a)` int(2) DEFAULT NULL, `EXTRACT(MONTH FROM a)` int(2) DEFAULT NULL, `EXTRACT(WEEK FROM a)` int(2) DEFAULT NULL, - `EXTRACT(DAY FROM a)` int(2) DEFAULT NULL, + `EXTRACT(DAY FROM a)` int(3) DEFAULT NULL, `EXTRACT(DAY_HOUR FROM a)` int(5) DEFAULT NULL, `EXTRACT(DAY_MINUTE FROM a)` int(7) DEFAULT NULL, `EXTRACT(DAY_SECOND FROM a)` int(9) DEFAULT NULL, @@ -3279,7 +3279,7 @@ def EXTRACT(YEAR_MONTH FROM a) 3 6 1 Y 32896 0 63 def EXTRACT(QUARTER FROM a) 3 2 1 Y 32896 0 63 def EXTRACT(MONTH FROM a) 3 2 1 Y 32896 0 63 def EXTRACT(WEEK FROM a) 3 2 9 Y 32896 0 63 -def EXTRACT(DAY FROM a) 3 2 2 Y 32896 0 63 +def EXTRACT(DAY FROM a) 3 3 3 Y 32896 0 63 def EXTRACT(DAY_HOUR FROM a) 3 5 5 Y 32896 0 63 def EXTRACT(DAY_MINUTE FROM a) 3 7 7 Y 32896 0 63 def EXTRACT(DAY_SECOND FROM a) 3 9 9 Y 32896 0 63 @@ -3300,7 +3300,7 @@ EXTRACT(YEAR_MONTH FROM a) 0 EXTRACT(QUARTER FROM a) 0 EXTRACT(MONTH FROM a) 0 EXTRACT(WEEK FROM a) 613566757 -EXTRACT(DAY FROM a) 34 +EXTRACT(DAY FROM a) -34 EXTRACT(DAY_HOUR FROM a) -3422 EXTRACT(DAY_MINUTE FROM a) -342259 EXTRACT(DAY_SECOND FROM a) -34225959 @@ -3366,7 +3366,7 @@ EXTRACT(YEAR_MONTH FROM a) 0 EXTRACT(QUARTER FROM a) 0 EXTRACT(MONTH FROM a) 0 EXTRACT(WEEK FROM a) 613566757 -EXTRACT(DAY FROM a) 34 +EXTRACT(DAY FROM a) -34 EXTRACT(DAY_HOUR FROM a) -3422 EXTRACT(DAY_MINUTE FROM a) -342259 EXTRACT(DAY_SECOND FROM a) -34225959 @@ -3411,7 +3411,7 @@ t2 CREATE TABLE `t2` ( `EXTRACT(QUARTER FROM a)` int(2) DEFAULT NULL, `EXTRACT(MONTH FROM a)` int(2) DEFAULT NULL, `EXTRACT(WEEK FROM a)` int(2) DEFAULT NULL, - `EXTRACT(DAY FROM a)` int(2) DEFAULT NULL, + `EXTRACT(DAY FROM a)` int(3) DEFAULT NULL, `EXTRACT(DAY_HOUR FROM a)` int(5) DEFAULT NULL, `EXTRACT(DAY_MINUTE FROM a)` int(7) DEFAULT NULL, `EXTRACT(DAY_SECOND FROM a)` int(9) DEFAULT NULL, @@ -6113,3 +6113,45 @@ NULL NULL Warnings: Warning 1292 Truncated incorrect time value: '18446744073709551615-01' Warning 1292 Truncated incorrect time value: '18446744073709551616-01' +# +# MDEV-17434 EXTRACT(DAY FROM negative_time) returns wrong result +# +CREATE TABLE t1 (a TIME(6)); +INSERT INTO t1 VALUES ('-24:10:10.10'); +SELECT +EXTRACT(MINUTE FROM a), +EXTRACT(SECOND FROM a), +EXTRACT(MICROSECOND FROM a), +EXTRACT(DAY FROM a), +EXTRACT(DAY_HOUR FROM a), +EXTRACT(DAY_MINUTE FROM a), +EXTRACT(DAY_SECOND FROM a), +EXTRACT(DAY_MICROSECOND FROM a) +FROM t1; +EXTRACT(MINUTE FROM a) EXTRACT(SECOND FROM a) EXTRACT(MICROSECOND FROM a) EXTRACT(DAY FROM a) EXTRACT(DAY_HOUR FROM a) EXTRACT(DAY_MINUTE FROM a) EXTRACT(DAY_SECOND FROM a) EXTRACT(DAY_MICROSECOND FROM a) +-10 -10 -100000 -1 -100 -10010 -1001010 -1001010100000 +CREATE TABLE t2 AS +SELECT +EXTRACT(MINUTE FROM a), +EXTRACT(SECOND FROM a), +EXTRACT(MICROSECOND FROM a), +EXTRACT(DAY FROM a), +EXTRACT(DAY_HOUR FROM a), +EXTRACT(DAY_MINUTE FROM a), +EXTRACT(DAY_SECOND FROM a), +EXTRACT(DAY_MICROSECOND FROM a) +FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `EXTRACT(MINUTE FROM a)` int(3) DEFAULT NULL, + `EXTRACT(SECOND FROM a)` int(3) DEFAULT NULL, + `EXTRACT(MICROSECOND FROM a)` int(7) DEFAULT NULL, + `EXTRACT(DAY FROM a)` int(3) DEFAULT NULL, + `EXTRACT(DAY_HOUR FROM a)` int(5) DEFAULT NULL, + `EXTRACT(DAY_MINUTE FROM a)` int(7) DEFAULT NULL, + `EXTRACT(DAY_SECOND FROM a)` int(9) DEFAULT NULL, + `EXTRACT(DAY_MICROSECOND FROM a)` bigint(15) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t2; +DROP TABLE t1; diff --git a/mysql-test/main/func_time.test b/mysql-test/main/func_time.test index da00ff0eb45..69fd12448eb 100644 --- a/mysql-test/main/func_time.test +++ b/mysql-test/main/func_time.test @@ -3014,3 +3014,34 @@ SELECT SELECT TIME('42949672955959-01'), TIME('42949672965959-01'); SELECT TIME('18446744073709551615-01'), TIME('18446744073709551616-01'); + +--echo # +--echo # MDEV-17434 EXTRACT(DAY FROM negative_time) returns wrong result +--echo # + +CREATE TABLE t1 (a TIME(6)); +INSERT INTO t1 VALUES ('-24:10:10.10'); +SELECT + EXTRACT(MINUTE FROM a), + EXTRACT(SECOND FROM a), + EXTRACT(MICROSECOND FROM a), + EXTRACT(DAY FROM a), + EXTRACT(DAY_HOUR FROM a), + EXTRACT(DAY_MINUTE FROM a), + EXTRACT(DAY_SECOND FROM a), + EXTRACT(DAY_MICROSECOND FROM a) +FROM t1; +CREATE TABLE t2 AS +SELECT + EXTRACT(MINUTE FROM a), + EXTRACT(SECOND FROM a), + EXTRACT(MICROSECOND FROM a), + EXTRACT(DAY FROM a), + EXTRACT(DAY_HOUR FROM a), + EXTRACT(DAY_MINUTE FROM a), + EXTRACT(DAY_SECOND FROM a), + EXTRACT(DAY_MICROSECOND FROM a) +FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; +DROP TABLE t1; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 2fc5869d762..317495d354e 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2098,7 +2098,7 @@ bool Item_extract::fix_length_and_dec() case INTERVAL_QUARTER: set_date_length(2); break; // 1..4 case INTERVAL_MONTH: set_date_length(2); break; // MM case INTERVAL_WEEK: set_date_length(2); break; // 0..52 - case INTERVAL_DAY: set_date_length(2); break; // DD + case INTERVAL_DAY: set_day_length(2); break; // DD case INTERVAL_DAY_HOUR: set_time_length(4); break; // DDhh case INTERVAL_DAY_MINUTE: set_time_length(6); break; // DDhhmm case INTERVAL_DAY_SECOND: set_time_length(8); break; // DDhhmmss @@ -2148,7 +2148,7 @@ longlong Item_extract::val_int() week_format= current_thd->variables.default_week_format; return calc_week(<ime, week_mode(week_format), &year); } - case INTERVAL_DAY: return ltime.day; + case INTERVAL_DAY: return ltime.day * neg; case INTERVAL_DAY_HOUR: return (long) (ltime.day*100L+ltime.hour)*neg; case INTERVAL_DAY_MINUTE: return (long) (ltime.day*10000L+ ltime.hour*100L+ diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index c1e77eae5bc..59031c69c6a 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -978,6 +978,11 @@ class Item_extract :public Item_int_func max_length= length; //QQ: see above date_value= true; } + void set_day_length(uint32 length) + { + max_length= length + 1/*sign*/; // e.g. '-24:00:00' -> -1 + date_value= true; + } void set_time_length(uint32 length) { max_length= length + 1/*sign*/;