From c99f9766b11bda7eb15d6875f2f1e64c2d01b461 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 5 Aug 2019 14:41:17 +0400 Subject: [PATCH] MDEV-19166 Assertion `!is_zero_datetime()' failed in Timestamp_or_zero_datetime::tv --- mysql-test/main/type_temporal_innodb.result | 13 +++++++++++++ mysql-test/main/type_temporal_innodb.test | 15 +++++++++++++++ sql/item.cc | 2 +- sql/item_timefunc.cc | 2 +- sql/sql_type.h | 17 +++++++++-------- 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/mysql-test/main/type_temporal_innodb.result b/mysql-test/main/type_temporal_innodb.result index 55b398b3b02..2aad1e02d02 100644 --- a/mysql-test/main/type_temporal_innodb.result +++ b/mysql-test/main/type_temporal_innodb.result @@ -172,3 +172,16 @@ CREATE TABLE tbl SELECT * FROM t1 WHERE t1.c1 = (SELECT c2 FROM t2 WHERE pk = 6) ERROR 22007: Truncated incorrect datetime value: '0000-00-00 00:00:00' DROP TABLE t1,t2; SET sql_mode=DEFAULT; +# +# MDEV-19166 Assertion `!is_zero_datetime()' failed in Timestamp_or_zero_datetime::tv +# +CREATE TABLE t1 (f TIMESTAMP DEFAULT 0) ENGINE=InnoDB; +INSERT INTO t1 VALUES ('2024-02-29'); +SELECT * FROM t1 WHERE SUBSTR(1 FROM BIT_LENGTH(f) FOR DEFAULT(f)); +f +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '' +DROP TABLE t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/type_temporal_innodb.test b/mysql-test/main/type_temporal_innodb.test index 3debb798018..b8c7720f8b6 100644 --- a/mysql-test/main/type_temporal_innodb.test +++ b/mysql-test/main/type_temporal_innodb.test @@ -81,3 +81,18 @@ CREATE TABLE tbl SELECT * FROM t1 WHERE t1.c1 = (SELECT c2 FROM t2 WHERE pk = 6) # ^^^ there is no column c2 in table t2 DROP TABLE t1,t2; SET sql_mode=DEFAULT; + + +--echo # +--echo # MDEV-19166 Assertion `!is_zero_datetime()' failed in Timestamp_or_zero_datetime::tv +--echo # + +CREATE TABLE t1 (f TIMESTAMP DEFAULT 0) ENGINE=InnoDB; +INSERT INTO t1 VALUES ('2024-02-29'); +SELECT * FROM t1 WHERE SUBSTR(1 FROM BIT_LENGTH(f) FOR DEFAULT(f)); +DROP TABLE t1; + + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/sql/item.cc b/sql/item.cc index 4bcaaa8aaf9..eaec0a2a737 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -9909,7 +9909,7 @@ Datetime Item_cache_timestamp::to_datetime(THD *thd) null_value= true; return Datetime(); } - return Datetime(thd, Timestamp_or_zero_datetime(m_native).tv()); + return m_native.to_datetime(thd); } diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 2c527154108..d3433963c25 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1220,7 +1220,7 @@ bool Item_func_unix_timestamp::get_timestamp_value(my_time_t *seconds, Timestamp_or_zero_datetime_native_null native(current_thd, args[0], true); if ((null_value= native.is_null() || native.is_zero_datetime())) return true; - Timestamp_or_zero_datetime tm(native); + Timestamp tm(native); *seconds= tm.tv().tv_sec; *second_part= tm.tv().tv_usec; return false; diff --git a/sql/sql_type.h b/sql/sql_type.h index a80ceb46838..f1f5995b3ec 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -2377,6 +2377,10 @@ public: } bool to_TIME(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) const; bool to_native(Native *to, uint decimals) const; + Datetime to_datetime(THD *thd) const + { + return Datetime(thd, *this); + } long fraction_remainder(uint dec) const { return my_time_fraction_remainder(tv_usec, dec); @@ -2417,7 +2421,7 @@ public: - real TIMESTAMP (seconds and microseconds since epoch), or - zero datetime '0000-00-00 00:00:00.000000' */ -class Timestamp_or_zero_datetime: public Timestamp +class Timestamp_or_zero_datetime: protected Timestamp { bool m_is_zero_datetime; public: @@ -2434,14 +2438,11 @@ public: Timestamp_or_zero_datetime(THD *thd, const MYSQL_TIME *ltime, uint *err_code); Datetime to_datetime(THD *thd) const { - return Datetime(thd, *this); + if (is_zero_datetime()) + return Datetime(); + return Timestamp::to_datetime(thd); } bool is_zero_datetime() const { return m_is_zero_datetime; } - const struct timeval &tv() const - { - DBUG_ASSERT(!is_zero_datetime()); - return Timestamp::tv(); - } void trunc(uint decimals) { if (!is_zero_datetime()) @@ -2487,7 +2488,7 @@ public: { return is_zero_datetime() ? Datetime() : - Datetime(thd, Timestamp_or_zero_datetime(*this).tv()); + Datetime(thd, Timestamp(*this).tv()); } bool is_zero_datetime() const {