diff options
-rw-r--r-- | mysql-test/r/old-mode.result | 22 | ||||
-rw-r--r-- | mysql-test/t/old-mode.test | 17 | ||||
-rw-r--r-- | sql/field.cc | 17 | ||||
-rw-r--r-- | sql/field.h | 1 | ||||
-rw-r--r-- | sql/field_conv.cc | 19 |
5 files changed, 69 insertions, 7 deletions
diff --git a/mysql-test/r/old-mode.result b/mysql-test/r/old-mode.result index 398e719cf02..b9a3edd4e94 100644 --- a/mysql-test/r/old-mode.result +++ b/mysql-test/r/old-mode.result @@ -149,4 +149,26 @@ a unix_timestamp(a) 2010-10-31 02:25:26 1288477526 2010-10-31 02:25:26 1288481126 drop table t1; +set global mysql56_temporal_format=false; +create table t1 (a timestamp); +set timestamp=1288477526; +insert t1 values (null); +set timestamp=1288481126; +insert t1 values (null); +select a, unix_timestamp(a) from t1; +a unix_timestamp(a) +2010-10-31 02:25:26 1288477526 +2010-10-31 02:25:26 1288481126 +set global mysql56_temporal_format=true; +select a, unix_timestamp(a) from t1; +a unix_timestamp(a) +2010-10-31 02:25:26 1288477526 +2010-10-31 02:25:26 1288481126 +create table t2 (a timestamp); +insert t2 select a from t1; +select a, unix_timestamp(a) from t2; +a unix_timestamp(a) +2010-10-31 02:25:26 1288477526 +2010-10-31 02:25:26 1288481126 +drop table t1, t2; set time_zone=DEFAULT; diff --git a/mysql-test/t/old-mode.test b/mysql-test/t/old-mode.test index 99c92f8093d..ed33da523c7 100644 --- a/mysql-test/t/old-mode.test +++ b/mysql-test/t/old-mode.test @@ -86,6 +86,8 @@ SET @@global.mysql56_temporal_format=DEFAULT; # # MDEV-12672 Replicated TIMESTAMP fields given wrong value near DST change # + +# Copy_field set time_zone='Europe/Moscow'; set global mysql56_temporal_format=false; create table t1 (a timestamp); @@ -99,4 +101,19 @@ select a, unix_timestamp(a) from t1; alter table t1 modify a timestamp; select a, unix_timestamp(a) from t1; drop table t1; + +# field_conv_incompatible() +set global mysql56_temporal_format=false; +create table t1 (a timestamp); +set timestamp=1288477526; +insert t1 values (null); +set timestamp=1288481126; +insert t1 values (null); +select a, unix_timestamp(a) from t1; +set global mysql56_temporal_format=true; +select a, unix_timestamp(a) from t1; +create table t2 (a timestamp); +insert t2 select a from t1; +select a, unix_timestamp(a) from t2; +drop table t1, t2; set time_zone=DEFAULT; diff --git a/sql/field.cc b/sql/field.cc index 8eb37c56c7e..6a28b38a612 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5064,6 +5064,23 @@ int Field_timestamp::store(longlong nr, bool unsigned_val) } +int Field_timestamp::store_timestamp(Field_timestamp *from) +{ + ulong sec_part; + my_time_t ts= from->get_timestamp(&sec_part); + store_TIME(ts, sec_part); + if (!ts && !sec_part && get_thd()->variables.sql_mode & MODE_NO_ZERO_DATE) + { + ErrConvString s( + STRING_WITH_LEN("0000-00-00 00:00:00.000000") - (decimals() ? 6 - decimals() : 7), + system_charset_info); + set_datetime_warning(WARN_DATA_TRUNCATED, &s, MYSQL_TIMESTAMP_DATETIME, 1); + return 1; + } + return 0; +} + + double Field_timestamp::val_real(void) { return (double) Field_timestamp::val_int(); diff --git a/sql/field.h b/sql/field.h index 30f24ecc1bb..154037df767 100644 --- a/sql/field.h +++ b/sql/field.h @@ -2186,6 +2186,7 @@ public: int store(longlong nr, bool unsigned_val); int store_time_dec(MYSQL_TIME *ltime, uint dec); int store_decimal(const my_decimal *); + int store_timestamp(Field_timestamp *from); double val_real(void); longlong val_int(void); String *val_str(String*,String *); diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 74c5fb5b502..850403afb97 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -219,6 +219,13 @@ set_field_to_null_with_conversions(Field *field, bool no_conversions) } +static int copy_timestamp_fields(Field *from, Field *to) +{ + DBUG_ASSERT(from->type() == MYSQL_TYPE_TIMESTAMP); + DBUG_ASSERT(to->type() == MYSQL_TYPE_TIMESTAMP); + return ((Field_timestamp*)to)->store_timestamp((Field_timestamp*)from); +} + static void do_skip(Copy_field *copy __attribute__((unused))) { } @@ -419,13 +426,7 @@ static void do_field_decimal(Copy_field *copy) static void do_field_timestamp(Copy_field *copy) { - DBUG_ASSERT(copy->from_field->type() == MYSQL_TYPE_TIMESTAMP); - DBUG_ASSERT(copy->to_field->type() == MYSQL_TYPE_TIMESTAMP); - ulong sec_part; - Field_timestamp *f= static_cast<Field_timestamp*>(copy->from_field); - Field_timestamp *t= static_cast<Field_timestamp*>(copy->to_field); - my_time_t ts= f->get_timestamp(&sec_part); - t->store_TIME(ts, sec_part); + copy_timestamp_fields(copy->from_field, copy->to_field); } @@ -938,6 +939,10 @@ int field_conv_incompatible(Field *to, Field *from) my_decimal buff; return to->store_decimal(from->val_decimal(&buff)); } + if (from->type() == MYSQL_TYPE_TIMESTAMP && to->type() == MYSQL_TYPE_TIMESTAMP) + { + return copy_timestamp_fields(from, to); + } if (from->cmp_type() == TIME_RESULT) { MYSQL_TIME ltime; |