mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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: Added regression test for bug#37076. mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result: Added regression test for bug#37076. mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result: Added regression test for bug#37076. mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result: Added regression test for bug#37076. sql/field.h: Fixed bug #37076: TIMESTAMP/DATETIME/DATE values are not replicated correctly between machines with mixed endiannes pack and unpack virtual methods have been overloaded for Field_timestamp (TIMESTAMP domain), Field_datetime (DATETIME domain) and Field_date (DATE domain) classes to replicate data between platforms with different endiannes in a correct way like in Field_long and Field_longlong classes. Common code have been moved to private handle_int32 and handle_int64 private methods.
This commit is contained in:
@ -265,6 +265,22 @@ eval SELECT "$last_error" AS Last_SQL_Error;
|
|||||||
enable_query_log;
|
enable_query_log;
|
||||||
query_vertical SELECT COUNT(*) FROM t1 ORDER BY c1,c2;
|
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
|
# cleanup
|
||||||
#
|
#
|
||||||
|
@ -440,4 +440,14 @@ Last_SQL_Error
|
|||||||
0
|
0
|
||||||
SELECT COUNT(*) FROM t1 ORDER BY c1,c2;
|
SELECT COUNT(*) FROM t1 ORDER BY c1,c2;
|
||||||
COUNT(*) 0
|
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;
|
DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8;
|
||||||
|
@ -440,4 +440,14 @@ Last_SQL_Error
|
|||||||
0
|
0
|
||||||
SELECT COUNT(*) FROM t1 ORDER BY c1,c2;
|
SELECT COUNT(*) FROM t1 ORDER BY c1,c2;
|
||||||
COUNT(*) 0
|
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;
|
DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8;
|
||||||
|
@ -440,4 +440,14 @@ Last_SQL_Error
|
|||||||
0
|
0
|
||||||
SELECT COUNT(*) FROM t1 ORDER BY c1,c2;
|
SELECT COUNT(*) FROM t1 ORDER BY c1,c2;
|
||||||
COUNT(*) 0
|
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;
|
DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8;
|
||||||
|
182
sql/field.h
182
sql/field.h
@ -529,6 +529,77 @@ private:
|
|||||||
*/
|
*/
|
||||||
virtual int do_save_field_metadata(uchar *metadata_ptr)
|
virtual int do_save_field_metadata(uchar *metadata_ptr)
|
||||||
{ return 0; }
|
{ 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;
|
void sql_type(String &str) const;
|
||||||
uint32 max_display_length() { return MY_INT32_NUM_DECIMAL_DIGITS; }
|
uint32 max_display_length() { return MY_INT32_NUM_DECIMAL_DIGITS; }
|
||||||
virtual uchar *pack(uchar* to, const uchar *from,
|
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;
|
return pack_int32(to, from, low_byte_first);
|
||||||
#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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const uchar *unpack(uchar* to, const uchar *from,
|
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;
|
return unpack_int32(to, from, low_byte_first);
|
||||||
#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);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -997,43 +1041,16 @@ public:
|
|||||||
bool can_be_compared_as_longlong() const { return TRUE; }
|
bool can_be_compared_as_longlong() const { return TRUE; }
|
||||||
uint32 max_display_length() { return 20; }
|
uint32 max_display_length() { return 20; }
|
||||||
virtual uchar *pack(uchar* to, const uchar *from,
|
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;
|
return pack_int64(to, from, low_byte_first);
|
||||||
#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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const uchar *unpack(uchar* to, const uchar *from,
|
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;
|
return unpack_int64(to, from, low_byte_first);
|
||||||
#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);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@ -1207,6 +1224,17 @@ public:
|
|||||||
bool get_date(MYSQL_TIME *ltime,uint fuzzydate);
|
bool get_date(MYSQL_TIME *ltime,uint fuzzydate);
|
||||||
bool get_time(MYSQL_TIME *ltime);
|
bool get_time(MYSQL_TIME *ltime);
|
||||||
timestamp_auto_set_type get_auto_set_type() const;
|
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;
|
void sql_type(String &str) const;
|
||||||
bool can_be_compared_as_longlong() const { return TRUE; }
|
bool can_be_compared_as_longlong() const { return TRUE; }
|
||||||
bool zero_pack() const { return 1; }
|
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 zero_pack() const { return 1; }
|
||||||
bool get_date(MYSQL_TIME *ltime,uint fuzzydate);
|
bool get_date(MYSQL_TIME *ltime,uint fuzzydate);
|
||||||
bool get_time(MYSQL_TIME *ltime);
|
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);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user