diff --git a/mysql-test/main/create.result b/mysql-test/main/create.result index 07aaf1e7189..a07695d5ba7 100644 --- a/mysql-test/main/create.result +++ b/mysql-test/main/create.result @@ -128,7 +128,7 @@ drop table t2; create table t2 select now() as a , curtime() as b, curdate() as c , 1+1 as d , 1.0 + 1 as e , 33333333333333333 + 3 as f; describe t2; Field Type Null Key Default Extra -a datetime NO NULL +a timestamp NO NULL b time NO NULL c date NO NULL d int(3) NO NULL diff --git a/mysql-test/main/func_group.result b/mysql-test/main/func_group.result index b8634a3854d..838f8836f22 100644 --- a/mysql-test/main/func_group.result +++ b/mysql-test/main/func_group.result @@ -781,12 +781,12 @@ insert into t1 values (now()); create table t2 select f2 from (select max(now()) f2 from t1) a; show columns from t2; Field Type Null Key Default Extra -f2 datetime YES NULL +f2 timestamp YES NULL drop table t2; create table t2 select f2 from (select now() f2 from t1) a; show columns from t2; Field Type Null Key Default Extra -f2 datetime NO NULL +f2 timestamp NO NULL drop table t2, t1; CREATE TABLE t1( id int PRIMARY KEY, diff --git a/mysql-test/main/func_time.result b/mysql-test/main/func_time.result index d989380b967..fc03e1db6ff 100644 --- a/mysql-test/main/func_time.result +++ b/mysql-test/main/func_time.result @@ -583,7 +583,9 @@ from_unixtime(2147483647) 2038-01-19 06:14:07 select from_unixtime(0); from_unixtime(0) -1970-01-01 03:00:00 +NULL +Warnings: +Warning 1292 Truncated incorrect unixtime value: '0.0' select unix_timestamp(from_unixtime(2147483647)); unix_timestamp(from_unixtime(2147483647)) 2147483647 @@ -6323,10 +6325,12 @@ TIME('- 01:00:00') TIME('- 1 01:00:00') SET time_zone='+00:00'; SELECT NULLIF(FROM_UNIXTIME('foo'), '2012-12-12 21:10:14'); NULLIF(FROM_UNIXTIME('foo'), '2012-12-12 21:10:14') -1970-01-01 00:00:00 +NULL Warnings: Warning 1292 Truncated incorrect DECIMAL value: 'foo' +Warning 1292 Truncated incorrect unixtime value: '0.0' Warning 1292 Truncated incorrect DECIMAL value: 'foo' +Warning 1292 Truncated incorrect unixtime value: '0.0' SET time_zone=DEFAULT; # # MDEV-18402 Assertion `sec.sec() <= 59' failed in Item_func_maketime::get_date @@ -6437,3 +6441,120 @@ SET timestamp=DEFAULT; # # End of 11.6 tests # +# +# Start of 11.7 tests +# +# +# MDEV-15751 CURRENT_TIMESTAMP should return a TIMESTAMP [WITH TIME ZONE?] +# +CREATE TABLE t1 (localtimestamp TIMESTAMP); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'localtimestamp TIMESTAMP)' at line 1 +CREATE TABLE t1 (current_timestamp TIMESTAMP); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'current_timestamp TIMESTAMP)' at line 1 +CREATE TABLE t1 AS +SELECT +localtimestamp, +localtimestamp(), +localtimestamp(0), +localtimestamp(1), +localtimestamp(2), +localtimestamp(3), +localtimestamp(4), +localtimestamp(5), +localtimestamp(6); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `localtimestamp` datetime NOT NULL, + `localtimestamp()` datetime NOT NULL, + `localtimestamp(0)` datetime NOT NULL, + `localtimestamp(1)` datetime(1) NOT NULL, + `localtimestamp(2)` datetime(2) NOT NULL, + `localtimestamp(3)` datetime(3) NOT NULL, + `localtimestamp(4)` datetime(4) NOT NULL, + `localtimestamp(5)` datetime(5) NOT NULL, + `localtimestamp(6)` datetime(6) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci +DROP TABLE t1; +CREATE TABLE t1 AS +SELECT +current_timestamp(), +current_timestamp(0), +current_timestamp(1), +current_timestamp(2), +current_timestamp(3), +current_timestamp(4), +current_timestamp(5), +current_timestamp(6); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `current_timestamp()` timestamp NOT NULL, + `current_timestamp(0)` timestamp NOT NULL, + `current_timestamp(1)` timestamp(1) NOT NULL, + `current_timestamp(2)` timestamp(2) NOT NULL, + `current_timestamp(3)` timestamp(3) NOT NULL, + `current_timestamp(4)` timestamp(4) NOT NULL, + `current_timestamp(5)` timestamp(5) NOT NULL, + `current_timestamp(6)` timestamp(6) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci +DROP TABLE t1; +CREATE TABLE t1 AS +SELECT +sysdate(), +sysdate(0), +sysdate(1), +sysdate(2), +sysdate(3), +sysdate(4), +sysdate(5), +sysdate(6); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `sysdate()` timestamp NOT NULL, + `sysdate(0)` timestamp NOT NULL, + `sysdate(1)` timestamp(1) NOT NULL, + `sysdate(2)` timestamp(2) NOT NULL, + `sysdate(3)` timestamp(3) NOT NULL, + `sysdate(4)` timestamp(4) NOT NULL, + `sysdate(5)` timestamp(5) NOT NULL, + `sysdate(6)` timestamp(6) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci +DROP TABLE t1; +CREATE TABLE t1 AS +SELECT +from_unixtime(1000000e0), +from_unixtime(1000000), +from_unixtime(1000000.1), +from_unixtime(1000000.12), +from_unixtime(1000000.123), +from_unixtime(1000000.1234), +from_unixtime(1000000.12345), +from_unixtime(1000000.123456), +from_unixtime(1000000.1234567), +from_unixtime(1000000.12345678), +from_unixtime(1000000.123456789), +from_unixtime(1000000.1234567891), +from_unixtime(1000000.12345678912); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `from_unixtime(1000000e0)` timestamp(6) NULL DEFAULT NULL, + `from_unixtime(1000000)` timestamp NULL DEFAULT NULL, + `from_unixtime(1000000.1)` timestamp(1) NULL DEFAULT NULL, + `from_unixtime(1000000.12)` timestamp(2) NULL DEFAULT NULL, + `from_unixtime(1000000.123)` timestamp(3) NULL DEFAULT NULL, + `from_unixtime(1000000.1234)` timestamp(4) NULL DEFAULT NULL, + `from_unixtime(1000000.12345)` timestamp(5) NULL DEFAULT NULL, + `from_unixtime(1000000.123456)` timestamp(6) NULL DEFAULT NULL, + `from_unixtime(1000000.1234567)` timestamp(6) NULL DEFAULT NULL, + `from_unixtime(1000000.12345678)` timestamp(6) NULL DEFAULT NULL, + `from_unixtime(1000000.123456789)` timestamp(6) NULL DEFAULT NULL, + `from_unixtime(1000000.1234567891)` timestamp(6) NULL DEFAULT NULL, + `from_unixtime(1000000.12345678912)` timestamp(6) NULL DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci +DROP TABLE t1; +# +# End of 11.7 tests +# diff --git a/mysql-test/main/func_time.test b/mysql-test/main/func_time.test index f4478079a34..2726e928dc7 100644 --- a/mysql-test/main/func_time.test +++ b/mysql-test/main/func_time.test @@ -3293,3 +3293,79 @@ SET timestamp=DEFAULT; --echo # --echo # End of 11.6 tests --echo # + +--echo # +--echo # Start of 11.7 tests +--echo # + +--echo # +--echo # MDEV-15751 CURRENT_TIMESTAMP should return a TIMESTAMP [WITH TIME ZONE?] +--echo # + +--error ER_PARSE_ERROR +CREATE TABLE t1 (localtimestamp TIMESTAMP); +--error ER_PARSE_ERROR +CREATE TABLE t1 (current_timestamp TIMESTAMP); + +CREATE TABLE t1 AS +SELECT + localtimestamp, + localtimestamp(), + localtimestamp(0), + localtimestamp(1), + localtimestamp(2), + localtimestamp(3), + localtimestamp(4), + localtimestamp(5), + localtimestamp(6); +SHOW CREATE TABLE t1; +DROP TABLE t1; + + +CREATE TABLE t1 AS +SELECT + current_timestamp(), + current_timestamp(0), + current_timestamp(1), + current_timestamp(2), + current_timestamp(3), + current_timestamp(4), + current_timestamp(5), + current_timestamp(6); +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1 AS +SELECT + sysdate(), + sysdate(0), + sysdate(1), + sysdate(2), + sysdate(3), + sysdate(4), + sysdate(5), + sysdate(6); +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1 AS +SELECT + from_unixtime(1000000e0), + from_unixtime(1000000), + from_unixtime(1000000.1), + from_unixtime(1000000.12), + from_unixtime(1000000.123), + from_unixtime(1000000.1234), + from_unixtime(1000000.12345), + from_unixtime(1000000.123456), + from_unixtime(1000000.1234567), + from_unixtime(1000000.12345678), + from_unixtime(1000000.123456789), + from_unixtime(1000000.1234567891), + from_unixtime(1000000.12345678912); +SHOW CREATE TABLE t1; +DROP TABLE t1; + +--echo # +--echo # End of 11.7 tests +--echo # diff --git a/mysql-test/main/func_time_hires.result b/mysql-test/main/func_time_hires.result index 02c095b83c9..e37574eced5 100644 --- a/mysql-test/main/func_time_hires.result +++ b/mysql-test/main/func_time_hires.result @@ -39,12 +39,12 @@ t1 CREATE TABLE `t1` ( `sec_to_time(12345)` time DEFAULT NULL, `sec_to_time(12345.6789)` time(4) DEFAULT NULL, `sec_to_time(1234567e-2)` time(6) DEFAULT NULL, - `now()` datetime NOT NULL, + `now()` timestamp NOT NULL, `curtime(0)` time NOT NULL, `utc_timestamp(1)` datetime(1) NOT NULL, `utc_time(2)` time(2) NOT NULL, `current_time(3)` time(3) NOT NULL, - `current_timestamp(4)` datetime(4) NOT NULL, + `current_timestamp(4)` timestamp(4) NOT NULL, `localtime(5)` time(5) NOT NULL, `localtimestamp(6)` datetime(6) NOT NULL, `time_to_sec(123456)` bigint(17) DEFAULT NULL, diff --git a/mysql-test/main/ps.result b/mysql-test/main/ps.result index 8631dcda6f7..525e51e1b89 100644 --- a/mysql-test/main/ps.result +++ b/mysql-test/main/ps.result @@ -4574,21 +4574,21 @@ EXECUTE stmt USING CURRENT_TIMESTAMP; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `c1` datetime NOT NULL + `c1` timestamp NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci DROP TABLE t1; EXECUTE stmt USING CURRENT_TIMESTAMP(3); SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `c1` datetime(3) NOT NULL + `c1` timestamp(3) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci DROP TABLE t1; EXECUTE stmt USING CURRENT_TIMESTAMP(6); SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `c1` datetime(6) NOT NULL + `c1` timestamp(6) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci DROP TABLE t1; EXECUTE stmt USING CURRENT_TIME; diff --git a/mysql-test/main/timezone.result b/mysql-test/main/timezone.result index 7250cb21b00..c876a12f680 100644 --- a/mysql-test/main/timezone.result +++ b/mysql-test/main/timezone.result @@ -53,7 +53,7 @@ DROP TABLE t1; select unix_timestamp('1970-01-01 01:00:00'), unix_timestamp('1970-01-01 01:00:01'); unix_timestamp('1970-01-01 01:00:00') unix_timestamp('1970-01-01 01:00:01') -0 1 +NULL 1 select unix_timestamp('1969-12-31 23:59:59'), unix_timestamp('1970-01-01 00:00:00'), unix_timestamp('1970-01-01 00:59:59'); unix_timestamp('1969-12-31 23:59:59') unix_timestamp('1970-01-01 00:00:00') unix_timestamp('1970-01-01 00:59:59') NULL NULL NULL diff --git a/mysql-test/main/timezone2.result b/mysql-test/main/timezone2.result index 369147b41c6..fa648ae74f8 100644 --- a/mysql-test/main/timezone2.result +++ b/mysql-test/main/timezone2.result @@ -680,10 +680,10 @@ INSERT INTO t1 VALUES ('2001-01-01 10:20:30'),('2001-01-01 10:20:31'); # Optimized (more than 24 hours before the DST fall back) # SET timestamp=@first_second_after_dst_fall_back-24*3600-1; -SELECT UNIX_TIMESTAMP(), NOW(); -UNIX_TIMESTAMP() NOW() +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +UNIX_TIMESTAMP() LOCALTIMESTAMP() 1288393199 2010-10-30 02:59:59 -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: @@ -692,34 +692,34 @@ Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = # Not optimized (24 hours before the DST fall back) # SET timestamp=@first_second_after_dst_fall_back-24*3600; -SELECT UNIX_TIMESTAMP(), NOW(); -UNIX_TIMESTAMP() NOW() +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +UNIX_TIMESTAMP() LOCALTIMESTAMP() 1288393200 2010-10-30 03:00:00 -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (current_timestamp()) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (localtimestamp()) # # Not optimized (less than 24 hours after the DST fall back) # SET timestamp=@first_second_after_dst_fall_back+24*3600-1; -SELECT UNIX_TIMESTAMP(), NOW(); -UNIX_TIMESTAMP() NOW() +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +UNIX_TIMESTAMP() LOCALTIMESTAMP() 1288565999 2010-11-01 01:59:59 -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (current_timestamp()) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (localtimestamp()) # # Optimized (24 hours after the DST fall back) # SET timestamp=@first_second_after_dst_fall_back+24*3600; -SELECT UNIX_TIMESTAMP(), NOW(); -UNIX_TIMESTAMP() NOW() +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +UNIX_TIMESTAMP() LOCALTIMESTAMP() 1288566000 2010-11-01 02:00:00 -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: @@ -737,10 +737,10 @@ INSERT INTO t1 VALUES ('2001-01-01 10:20:30'),('2001-01-01 10:20:31'); # Optimized (more than 24 hours before the DST sprint forward) # SET timestamp=@first_second_after_dst_spring_forward-24*3600-1; -SELECT UNIX_TIMESTAMP(), NOW(); -UNIX_TIMESTAMP() NOW() +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +UNIX_TIMESTAMP() LOCALTIMESTAMP() 1301093999 2011-03-26 01:59:59 -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: @@ -749,34 +749,34 @@ Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = # Not optimized (24 hours before the DST sprint forward) # SET timestamp=@first_second_after_dst_spring_forward-24*3600; -SELECT UNIX_TIMESTAMP(), NOW(); -UNIX_TIMESTAMP() NOW() +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +UNIX_TIMESTAMP() LOCALTIMESTAMP() 1301094000 2011-03-26 02:00:00 -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (current_timestamp()) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (localtimestamp()) # # Not optimized (less than 24 hours after the DST sprint forward) # SET timestamp=@first_second_after_dst_spring_forward+24*3600-1; -SELECT UNIX_TIMESTAMP(), NOW(); -UNIX_TIMESTAMP() NOW() +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +UNIX_TIMESTAMP() LOCALTIMESTAMP() 1301266799 2011-03-28 02:59:59 -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (current_timestamp()) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (localtimestamp()) # # Optimized (24 hours after the DST sprint forward) # SET timestamp=@first_second_after_dst_spring_forward+24*3600; -SELECT UNIX_TIMESTAMP(), NOW(); -UNIX_TIMESTAMP() NOW() +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +UNIX_TIMESTAMP() LOCALTIMESTAMP() 1301266800 2011-03-28 03:00:00 -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: @@ -805,10 +805,10 @@ INSERT INTO t1 VALUES ('2001-01-01 10:20:30'); # Optimized (more than 24 hours before the leap second) # SET timestamp=@leap_second-24*3600-1; -SELECT UNIX_TIMESTAMP(), NOW(); -UNIX_TIMESTAMP() NOW() +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +UNIX_TIMESTAMP() LOCALTIMESTAMP() 362707208 1981-06-30 03:59:59 -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using where Warnings: @@ -817,37 +817,79 @@ Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = # Not optimized (24 hours before the leap second) # SET timestamp=@leap_second-24*3600; -SELECT UNIX_TIMESTAMP(), NOW(); -UNIX_TIMESTAMP() NOW() +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +UNIX_TIMESTAMP() LOCALTIMESTAMP() 362707209 1981-06-30 04:00:00 -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (current_timestamp()) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (localtimestamp()) # # Not optimized (less than 24 hours after the leap second) # SET timestamp=@leap_second+24*3600-1; -SELECT UNIX_TIMESTAMP(), NOW(); -UNIX_TIMESTAMP() NOW() +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +UNIX_TIMESTAMP() LOCALTIMESTAMP() 362880008 1981-07-02 03:59:58 -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (current_timestamp()) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (localtimestamp()) # # Not optimized (24 hours after the leap second) # SET timestamp=@leap_second+24*3600; -SELECT UNIX_TIMESTAMP(), NOW(); -UNIX_TIMESTAMP() NOW() +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +UNIX_TIMESTAMP() LOCALTIMESTAMP() 362880009 1981-07-02 03:59:59 -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using where Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'1981-07-02 03:59:59' DROP TABLE t1; SET time_zone=DEFAULT; +# +# End of 11.3 tests +# +# +# Start of 11.7 tests +# +# +# MDEV-15751 CURRENT_TIMESTAMP should return a TIMESTAMP [WITH TIME ZONE?] +# +SET time_zone='Europe/Moscow'; +CREATE TABLE t1 (a TIMESTAMP); +SET timestamp=1288477526 /*summer time*/; +INSERT INTO t1 VALUES (CURRENT_TIMESTAMP()), (COALESCE(CURRENT_TIMESTAMP())); +SET timestamp=1288477526+3600 /*winter time*/; +INSERT INTO t1 VALUES (CURRENT_TIMESTAMP()), (COALESCE(CURRENT_TIMESTAMP())); +# The two INSERTs produce equal "a" but different UNIX_TIMESTAMP(a) +SELECT a, UNIX_TIMESTAMP(a) FROM t1; +a UNIX_TIMESTAMP(a) +2010-10-31 02:25:26 1288477526 +2010-10-31 02:25:26 1288477526 +2010-10-31 02:25:26 1288481126 +2010-10-31 02:25:26 1288481126 +DROP TABLE t1; +SET time_zone=DEFAULT; +SET time_zone='Europe/Moscow'; +CREATE TABLE t1 (a TIMESTAMP); +SET timestamp=1288477526 /*summer time*/; +INSERT INTO t1 VALUES (LOCALTIMESTAMP()), (COALESCE(LOCALTIMESTAMP())); +SET timestamp=1288477526+3600 /*winter time*/; +INSERT INTO t1 VALUES (LOCALTIMESTAMP()), (COALESCE(LOCALTIMESTAMP())); +# The two INSERTs produce equal "a" and equal (summer) UNIX_TIMESTAMP(a) +SELECT a, UNIX_TIMESTAMP(a) FROM t1; +a UNIX_TIMESTAMP(a) +2010-10-31 02:25:26 1288477526 +2010-10-31 02:25:26 1288477526 +2010-10-31 02:25:26 1288477526 +2010-10-31 02:25:26 1288477526 +DROP TABLE t1; +SET time_zone=DEFAULT; +# +# End of 11.7 tests +# diff --git a/mysql-test/main/timezone2.test b/mysql-test/main/timezone2.test index 290129ac3ac..aba69d2081f 100644 --- a/mysql-test/main/timezone2.test +++ b/mysql-test/main/timezone2.test @@ -636,32 +636,32 @@ INSERT INTO t1 VALUES ('2001-01-01 10:20:30'),('2001-01-01 10:20:31'); --echo # SET timestamp=@first_second_after_dst_fall_back-24*3600-1; -SELECT UNIX_TIMESTAMP(), NOW(); -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); --echo # --echo # Not optimized (24 hours before the DST fall back) --echo # SET timestamp=@first_second_after_dst_fall_back-24*3600; -SELECT UNIX_TIMESTAMP(), NOW(); -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); --echo # --echo # Not optimized (less than 24 hours after the DST fall back) --echo # SET timestamp=@first_second_after_dst_fall_back+24*3600-1; -SELECT UNIX_TIMESTAMP(), NOW(); -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); --echo # --echo # Optimized (24 hours after the DST fall back) --echo # SET timestamp=@first_second_after_dst_fall_back+24*3600; -SELECT UNIX_TIMESTAMP(), NOW(); -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); DROP TABLE t1; SET time_zone=DEFAULT; @@ -684,32 +684,32 @@ INSERT INTO t1 VALUES ('2001-01-01 10:20:30'),('2001-01-01 10:20:31'); --echo # SET timestamp=@first_second_after_dst_spring_forward-24*3600-1; -SELECT UNIX_TIMESTAMP(), NOW(); -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); --echo # --echo # Not optimized (24 hours before the DST sprint forward) --echo # SET timestamp=@first_second_after_dst_spring_forward-24*3600; -SELECT UNIX_TIMESTAMP(), NOW(); -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); --echo # --echo # Not optimized (less than 24 hours after the DST sprint forward) --echo # SET timestamp=@first_second_after_dst_spring_forward+24*3600-1; -SELECT UNIX_TIMESTAMP(), NOW(); -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); --echo # --echo # Optimized (24 hours after the DST sprint forward) --echo # SET timestamp=@first_second_after_dst_spring_forward+24*3600; -SELECT UNIX_TIMESTAMP(), NOW(); -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); DROP TABLE t1; @@ -735,33 +735,72 @@ INSERT INTO t1 VALUES ('2001-01-01 10:20:30'); --echo # SET timestamp=@leap_second-24*3600-1; -SELECT UNIX_TIMESTAMP(), NOW(); -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); --echo # --echo # Not optimized (24 hours before the leap second) --echo # SET timestamp=@leap_second-24*3600; -SELECT UNIX_TIMESTAMP(), NOW(); -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); --echo # --echo # Not optimized (less than 24 hours after the leap second) --echo # SET timestamp=@leap_second+24*3600-1; -SELECT UNIX_TIMESTAMP(), NOW(); -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); --echo # --echo # Not optimized (24 hours after the leap second) --echo # SET timestamp=@leap_second+24*3600; -SELECT UNIX_TIMESTAMP(), NOW(); -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=now(); +SELECT UNIX_TIMESTAMP(), LOCALTIMESTAMP(); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=LOCALTIMESTAMP(); DROP TABLE t1; SET time_zone=DEFAULT; + + +--echo # +--echo # End of 11.3 tests +--echo # + +--echo # +--echo # Start of 11.7 tests +--echo # + +--echo # +--echo # MDEV-15751 CURRENT_TIMESTAMP should return a TIMESTAMP [WITH TIME ZONE?] +--echo # + +SET time_zone='Europe/Moscow'; +CREATE TABLE t1 (a TIMESTAMP); +SET timestamp=1288477526 /*summer time*/; +INSERT INTO t1 VALUES (CURRENT_TIMESTAMP()), (COALESCE(CURRENT_TIMESTAMP())); +SET timestamp=1288477526+3600 /*winter time*/; +INSERT INTO t1 VALUES (CURRENT_TIMESTAMP()), (COALESCE(CURRENT_TIMESTAMP())); +--echo # The two INSERTs produce equal "a" but different UNIX_TIMESTAMP(a) +SELECT a, UNIX_TIMESTAMP(a) FROM t1; +DROP TABLE t1; +SET time_zone=DEFAULT; + +SET time_zone='Europe/Moscow'; +CREATE TABLE t1 (a TIMESTAMP); +SET timestamp=1288477526 /*summer time*/; +INSERT INTO t1 VALUES (LOCALTIMESTAMP()), (COALESCE(LOCALTIMESTAMP())); +SET timestamp=1288477526+3600 /*winter time*/; +INSERT INTO t1 VALUES (LOCALTIMESTAMP()), (COALESCE(LOCALTIMESTAMP())); +--echo # The two INSERTs produce equal "a" and equal (summer) UNIX_TIMESTAMP(a) +SELECT a, UNIX_TIMESTAMP(a) FROM t1; +DROP TABLE t1; +SET time_zone=DEFAULT; + +--echo # +--echo # End of 11.7 tests +--echo # diff --git a/mysql-test/main/timezone4.result b/mysql-test/main/timezone4.result index 28028bea657..5c3270af351 100644 --- a/mysql-test/main/timezone4.result +++ b/mysql-test/main/timezone4.result @@ -1,6 +1,20 @@ select from_unixtime(0); from_unixtime(0) -1969-12-31 14:00:00 +NULL +Warnings: +Warning 1292 Truncated incorrect unixtime value: '0.0' +select from_unixtime(0.000001); +from_unixtime(0.000001) +1969-12-31 14:00:00.000001 +select from_unixtime(1); +from_unixtime(1) +1969-12-31 14:00:01 +select unix_timestamp('1969-12-31 14:00:00'); +unix_timestamp('1969-12-31 14:00:00') +NULL +select unix_timestamp('1969-12-31 14:00:00.000001'); +unix_timestamp('1969-12-31 14:00:00.000001') +0.000001 select unix_timestamp('1969-12-31 14:00:01'); unix_timestamp('1969-12-31 14:00:01') 1 diff --git a/mysql-test/main/timezone4.test b/mysql-test/main/timezone4.test index d7372c75d5a..a2f0b4505b3 100644 --- a/mysql-test/main/timezone4.test +++ b/mysql-test/main/timezone4.test @@ -8,6 +8,12 @@ # select from_unixtime(0); +select from_unixtime(0.000001); +select from_unixtime(1); + # check 0 boundary + +select unix_timestamp('1969-12-31 14:00:00'); +select unix_timestamp('1969-12-31 14:00:00.000001'); select unix_timestamp('1969-12-31 14:00:01'); diff --git a/mysql-test/main/type_newdecimal.result b/mysql-test/main/type_newdecimal.result index 06dc015c79f..048ff29f412 100644 --- a/mysql-test/main/type_newdecimal.result +++ b/mysql-test/main/type_newdecimal.result @@ -2472,6 +2472,7 @@ SELECT 1 FROM t1 GROUP BY v1 ORDER BY AVG ( from_unixtime ( '' ) ) ; 1 Warnings: Warning 1292 Truncated incorrect DECIMAL value: '' +Warning 1292 Truncated incorrect unixtime value: '0.0' DROP TABLE t1; SELECT SUM(DISTINCT 0.000000000000000000000000000000000000001); SUM(DISTINCT 0.000000000000000000000000000000000000001) diff --git a/mysql-test/main/type_timestamp,32bit.rdiff b/mysql-test/main/type_timestamp,32bit.rdiff index dd48488d66e..15fd72ce31d 100644 --- a/mysql-test/main/type_timestamp,32bit.rdiff +++ b/mysql-test/main/type_timestamp,32bit.rdiff @@ -1,11 +1,6 @@ ---- main/type_timestamp.result -+++ main/type_timestamp.reject -@@ -1,4 +1,3 @@ --drop table if exists t1,t2; - set time_zone="+03:00"; - CREATE TABLE t1 (a int, t timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); - CREATE TABLE t2 (a int, t datetime); -@@ -1373,7 +1372,7 @@ +--- type_timestamp.result 2024-09-17 11:32:07.799634536 +0400 ++++ type_timestamp.reject 2024-09-17 14:10:30.223789268 +0400 +@@ -1372,7 +1372,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: @@ -14,7 +9,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='1001-01-01 10:20:30'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where -@@ -1389,7 +1388,7 @@ +@@ -1388,7 +1388,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: @@ -23,7 +18,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=10010101102030; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where -@@ -1404,7 +1403,7 @@ +@@ -1403,7 +1403,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: @@ -32,7 +27,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=10010101102030e0; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where -@@ -1419,7 +1418,7 @@ +@@ -1418,7 +1418,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: @@ -41,7 +36,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=10010101102030.0; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where -@@ -1434,17 +1433,17 @@ +@@ -1433,17 +1433,17 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: @@ -62,12 +57,12 @@ # # Comparison predicates: Good TIMESTAMP values switch to TIMESTAMP comparison # -@@ -1570,22 +1569,22 @@ +@@ -1569,22 +1569,22 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2038-01-18 03:14:08' -+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (from_unixtime(0x7fffffff - 24 * 3600 + 1)) ++Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (cast(from_unixtime(0x7fffffff - 24 * 3600 + 1) as datetime)) EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2038-01-18 03:14:08'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where @@ -80,16 +75,16 @@ Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2038-01-19 03:14:07' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2038-01-19 03:14:07' - EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(0x7FFFFFFF); + EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST(FROM_UNIXTIME(0x7FFFFFFF) AS DATETIME); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2038-01-19 03:14:07' -+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (from_unixtime(0x7fffffff)) ++Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = (cast(from_unixtime(0x7fffffff) as datetime)) # # Corner cases: rounding # -@@ -1620,7 +1619,7 @@ +@@ -1619,7 +1619,7 @@ 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: Note 1292 Truncated incorrect DATETIME value: '2038-01-18 03:14:07.9999999' @@ -98,7 +93,7 @@ SET sql_mode=DEFAULT; # # NULLIF: Bad TIMESTAMP values preserve DATETIME comparison -@@ -1639,7 +1638,7 @@ +@@ -1638,7 +1638,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: @@ -107,7 +102,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,'1001-01-01 10:20:30'); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where -@@ -1654,7 +1653,7 @@ +@@ -1653,7 +1653,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: @@ -116,7 +111,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,10010101102030); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where -@@ -1669,7 +1668,7 @@ +@@ -1668,7 +1668,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: @@ -125,7 +120,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,10010101102030e0); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where -@@ -1684,7 +1683,7 @@ +@@ -1683,7 +1683,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: @@ -134,7 +129,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE NULLIF(a,10010101102030.0); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where -@@ -1699,7 +1698,7 @@ +@@ -1698,7 +1698,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: diff --git a/mysql-test/main/type_timestamp.result b/mysql-test/main/type_timestamp.result index 57363bb809b..7190cff26b2 100644 --- a/mysql-test/main/type_timestamp.result +++ b/mysql-test/main/type_timestamp.result @@ -1541,7 +1541,7 @@ Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = # Corner cases: DATETIME values inside the supported optimization range: # FROM_UNIXTIME(24*3600) .. FROM_UNIXTIME(0x7FFFFFFF-24*3600) # -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(24*3600); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST(FROM_UNIXTIME(24*3600) AS DATETIME); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: @@ -1556,7 +1556,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2038-01-18 03:14:07' -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(0x7FFFFFFF-24*3600); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST(FROM_UNIXTIME(0x7FFFFFFF-24*3600) AS DATETIME); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: @@ -1565,7 +1565,7 @@ Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = # Corner cases: DATETIME values after the supported optimization range # FROM_UNIXTIME(0x7FFFFFFF-24*3600+1) .. FROM_UNIXTIME(0x7FFFFFFF) # -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(0x7FFFFFFF-24*3600+1); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST(FROM_UNIXTIME(0x7FFFFFFF-24*3600+1) AS DATETIME); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: @@ -1580,7 +1580,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP/*WITH LOCAL TIME ZONE*/'2038-01-19 03:14:07' -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(0x7FFFFFFF); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST(FROM_UNIXTIME(0x7FFFFFFF) AS DATETIME); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: diff --git a/mysql-test/main/type_timestamp.test b/mysql-test/main/type_timestamp.test index d208759fca1..f3555d4ab84 100644 --- a/mysql-test/main/type_timestamp.test +++ b/mysql-test/main/type_timestamp.test @@ -992,20 +992,20 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(24*3600-1); --echo # FROM_UNIXTIME(24*3600) .. FROM_UNIXTIME(0x7FFFFFFF-24*3600) --echo # -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(24*3600); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST(FROM_UNIXTIME(24*3600) AS DATETIME); EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'1970-01-02 00:00:00'; EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2038-01-18 03:14:07'; -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(0x7FFFFFFF-24*3600); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST(FROM_UNIXTIME(0x7FFFFFFF-24*3600) AS DATETIME); --echo # --echo # Corner cases: DATETIME values after the supported optimization range --echo # FROM_UNIXTIME(0x7FFFFFFF-24*3600+1) .. FROM_UNIXTIME(0x7FFFFFFF) --echo # -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(0x7FFFFFFF-24*3600+1); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST(FROM_UNIXTIME(0x7FFFFFFF-24*3600+1) AS DATETIME); EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2038-01-18 03:14:08'; EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'2038-01-19 03:14:07'; -EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=FROM_UNIXTIME(0x7FFFFFFF); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST(FROM_UNIXTIME(0x7FFFFFFF) AS DATETIME); --echo # --echo # Corner cases: rounding diff --git a/mysql-test/suite/binlog/r/type_datetime_func_current_timestamp.result b/mysql-test/suite/binlog/r/type_datetime_func_current_timestamp.result new file mode 100644 index 00000000000..b18dcb43354 --- /dev/null +++ b/mysql-test/suite/binlog/r/type_datetime_func_current_timestamp.result @@ -0,0 +1,55 @@ +SET time_zone='+02:00'; +SET timestamp=100000000; +# +# This test makes sure binlog has SET time_zone +# for "TIMESTAMP function to DATETIME column" conversion. +# +CREATE TABLE t1 (a DATETIME); +INSERT INTO t1 VALUES (CURRENT_TIMESTAMP()); +INSERT INTO t1 VALUES (COALESCE(CURRENT_TIMESTAMP())); +DROP TABLE t1; +FLUSH LOGS; +/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/; +/*!40019 SET @@session.max_delayed_threads=0*/; +/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; +DELIMITER /*!*/; +ROLLBACK/*!*/; +use `test`/*!*/; +SET TIMESTAMP=100000000/*!*/; +SET @@session.pseudo_thread_id=999999999/*!*/; +SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1, @@session.sql_if_exists=0, @@session.explicit_defaults_for_timestamp=1, @@session.system_versioning_insert_history=0/*!*/; +SET @@session.sql_mode=#/*!*/; +SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; +/*!\C latin1 *//*!*/; +SET @@session.character_set_client=latin1,@@session.collation_connection=8,@@session.collation_server=#/*!*/; +SET @@session.lc_time_names=0/*!*/; +SET @@session.collation_database=DEFAULT/*!*/; +CREATE TABLE t1 (a DATETIME) +/*!*/; +START TRANSACTION +/*!*/; +SET TIMESTAMP=100000000/*!*/; +SET @@session.time_zone='+02:00'/*!*/; +INSERT INTO t1 VALUES (CURRENT_TIMESTAMP()) +/*!*/; +SET TIMESTAMP=100000000/*!*/; +COMMIT +/*!*/; +START TRANSACTION +/*!*/; +SET TIMESTAMP=100000000/*!*/; +INSERT INTO t1 VALUES (COALESCE(CURRENT_TIMESTAMP())) +/*!*/; +SET TIMESTAMP=100000000/*!*/; +COMMIT +/*!*/; +SET TIMESTAMP=100000000/*!*/; +DROP TABLE `t1` /* generated by server */ +/*!*/; +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/; +SET time_zone=DEFAULT; +SET Timestamp=DEFAULT; diff --git a/mysql-test/suite/binlog/r/type_timestamp_func_current_timestamp.result b/mysql-test/suite/binlog/r/type_timestamp_func_current_timestamp.result new file mode 100644 index 00000000000..14efb90e9ed --- /dev/null +++ b/mysql-test/suite/binlog/r/type_timestamp_func_current_timestamp.result @@ -0,0 +1,53 @@ +SET time_zone='+02:00'; +SET timestamp=100000000; +# +# This test makes sure binlog does not have SET time_zone +# +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES (CURRENT_TIMESTAMP()); +INSERT INTO t1 VALUES (COALESCE(CURRENT_TIMESTAMP())); +DROP TABLE t1; +FLUSH LOGS; +/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/; +/*!40019 SET @@session.max_delayed_threads=0*/; +/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; +DELIMITER /*!*/; +ROLLBACK/*!*/; +use `test`/*!*/; +SET TIMESTAMP=100000000/*!*/; +SET @@session.pseudo_thread_id=999999999/*!*/; +SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1, @@session.sql_if_exists=0, @@session.explicit_defaults_for_timestamp=1, @@session.system_versioning_insert_history=0/*!*/; +SET @@session.sql_mode=#/*!*/; +SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; +/*!\C latin1 *//*!*/; +SET @@session.character_set_client=latin1,@@session.collation_connection=8,@@session.collation_server=#/*!*/; +SET @@session.lc_time_names=0/*!*/; +SET @@session.collation_database=DEFAULT/*!*/; +CREATE TABLE t1 (a TIMESTAMP) +/*!*/; +START TRANSACTION +/*!*/; +SET TIMESTAMP=100000000/*!*/; +INSERT INTO t1 VALUES (CURRENT_TIMESTAMP()) +/*!*/; +SET TIMESTAMP=100000000/*!*/; +COMMIT +/*!*/; +START TRANSACTION +/*!*/; +SET TIMESTAMP=100000000/*!*/; +INSERT INTO t1 VALUES (COALESCE(CURRENT_TIMESTAMP())) +/*!*/; +SET TIMESTAMP=100000000/*!*/; +COMMIT +/*!*/; +SET TIMESTAMP=100000000/*!*/; +DROP TABLE `t1` /* generated by server */ +/*!*/; +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/; +SET time_zone=DEFAULT; +SET Timestamp=DEFAULT; diff --git a/mysql-test/suite/binlog/t/type_datetime_func_current_timestamp.test b/mysql-test/suite/binlog/t/type_datetime_func_current_timestamp.test new file mode 100644 index 00000000000..f7ecf82d503 --- /dev/null +++ b/mysql-test/suite/binlog/t/type_datetime_func_current_timestamp.test @@ -0,0 +1,29 @@ +--source include/not_embedded.inc +--source include/have_binlog_format_statement.inc +-- source include/have_log_bin.inc + +let $MYSQLD_DATADIR= `select @@datadir`; + +--disable_query_log +reset master; # get rid of previous tests binlog +--enable_query_log + +SET time_zone='+02:00'; +SET timestamp=100000000; + +--echo # +--echo # This test makes sure binlog has SET time_zone +--echo # for "TIMESTAMP function to DATETIME column" conversion. +--echo # + +CREATE TABLE t1 (a DATETIME); +INSERT INTO t1 VALUES (CURRENT_TIMESTAMP()); +INSERT INTO t1 VALUES (COALESCE(CURRENT_TIMESTAMP())); +DROP TABLE t1; +FLUSH LOGS; + +--replace_regex /@@session.sql_mode=\d+/@@session.sql_mode=#/ /collation_server=\d+/collation_server=#/ +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 --short-form + +SET time_zone=DEFAULT; +SET Timestamp=DEFAULT; diff --git a/mysql-test/suite/binlog/t/type_timestamp_func_current_timestamp.test b/mysql-test/suite/binlog/t/type_timestamp_func_current_timestamp.test new file mode 100644 index 00000000000..a844f0dfe09 --- /dev/null +++ b/mysql-test/suite/binlog/t/type_timestamp_func_current_timestamp.test @@ -0,0 +1,28 @@ +--source include/not_embedded.inc +--source include/have_binlog_format_statement.inc +-- source include/have_log_bin.inc + +let $MYSQLD_DATADIR= `select @@datadir`; + +--disable_query_log +reset master; # get rid of previous tests binlog +--enable_query_log + +SET time_zone='+02:00'; +SET timestamp=100000000; + +--echo # +--echo # This test makes sure binlog does not have SET time_zone +--echo # + +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES (CURRENT_TIMESTAMP()); +INSERT INTO t1 VALUES (COALESCE(CURRENT_TIMESTAMP())); +DROP TABLE t1; +FLUSH LOGS; + +--replace_regex /@@session.sql_mode=\d+/@@session.sql_mode=#/ /collation_server=\d+/collation_server=#/ +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 --short-form + +SET time_zone=DEFAULT; +SET Timestamp=DEFAULT; diff --git a/mysql-test/suite/vcol/r/vcol_blocked_sql_funcs.result b/mysql-test/suite/vcol/r/vcol_blocked_sql_funcs.result index 43fc9f8d187..bb4054bb20f 100644 --- a/mysql-test/suite/vcol/r/vcol_blocked_sql_funcs.result +++ b/mysql-test/suite/vcol/r/vcol_blocked_sql_funcs.result @@ -43,9 +43,9 @@ create or replace table t1 (a datetime, b varchar(10) as (localtime) PERSISTENT) ERROR HY000: Function or expression 'curtime()' cannot be used in the GENERATED ALWAYS AS clause of `b` # LOCALTIMESTAMP, LOCALTIMESTAMP()(v4.0.6) create or replace table t1 (a datetime, b varchar(10) as (localtimestamp()) PERSISTENT); -ERROR HY000: Function or expression 'current_timestamp()' cannot be used in the GENERATED ALWAYS AS clause of `b` +ERROR HY000: Function or expression 'localtimestamp()' cannot be used in the GENERATED ALWAYS AS clause of `b` create or replace table t1 (a datetime, b varchar(10) as (localtimestamp) PERSISTENT); -ERROR HY000: Function or expression 'current_timestamp()' cannot be used in the GENERATED ALWAYS AS clause of `b` +ERROR HY000: Function or expression 'localtimestamp()' cannot be used in the GENERATED ALWAYS AS clause of `b` # NOW() create or replace table t1 (a datetime, b varchar(10) as (now()) PERSISTENT); ERROR HY000: Function or expression 'current_timestamp()' cannot be used in the GENERATED ALWAYS AS clause of `b` diff --git a/mysql-test/suite/versioning/r/derived.result b/mysql-test/suite/versioning/r/derived.result index 50cfb4020d0..700c92a8d5c 100644 --- a/mysql-test/suite/versioning/r/derived.result +++ b/mysql-test/suite/versioning/r/derived.result @@ -211,12 +211,12 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where 1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join) Query A: -Note 1003 select `test`.`t1`.`x` AS `x`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME AS OF TIMESTAMP current_timestamp(6) join `test`.`t2` FOR SYSTEM_TIME AS OF TIMESTAMP current_timestamp(6) where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t2`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t2`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t1`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t1`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' +Note 1003 select `test`.`t1`.`x` AS `x`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME AS OF TIMESTAMP current_timestamp(6) join `test`.`t2` FOR SYSTEM_TIME AS OF TIMESTAMP current_timestamp(6) where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t2`.`row_end` > (current_timestamp(6)) and `test`.`t2`.`row_start` <= (current_timestamp(6)) and `test`.`t1`.`row_end` > (current_timestamp(6)) and `test`.`t1`.`row_start` <= (current_timestamp(6)) id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where 1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join) Query B: -Note 1003 select `test`.`t1`.`x` AS `x`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME AS OF TIMESTAMP current_timestamp(6) join `test`.`t2` FOR SYSTEM_TIME AS OF TIMESTAMP current_timestamp(6) where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t2`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t2`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t1`.`row_end` > TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' and `test`.`t1`.`row_start` <= TIMESTAMP/*WITH LOCAL TIME ZONE*/'YYYY-MM-DD hh:ss:mm:.uuuuuu' +Note 1003 select `test`.`t1`.`x` AS `x`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME AS OF TIMESTAMP current_timestamp(6) join `test`.`t2` FOR SYSTEM_TIME AS OF TIMESTAMP current_timestamp(6) where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t2`.`row_end` > (current_timestamp(6)) and `test`.`t2`.`row_start` <= (current_timestamp(6)) and `test`.`t1`.`row_end` > (current_timestamp(6)) and `test`.`t1`.`row_start` <= (current_timestamp(6)) Fine result: queries A and B are equal. ## LEFT JOIN: t1, t2 versioned select * from ( diff --git a/sql/field.h b/sql/field.h index f0acfb6643d..554088144f2 100644 --- a/sql/field.h +++ b/sql/field.h @@ -3272,7 +3272,7 @@ public: bool zero_pack() const override { return false; } /* This method is used by storage/perfschema and - Item_func_now_local::save_in_field(). + thd_get_query_start_data(). */ void store_TIME(my_time_t ts, ulong sec_part) { diff --git a/sql/item.cc b/sql/item.cc index f19e776882e..357dec9e733 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2752,6 +2752,26 @@ bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll, } +bool +Item_func_or_sum + ::check_fsp_or_error() const +{ + if (decimals > TIME_SECOND_PART_DIGITS) + { + /* + Historically MariaDB raises ER_TOO_BIG_PRECISION + instead of ER_TOO_BIG_SCALE when checking fractional digits + of an SQL function. Perhaps should be fixed eventually. + */ + my_error(ER_TOO_BIG_PRECISION, MYF(0), + func_name(), TIME_SECOND_PART_DIGITS); + return true; + } + return false; +} + + + /** @brief Building clone for Item_func_or_sum diff --git a/sql/item.h b/sql/item.h index 716e2a4e583..3f7439aec0f 100644 --- a/sql/item.h +++ b/sql/item.h @@ -5601,6 +5601,8 @@ class Item_func_or_sum: public Item_result_field, public Used_tables_and_const_cache { protected: + bool check_fsp_or_error() const; + bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems, uint flags, int item_sep) { diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 924824e0f93..f47da52f884 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1255,6 +1255,15 @@ bool Item_func_unix_timestamp::get_timestamp_value(my_time_t *seconds, Timestamp tm(native); *seconds= (my_time_t) tm.tv_sec; *second_part= tm.tv_usec; + if ((null_value= (tm.tv_sec == 0 && tm.tv_usec == 0))) + { + /* + The value {0,0}='1970-01-01 00:00:00.000000 GMT' cannot be + stored in a TIMESTAMP field. Return SQL NULL. + Simmetrically, UNIX_TIMESTAMP(0) also returns SQL NULL. + */ + return true; + } return false; } @@ -1536,6 +1545,17 @@ bool Item_func_from_days::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzz } +bool Item_func_current_timestamp::val_native(THD *thd, Native *to) +{ + Timestamp ts(Timeval(thd->query_start(), thd->query_start_sec_part())); + /* + to_native() can fail in case of EOM. Don't set null_value on EOM, + because CURRENT_TIMESTAMP is NOT NULL. The statement will fail anyway. + */ + return ts.trunc(decimals).to_native(to, decimals); +} + + /** Converts current time in my_time_t to MYSQL_TIME representation for local time zone. Defines time zone (local) used for whole CURDATE function. @@ -1581,13 +1601,8 @@ bool Item_func_curdate::get_date(THD *thd, MYSQL_TIME *res, bool Item_func_curtime::fix_fields(THD *thd, Item **items) { - if (decimals > TIME_SECOND_PART_DIGITS) - { - my_error(ER_TOO_BIG_PRECISION, MYF(0), - func_name(), TIME_SECOND_PART_DIGITS); - return 1; - } - return Item_timefunc::fix_fields(thd, items); + return check_fsp_or_error() || + Item_timefunc::fix_fields(thd, items); } bool Item_func_curtime::get_date(THD *thd, MYSQL_TIME *res, @@ -1657,13 +1672,8 @@ void Item_func_curtime_utc::store_now_in_TIME(THD *thd, MYSQL_TIME *now_time) bool Item_func_now::fix_fields(THD *thd, Item **items) { - if (decimals > TIME_SECOND_PART_DIGITS) - { - my_error(ER_TOO_BIG_PRECISION, MYF(0), - func_name(), TIME_SECOND_PART_DIGITS); - return 1; - } - return Item_datetimefunc::fix_fields(thd, items); + return check_fsp_or_error() || + Item_datetimefunc::fix_fields(thd, items); } void Item_func_now::print(String *str, enum_query_type query_type) @@ -1676,23 +1686,6 @@ void Item_func_now::print(String *str, enum_query_type query_type) } -int Item_func_now_local::save_in_field(Field *field, bool no_conversions) -{ - if (field->type() == MYSQL_TYPE_TIMESTAMP) - { - THD *thd= field->get_thd(); - my_time_t ts= thd->query_start(); - ulong sec_part= decimals ? thd->query_start_sec_part() : 0; - sec_part-= my_time_fraction_remainder(sec_part, decimals); - field->set_notnull(); - field->store_timestamp(ts, sec_part); - return 0; - } - else - return Item_datetimefunc::save_in_field(field, no_conversions); -} - - /** Converts current time in my_time_t to MYSQL_TIME representation for local time zone. Defines time zone (local) used for whole NOW function. @@ -1739,22 +1732,18 @@ bool Item_func_now::get_date(THD *thd, MYSQL_TIME *res, Converts current time in my_time_t to MYSQL_TIME representation for local time zone. Defines time zone (local) used for whole SYSDATE function. */ -void Item_func_sysdate_local::store_now_in_TIME(THD *thd, MYSQL_TIME *now_time) +bool Item_func_sysdate_local::val_native(THD *thd, Native *to) { my_hrtime_t now= my_hrtime(); - thd->variables.time_zone->gmt_sec_to_TIME(now_time, hrtime_to_my_time(now)); - set_sec_part(hrtime_sec_part(now), now_time, this); - thd->used|= THD::TIME_ZONE_USED; + Timestamp ts(hrtime_to_my_time(now), hrtime_sec_part(now)); + /* + to_native() can fail on EOM. Don't set null_value here, + because SYSDATE is NOT NULL. The statement will fail anyway. + */ + return ts.trunc(decimals).to_native(to, decimals); } -bool Item_func_sysdate_local::get_date(THD *thd, MYSQL_TIME *res, - date_mode_t fuzzydate __attribute__((unused))) -{ - store_now_in_TIME(thd, res); - return 0; -} - bool Item_func_sec_to_time::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(fixed()); @@ -2766,7 +2755,6 @@ null_date: bool Item_func_from_unixtime::fix_length_and_dec(THD *thd) { - thd->used|= THD::TIME_ZONE_USED; tz= thd->variables.time_zone; Type_std_attributes::set( Type_temporal_attributes_not_fixed_dec(MAX_DATETIME_WIDTH, @@ -2777,26 +2765,36 @@ bool Item_func_from_unixtime::fix_length_and_dec(THD *thd) } -bool Item_func_from_unixtime::get_date(THD *thd, MYSQL_TIME *ltime, - date_mode_t fuzzydate __attribute__((unused))) +bool Item_func_from_unixtime::val_native(THD *thd, Native *to) { - bzero((char *)ltime, sizeof(*ltime)); - ltime->time_type= MYSQL_TIMESTAMP_TIME; - VSec9 sec(thd, args[0], "unixtime", TIMESTAMP_MAX_VALUE); DBUG_ASSERT(sec.is_null() || sec.sec() <= TIMESTAMP_MAX_VALUE); if (sec.is_null() || sec.truncated() || sec.neg()) return (null_value= 1); - sec.round(MY_MIN(decimals, TIME_SECOND_PART_DIGITS), thd->temporal_round_mode()); + // decimals can be NOT_FIXED_DEC + decimal_digits_t fixed_decimals= MY_MIN(decimals, TIME_SECOND_PART_DIGITS); + + sec.round(fixed_decimals, thd->temporal_round_mode()); + + if (sec.sec() == 0 && sec.usec() == 0) + { + /* + The value {0,0}='1970-01-01 00:00:00.000000 GMT' cannot be + stored in a TIMESTAMP field. Return SQL NULL. + Simmetrically, UNIX_TIMESTAMP('1970-01-01 00:00:00') + also returns SQL NULL (assuming time_zone='+00:00'). + */ + thd->push_warning_truncated_wrong_value("unixtime", "0.0"); + return (null_value= true); // 0.0 after rounding + } + if (sec.sec() > TIMESTAMP_MAX_VALUE) return (null_value= true); // Went out of range after rounding - tz->gmt_sec_to_TIME(ltime, (my_time_t) sec.sec()); - ltime->second_part= sec.usec(); - - return (null_value= 0); + const Timestamp ts(Timeval(sec.sec(), sec.usec())); + return null_value= ts.to_native(to, fixed_decimals); } diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index d5af342b18b..f44a031fa54 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -708,6 +708,50 @@ public: }; +class Item_timestampfunc: public Item_func +{ +protected: + Datetime to_datetime(THD *thd) + { + return Timestamp_or_zero_datetime_native_null(thd, this).to_datetime(thd); + } +public: + Item_timestampfunc(THD *thd) :Item_func(thd) {} + Item_timestampfunc(THD *thd, uint dec) :Item_func(thd) { decimals= dec; } + Item_timestampfunc(THD *thd, Item *a) :Item_func(thd, a) {} + const Type_handler *type_handler() const override + { return &type_handler_timestamp2; } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override + { + return null_value= to_datetime(thd).copy_to_mysql_time(ltime); + } + double val_real() override + { + const Datetime dt= to_datetime(current_thd); + null_value= !dt.is_valid_datetime(); + return dt.to_double(); + } + longlong val_int() override + { + const Datetime dt= to_datetime(current_thd); + null_value= !dt.is_valid_datetime(); + return dt.to_longlong(); + } + my_decimal *val_decimal(my_decimal *to) override + { + const Datetime dt= to_datetime(current_thd); + null_value= !dt.is_valid_datetime(); + return dt.to_decimal(to); + } + String *val_str(String *to) override + { + const Datetime dt= to_datetime(current_thd); + null_value= !dt.is_valid_datetime(); + return dt.to_string(to, decimals); + } +}; + + /* Abstract CURTIME function. Children should define what time zone is used */ class Item_func_curtime :public Item_timefunc @@ -838,18 +882,53 @@ public: }; +class Item_func_current_timestamp: public Item_timestampfunc +{ +public: + Item_func_current_timestamp(THD *thd, uint dec) + :Item_timestampfunc(thd, dec) + { } + LEX_CSTRING func_name_cstring() const override + { + static LEX_CSTRING name= {STRING_WITH_LEN("current_timestamp") }; + return name; + } + void print(String *str, enum_query_type query_type) override + { + str->append(func_name_cstring()); + str->append('('); + if (decimals) + str->append_ulonglong(decimals); + str->append(')'); + } + bool fix_length_and_dec(THD *thd) override + { + if (check_fsp_or_error()) + return true; + fix_attributes_datetime(decimals); + return false; + } + bool val_native(THD *thd, Native *to) override; + bool check_vcol_func_processor(void *arg) override + { + return mark_unsupported_function(func_name(), "()", arg, VCOL_TIME_FUNC); + } + enum Functype functype() const override { return NOW_FUNC; } + Item *do_get_copy(THD *thd) const override + { return get_item_copy(thd, this); } +}; + + class Item_func_now_local :public Item_func_now { public: Item_func_now_local(THD *thd, uint dec): Item_func_now(thd, dec) {} LEX_CSTRING func_name_cstring() const override { - static LEX_CSTRING name= {STRING_WITH_LEN("current_timestamp") }; + static LEX_CSTRING name= {STRING_WITH_LEN("localtimestamp") }; return name; } - int save_in_field(Field *field, bool no_conversions) override; void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time) override; - enum Functype functype() const override { return NOW_FUNC; } Item *do_get_copy(THD *thd) const override { return get_item_copy(thd, this); } }; @@ -880,18 +959,34 @@ public: This is like NOW(), but always uses the real current time, not the query_start(). This matches the Oracle behavior. */ -class Item_func_sysdate_local :public Item_func_now +class Item_func_sysdate_local :public Item_timestampfunc { public: - Item_func_sysdate_local(THD *thd, uint dec): Item_func_now(thd, dec) {} + Item_func_sysdate_local(THD *thd, uint dec) + :Item_timestampfunc(thd, dec) + { } bool const_item() const override { return 0; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("sysdate") }; return name; } - void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time) override; - bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) override; + void print(String *str, enum_query_type query_type) override + { + str->append(func_name_cstring()); + str->append('('); + if (decimals) + str->append_ulonglong(decimals); + str->append(')'); + } + bool fix_length_and_dec(THD *thd) override + { + if (check_fsp_or_error()) + return true; + fix_attributes_datetime(decimals); + return false; + } + bool val_native(THD *thd, Native *to) override; table_map used_tables() const override { return RAND_TABLE_BIT; } bool check_vcol_func_processor(void *arg) override { @@ -1033,20 +1128,20 @@ public: }; -class Item_func_from_unixtime :public Item_datetimefunc +class Item_func_from_unixtime :public Item_timestampfunc { bool check_arguments() const override { return args[0]->check_type_can_return_decimal(func_name_cstring()); } Time_zone *tz; public: - Item_func_from_unixtime(THD *thd, Item *a): Item_datetimefunc(thd, a) {} + Item_func_from_unixtime(THD *thd, Item *a): Item_timestampfunc(thd, a) {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("from_unixtime") }; return name; } bool fix_length_and_dec(THD *thd) override; - bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) override; + bool val_native(THD *thd, Native *to) override; bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC); diff --git a/sql/lex.h b/sql/lex.h index 8973419b73e..30cbbc5028e 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -353,7 +353,7 @@ SYMBOL symbols[] = { { "LOAD", SYM(LOAD)}, { "LOCAL", SYM(LOCAL_SYM)}, { "LOCALTIME", SYM(CURTIME)}, - { "LOCALTIMESTAMP", SYM(NOW_SYM)}, + { "LOCALTIMESTAMP", SYM(LOCALTIMESTAMP)}, { "LOCK", SYM(LOCK_SYM)}, { "LOCKED", SYM(LOCKED_SYM)}, { "LOCKS", SYM(LOCKS_SYM)}, diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index e3d62fd1a7b..8dcfc7fe94d 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -9613,7 +9613,7 @@ Item *LEX::make_item_func_sysdate(THD *thd, uint fsp) set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); Item *item= global_system_variables.sysdate_is_now == 0 ? (Item *) new (thd->mem_root) Item_func_sysdate_local(thd, fsp) : - (Item *) new (thd->mem_root) Item_func_now_local(thd, fsp); + (Item *) new (thd->mem_root) Item_func_current_timestamp(thd, fsp); if (unlikely(item == NULL)) return NULL; safe_to_cache_query=0; diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 9f2ab865621..2d355c27625 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -468,7 +468,10 @@ bool Timestamp::to_native(Native *to, uint decimals) const { uint len= my_timestamp_binary_length(decimals); if (to->reserve(len)) + { + to->length(0); // Safety: set to '0000-00-00 00:00:00' on falures return true; + } my_timestamp_to_binary(this, (uchar *) to->ptr(), decimals); to->length(len); return false; diff --git a/sql/sql_type.h b/sql/sql_type.h index 5d2021c0636..25491b0f42d 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -1340,7 +1340,7 @@ public: { return is_valid_temporal() ? TIME_to_double(this) : 0; } - my_decimal *to_decimal(my_decimal *to) + my_decimal *to_decimal(my_decimal *to) const { return is_valid_temporal() ? Temporal::to_decimal(to) : bad_to_decimal(to); } @@ -1987,7 +1987,7 @@ public: str->length(my_time_to_str(this, const_cast(str->ptr()), dec)); return str; } - my_decimal *to_decimal(my_decimal *to) + my_decimal *to_decimal(my_decimal *to) const { return is_valid_time() ? Temporal::to_decimal(to) : bad_to_decimal(to); } @@ -2342,7 +2342,7 @@ public: str->length(my_date_to_str(this, const_cast(str->ptr()))); return str; } - my_decimal *to_decimal(my_decimal *to) + my_decimal *to_decimal(my_decimal *to) const { return is_valid_date() ? Temporal::to_decimal(to) : bad_to_decimal(to); } @@ -2663,7 +2663,7 @@ public: str->length(my_datetime_to_str(this, const_cast(str->ptr()), dec)); return str; } - my_decimal *to_decimal(my_decimal *to) + my_decimal *to_decimal(my_decimal *to) const { return is_valid_datetime() ? Temporal::to_decimal(to) : bad_to_decimal(to); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index cc2b3d813bd..9f63aacc573 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -572,6 +572,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token LINEAR_SYM %token LINES %token LOAD +%token LOCALTIMESTAMP /* SQL-2003-R */ %token LOCATOR_SYM /* SQL-2003-N */ %token LOCK_SYM %token LONGBLOB @@ -3097,7 +3098,7 @@ opt_ev_status: ev_starts: /* empty */ { - Item *item= new (thd->mem_root) Item_func_now_local(thd, 0); + Item *item= new (thd->mem_root) Item_func_current_timestamp(thd, 0); if (unlikely(item == NULL)) MYSQL_YYABORT; Lex->event_parse_data->item_starts= item; @@ -6678,7 +6679,7 @@ attribute: } | ON UPDATE_SYM NOW_SYM opt_default_time_precision { - Item *item= new (thd->mem_root) Item_func_now_local(thd, $4); + Item *item= new (thd->mem_root) Item_func_current_timestamp(thd, $4); if (unlikely(item == NULL)) MYSQL_YYABORT; Lex->last_field->on_update= item; @@ -10500,9 +10501,16 @@ function_call_nonkeyword: if (unlikely($$ == NULL)) MYSQL_YYABORT; } - | NOW_SYM opt_time_precision + | LOCALTIMESTAMP opt_time_precision { $$= new (thd->mem_root) Item_func_now_local(thd, $2); + if (unlikely($$ == NULL)) + MYSQL_YYABORT; + Lex->safe_to_cache_query= false; + } + | NOW_SYM opt_time_precision + { + $$= new (thd->mem_root) Item_func_current_timestamp(thd, $2); if (unlikely($$ == NULL)) MYSQL_YYABORT; Lex->safe_to_cache_query=0;