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.cc | |
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.cc')
-rw-r--r-- | sql/field.cc | 53 |
1 files changed, 45 insertions, 8 deletions
diff --git a/sql/field.cc b/sql/field.cc index 728cd7e4090..b83b2bfae5a 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7725,12 +7725,6 @@ void Field_blob::sql_type(String &res) const uchar *Field_blob::pack(uchar *to, const uchar *from, uint max_length, bool low_byte_first) { - DBUG_ENTER("Field_blob::pack"); - DBUG_PRINT("enter", ("to: 0x%lx; from: 0x%lx;" - " max_length: %u; low_byte_first: %d", - (ulong) to, (ulong) from, - max_length, low_byte_first)); - DBUG_DUMP("record", from, table->s->reclength); uchar *save= ptr; ptr= (uchar*) from; uint32 length=get_length(); // Length of from string @@ -7751,8 +7745,7 @@ uchar *Field_blob::pack(uchar *to, const uchar *from, memcpy(to+packlength, from,length); } ptr=save; // Restore org row pointer - DBUG_DUMP("packed", to, packlength + length); - DBUG_RETURN(to+packlength+length); + return to+packlength+length; } @@ -8396,6 +8389,50 @@ uint Field_enum::is_equal(Create_field *new_field) } +uchar *Field_enum::pack(uchar *to, const uchar *from, + uint max_length, bool low_byte_first) +{ + DBUG_ENTER("Field_enum::pack"); + DBUG_PRINT("debug", ("packlength: %d", packlength)); + DBUG_DUMP("from", from, packlength); + + switch (packlength) + { + case 1: + *to = *from; + DBUG_RETURN(to + 1); + case 2: DBUG_RETURN(pack_int16(to, from, low_byte_first)); + case 3: DBUG_RETURN(pack_int24(to, from, low_byte_first)); + case 4: DBUG_RETURN(pack_int32(to, from, low_byte_first)); + case 8: DBUG_RETURN(pack_int64(to, from, low_byte_first)); + default: + DBUG_ASSERT(0); + } +} + +const uchar *Field_enum::unpack(uchar *to, const uchar *from, + uint param_data, bool low_byte_first) +{ + DBUG_ENTER("Field_enum::unpack"); + DBUG_PRINT("debug", ("packlength: %d", packlength)); + DBUG_DUMP("from", from, packlength); + + switch (packlength) + { + case 1: + *to = *from; + DBUG_RETURN(from + 1); + + case 2: DBUG_RETURN(unpack_int16(to, from, low_byte_first)); + case 3: DBUG_RETURN(unpack_int24(to, from, low_byte_first)); + case 4: DBUG_RETURN(unpack_int32(to, from, low_byte_first)); + case 8: DBUG_RETURN(unpack_int64(to, from, low_byte_first)); + default: + DBUG_ASSERT(0); + } +} + + /** @return returns 1 if the fields are equally defined |