From 1cdf22374be6a23f026cfedd4d099b06f84a301c Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Sat, 4 May 2024 22:34:14 +0400 Subject: [PATCH] MDEV-34069 Zero datetime reinterprets as '1970-01-01 00:00:00' on field_datetime=field_timestamp The code in Field_timestamp::save_in_field() did not catch zero datetime and stored it to the other field like a usual value using store_timestamp_dec(), which knows nothing about zero date and treats {tv_sec=0, tv_usec=0} as a normal timeval value corresponding to '1970-01-01 00:00:00 +00:00'. Fixing the code to catch the special combination (ts==0 && sec_pat==0) and store it using store_time_dec() with a zero datetime passed as an argument. --- mysql-test/main/type_timestamp.result | 30 +++++++++++++++++++++++++++ mysql-test/main/type_timestamp.test | 20 ++++++++++++++++++ sql/field.cc | 2 ++ 3 files changed, 52 insertions(+) diff --git a/mysql-test/main/type_timestamp.result b/mysql-test/main/type_timestamp.result index f95a1d6ae39..2763b25f58c 100644 --- a/mysql-test/main/type_timestamp.result +++ b/mysql-test/main/type_timestamp.result @@ -1368,5 +1368,35 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t1; # +# MDEV-34069 Zero datetime reinterprets as '1970-01-01 00:00:00' on field_datetime=field_timestamp +# +SET sql_mode=''; +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES ('0000-00-00 00:00:00'); +SELECT * FROM t1; +a +0000-00-00 00:00:00 +CREATE TABLE t2 (a DATETIME); +INSERT INTO t2 SELECT a FROM t1; +SELECT * FROM t2; +a +0000-00-00 00:00:00 +SET sql_mode='NO_ZERO_DATE,NO_ZERO_IN_DATE'; +INSERT INTO t2 VALUES ('0000-00-00 00:00:00'); +Warnings: +Warning 1264 Out of range value for column 'a' at row 1 +INSERT INTO t2 SELECT a FROM t1; +Warnings: +Warning 1264 Out of range value for column 'a' at row 1 +SELECT * FROM t2; +a +0000-00-00 00:00:00 +0000-00-00 00:00:00 +0000-00-00 00:00:00 +DROP TABLE t2, t1; +SET time_zone=DEFAULT; +SET sql_mode=DEFAULT; +# # End of 10.5 tests # diff --git a/mysql-test/main/type_timestamp.test b/mysql-test/main/type_timestamp.test index 526a0e69857..076ecbd41ed 100644 --- a/mysql-test/main/type_timestamp.test +++ b/mysql-test/main/type_timestamp.test @@ -920,6 +920,26 @@ create table t1 (f1 timestamp, f2 timestamp); show create table t1; drop table t1; +--echo # +--echo # MDEV-34069 Zero datetime reinterprets as '1970-01-01 00:00:00' on field_datetime=field_timestamp +--echo # + +SET sql_mode=''; +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES ('0000-00-00 00:00:00'); +SELECT * FROM t1; +CREATE TABLE t2 (a DATETIME); +INSERT INTO t2 SELECT a FROM t1; +SELECT * FROM t2; +SET sql_mode='NO_ZERO_DATE,NO_ZERO_IN_DATE'; +INSERT INTO t2 VALUES ('0000-00-00 00:00:00'); +INSERT INTO t2 SELECT a FROM t1; +SELECT * FROM t2; +DROP TABLE t2, t1; +SET time_zone=DEFAULT; +SET sql_mode=DEFAULT; + --echo # --echo # End of 10.5 tests --echo # diff --git a/sql/field.cc b/sql/field.cc index 828687aeaf3..e428f38b896 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5184,6 +5184,8 @@ int Field_timestamp::save_in_field(Field *to) { ulong sec_part; my_time_t ts= get_timestamp(&sec_part); + if (!ts && !sec_part) + return to->store_time_dec(Datetime::zero().get_mysql_time(), decimals()); return to->store_timestamp_dec(Timeval(ts, sec_part), decimals()); }