From 954fba4739630580daff90b566f1ee1612131b8d Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Thu, 19 Jun 2008 18:02:04 +0500 Subject: [PATCH] Fixed bug #37076: TIMESTAMP/DATETIME/DATE values are not replicated correctly between machines with mixed endiannes --- mysql-test/extra/rpl_tests/rpl_row_basic.test | 16 ++ .../suite/rpl/r/rpl_row_basic_2myisam.result | 10 + .../suite/rpl/r/rpl_row_basic_3innodb.result | 10 + .../suite/rpl_ndb/r/rpl_row_basic_7ndb.result | 10 + sql/field.h | 182 +++++++++++------- 5 files changed, 162 insertions(+), 66 deletions(-) diff --git a/mysql-test/extra/rpl_tests/rpl_row_basic.test b/mysql-test/extra/rpl_tests/rpl_row_basic.test index 48ddbaf244a..f2142ccc4d4 100644 --- a/mysql-test/extra/rpl_tests/rpl_row_basic.test +++ b/mysql-test/extra/rpl_tests/rpl_row_basic.test @@ -265,6 +265,22 @@ eval SELECT "$last_error" AS Last_SQL_Error; enable_query_log; query_vertical SELECT COUNT(*) FROM t1 ORDER BY c1,c2; +# BUG#37076: TIMESTAMP/DATETIME values are not replicated correctly +# between machines with mixed endiannes +# (regression test) + +--echo **** Test for BUG#37076 **** +--echo **** On Master **** +connection master; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (a TIMESTAMP, b DATETIME, c DATE); +INSERT INTO t1 VALUES( + '2005-11-14 01:01:01', '2005-11-14 01:01:02', '2005-11-14'); + +--echo **** On Slave **** +sync_slave_with_master slave; +SELECT * FROM t1; + # # cleanup # diff --git a/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result b/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result index 22284a26412..ecd59005b59 100644 --- a/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result +++ b/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result @@ -440,4 +440,14 @@ Last_SQL_Error 0 SELECT COUNT(*) FROM t1 ORDER BY c1,c2; COUNT(*) 0 +**** Test for BUG#37076 **** +**** On Master **** +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (a TIMESTAMP, b DATETIME, c DATE); +INSERT INTO t1 VALUES( +'2005-11-14 01:01:01', '2005-11-14 01:01:02', '2005-11-14'); +**** On Slave **** +SELECT * FROM t1; +a b c +2005-11-14 01:01:01 2005-11-14 01:01:02 2005-11-14 DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8; diff --git a/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result b/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result index f7b9e5d627a..4fc2bc6d714 100644 --- a/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result +++ b/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result @@ -440,4 +440,14 @@ Last_SQL_Error 0 SELECT COUNT(*) FROM t1 ORDER BY c1,c2; COUNT(*) 0 +**** Test for BUG#37076 **** +**** On Master **** +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (a TIMESTAMP, b DATETIME, c DATE); +INSERT INTO t1 VALUES( +'2005-11-14 01:01:01', '2005-11-14 01:01:02', '2005-11-14'); +**** On Slave **** +SELECT * FROM t1; +a b c +2005-11-14 01:01:01 2005-11-14 01:01:02 2005-11-14 DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8; diff --git a/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result b/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result index 08232817e92..b1554bec156 100644 --- a/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result +++ b/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result @@ -440,4 +440,14 @@ Last_SQL_Error 0 SELECT COUNT(*) FROM t1 ORDER BY c1,c2; COUNT(*) 0 +**** Test for BUG#37076 **** +**** On Master **** +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (a TIMESTAMP, b DATETIME, c DATE); +INSERT INTO t1 VALUES( +'2005-11-14 01:01:01', '2005-11-14 01:01:02', '2005-11-14'); +**** On Slave **** +SELECT * FROM t1; +a b c +2005-11-14 01:01:01 2005-11-14 01:01:02 2005-11-14 DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8; diff --git a/sql/field.h b/sql/field.h index 479a71dfee5..c71f54d8165 100644 --- a/sql/field.h +++ b/sql/field.h @@ -529,6 +529,77 @@ private: */ virtual int do_save_field_metadata(uchar *metadata_ptr) { return 0; } + +protected: + /* + Helper function to pack()/unpack() int32 values + */ + static void handle_int32(uchar *to, const uchar *from, + bool low_byte_first_from, bool low_byte_first_to) + { + int32 val; +#ifdef WORDS_BIGENDIAN + if (low_byte_first_from) + val = sint4korr(from); + else +#endif + longget(val, from); + +#ifdef WORDS_BIGENDIAN + if (low_byte_first_to) + int4store(to, val); + else +#endif + longstore(to, val); + } + + /* + Helper function to pack()/unpack() int64 values + */ + static void handle_int64(uchar* to, const uchar *from, + bool low_byte_first_from, bool low_byte_first_to) + { + int64 val; +#ifdef WORDS_BIGENDIAN + if (low_byte_first_from) + val = sint8korr(from); + else +#endif + longlongget(val, from); + +#ifdef WORDS_BIGENDIAN + if (low_byte_first_to) + int8store(to, val); + else +#endif + longlongstore(to, val); + } + + uchar *pack_int32(uchar *to, const uchar *from, bool low_byte_first_to) + { + handle_int32(to, from, table->s->db_low_byte_first, low_byte_first_to); + return to + sizeof(int32); + } + + const uchar *unpack_int32(uchar* to, const uchar *from, + bool low_byte_first_from) + { + handle_int32(to, from, low_byte_first_from, table->s->db_low_byte_first); + return from + sizeof(int32); + } + + uchar *pack_int64(uchar* to, const uchar *from, bool low_byte_first_to) + { + handle_int64(to, from, table->s->db_low_byte_first, low_byte_first_to); + return to + sizeof(int64); + } + + const uchar *unpack_int64(uchar* to, const uchar *from, + bool low_byte_first_from) + { + handle_int64(to, from, low_byte_first_from, table->s->db_low_byte_first); + return from + sizeof(int64); + } }; @@ -916,43 +987,16 @@ public: void sql_type(String &str) const; uint32 max_display_length() { return MY_INT32_NUM_DECIMAL_DIGITS; } virtual uchar *pack(uchar* to, const uchar *from, - uint max_length, bool low_byte_first) + uint max_length __attribute__((unused)), + bool low_byte_first) { - int32 val; -#ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) - val = sint4korr(from); - else -#endif - longget(val, from); - -#ifdef WORDS_BIGENDIAN - if (low_byte_first) - int4store(to, val); - else -#endif - longstore(to, val); - return to + sizeof(val); + return pack_int32(to, from, low_byte_first); } - virtual const uchar *unpack(uchar* to, const uchar *from, - uint param_data, bool low_byte_first) + uint param_data __attribute__((unused)), + bool low_byte_first) { - int32 val; -#ifdef WORDS_BIGENDIAN - if (low_byte_first) - val = sint4korr(from); - else -#endif - longget(val, from); - -#ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) - int4store(to, val); - else -#endif - longstore(to, val); - return from + sizeof(val); + return unpack_int32(to, from, low_byte_first); } }; @@ -997,43 +1041,16 @@ public: bool can_be_compared_as_longlong() const { return TRUE; } uint32 max_display_length() { return 20; } virtual uchar *pack(uchar* to, const uchar *from, - uint max_length, bool low_byte_first) + uint max_length __attribute__((unused)), + bool low_byte_first) { - int64 val; -#ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) - val = sint8korr(from); - else -#endif - longlongget(val, from); - -#ifdef WORDS_BIGENDIAN - if (low_byte_first) - int8store(to, val); - else -#endif - longlongstore(to, val); - return to + sizeof(val); + return pack_int64(to, from, low_byte_first); } - virtual const uchar *unpack(uchar* to, const uchar *from, - uint param_data, bool low_byte_first) + uint param_data __attribute__((unused)), + bool low_byte_first) { - int64 val; -#ifdef WORDS_BIGENDIAN - if (low_byte_first) - val = sint8korr(from); - else -#endif - longlongget(val, from); - -#ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) - int8store(to, val); - else -#endif - longlongstore(to, val); - return from + sizeof(val); + return unpack_int64(to, from, low_byte_first); } }; #endif @@ -1207,6 +1224,17 @@ public: bool get_date(MYSQL_TIME *ltime,uint fuzzydate); bool get_time(MYSQL_TIME *ltime); timestamp_auto_set_type get_auto_set_type() const; + uchar *pack(uchar *to, const uchar *from, + uint max_length __attribute__((unused)), bool low_byte_first) + { + return pack_int32(to, from, low_byte_first); + } + const uchar *unpack(uchar* to, const uchar *from, + uint param_data __attribute__((unused)), + bool low_byte_first) + { + return unpack_int32(to, from, low_byte_first); + } }; @@ -1261,6 +1289,17 @@ public: void sql_type(String &str) const; bool can_be_compared_as_longlong() const { return TRUE; } bool zero_pack() const { return 1; } + uchar *pack(uchar* to, const uchar *from, + uint max_length __attribute__((unused)), bool low_byte_first) + { + return pack_int32(to, from, low_byte_first); + } + const uchar *unpack(uchar* to, const uchar *from, + uint param_data __attribute__((unused)), + bool low_byte_first) + { + return unpack_int32(to, from, low_byte_first); + } }; @@ -1374,6 +1413,17 @@ public: bool zero_pack() const { return 1; } bool get_date(MYSQL_TIME *ltime,uint fuzzydate); bool get_time(MYSQL_TIME *ltime); + uchar *pack(uchar* to, const uchar *from, + uint max_length __attribute__((unused)), bool low_byte_first) + { + return pack_int64(to, from, low_byte_first); + } + const uchar *unpack(uchar* to, const uchar *from, + uint param_data __attribute__((unused)), + bool low_byte_first) + { + return unpack_int64(to, from, low_byte_first); + } };