diff options
author | Mats Kindahl <mats.kindahl@oracle.com> | 2010-10-06 19:20:18 +0200 |
---|---|---|
committer | Mats Kindahl <mats.kindahl@oracle.com> | 2010-10-06 19:20:18 +0200 |
commit | 9d249079a8b9ee24f4b3b69fb224d7b0aa664ca3 (patch) | |
tree | 2909636aa5d6cef036b49fdc3bb632d2c1580abb /sql/field.h | |
parent | f703a7779fed9a9b677649ba443a6b467f0125d2 (diff) | |
download | mariadb-git-9d249079a8b9ee24f4b3b69fb224d7b0aa664ca3.tar.gz |
Bug #52131: SET and ENUM stored endian-dependent in binary log
Replication SET and ENUM fields from a big-endian to a little-
endian machine (or the opposite) that are represented using
more than 1 byte (SET fields with more than 8 members or ENUM
fields with more than 256 constants) will fail to replicate
correctly when using row-based replication.
The reason is that there are no pack() or unpack() functions
for Field_set or Field_enum, which make them rely on Field::pack
and Field::unpack. These functions pack data as strings, but
since Field_set and Field_enum use integral types for
representation, the fields are stored incorrectly on big-endian
machines.
This patch adds Field_enum::pack and Field_enum::unpack
functions that store the integral value correctly in the binary
log even on big-endian machines. Since Field_set inherits from
Field_enum, it will use the same functions for packing and
unpacking the field.
Diffstat (limited to 'sql/field.h')
-rw-r--r-- | sql/field.h | 106 |
1 files changed, 76 insertions, 30 deletions
diff --git a/sql/field.h b/sql/field.h index 7b250c34fe4..d854b78f9a3 100644 --- a/sql/field.h +++ b/sql/field.h @@ -554,6 +554,48 @@ private: { return 0; } protected: + static void handle_int16(uchar *to, const uchar *from, + bool low_byte_first_from, bool low_byte_first_to) + { + int16 val; +#ifdef WORDS_BIGENDIAN + if (low_byte_first_from) + val = sint2korr(from); + else +#endif + shortget(val, from); + +#ifdef WORDS_BIGENDIAN + if (low_byte_first_to) + int2store(to, val); + else +#endif + shortstore(to, val); + } + + static void handle_int24(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 = sint3korr(from); + else +#endif + val= (from[0] << 16) + (from[1] << 8) + from[2]; + +#ifdef WORDS_BIGENDIAN + if (low_byte_first_to) + int2store(to, val); + else +#endif + { + to[0]= 0xFF & (val >> 16); + to[1]= 0xFF & (val >> 8); + to[2]= 0xFF & val; + } + } + /* Helper function to pack()/unpack() int32 values */ @@ -598,6 +640,32 @@ protected: longlongstore(to, val); } + uchar *pack_int16(uchar *to, const uchar *from, bool low_byte_first_to) + { + handle_int16(to, from, table->s->db_low_byte_first, low_byte_first_to); + return to + sizeof(int16); + } + + const uchar *unpack_int16(uchar* to, const uchar *from, + bool low_byte_first_from) + { + handle_int16(to, from, low_byte_first_from, table->s->db_low_byte_first); + return from + sizeof(int16); + } + + uchar *pack_int24(uchar *to, const uchar *from, bool low_byte_first_to) + { + handle_int24(to, from, table->s->db_low_byte_first, low_byte_first_to); + return to + 3; + } + + const uchar *unpack_int24(uchar* to, const uchar *from, + bool low_byte_first_from) + { + handle_int24(to, from, low_byte_first_from, table->s->db_low_byte_first); + return from + 3; + } + 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); @@ -918,41 +986,13 @@ public: virtual uchar *pack(uchar* to, const uchar *from, uint max_length, bool low_byte_first) { - int16 val; -#ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) - val = sint2korr(from); - else -#endif - shortget(val, from); - -#ifdef WORDS_BIGENDIAN - if (low_byte_first) - int2store(to, val); - else -#endif - shortstore(to, val); - return to + sizeof(val); + return pack_int16(to, from, low_byte_first); } virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data, bool low_byte_first) { - int16 val; -#ifdef WORDS_BIGENDIAN - if (low_byte_first) - val = sint2korr(from); - else -#endif - shortget(val, from); - -#ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) - int2store(to, val); - else -#endif - shortstore(to, val); - return from + sizeof(val); + return unpack_int16(to, from, low_byte_first); } }; @@ -1895,6 +1935,12 @@ public: bool has_charset(void) const { return TRUE; } /* enum and set are sorted as integers */ CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; } + + virtual uchar *pack(uchar *to, const uchar *from, + uint max_length, bool low_byte_first); + virtual const uchar *unpack(uchar *to, const uchar *from, + uint param_data, bool low_byte_first); + private: int do_save_field_metadata(uchar *first_byte); uint is_equal(Create_field *new_field); |