List:Commits« Previous MessageNext Message »
From:Luís Soares Date:October 29 2010 12:21pm
Subject:Re: bzr commit into mysql-trunk-bugfixing branch (luis.soares:3288)
Bug#53386
View as plain text  
Hi Mats,

On 10/27/2010 01:55 PM, Mats Kindahl wrote:
> On 10/20/2010 04:45 PM, Luis Soares wrote:
>> #At
> file:///home/lsoares/Workspace/bzr/work/bugfixing/53386/mysql-trunk-bugfixing/ based on
> revid:alfranio.correia@stripped
>>
>>   3288 Luis Soares	2010-10-20
>>        BUG#53386: HA_ERR_CORRUPT_EVENT or debug assertion with different
>>        table on slave
>>
>>        When the number of raw bytes used for a CHAR field exceeds 255
>>        two bytes are actually used while packing the length of the
>>        field. CHAR fields can exceed the raw 255 byte length, for
>>        instance, if using multi-byte character sets.
>>
>>        The problem is that when calculating the raw length of the field,
>>        at unpacking time, only one byte was assumed to be used
>>        always. Therefore, the number of bytes used would not add up,
>>        triggering the assertion.
>>
>>        We fix this, by making the member function that calculates the
>>        raw byte length for a given field to take into account the actual
>>        number of bytes used while packing the field length.
>>       @ mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test
>>          Extended the test case with one based on the bug report entry.
>>

[ snip ]

>>
>> === modified file 'sql/rpl_utility.cc'
>> --- a/sql/rpl_utility.cc	2010-07-16 21:00:50 +0000
>> +++ b/sql/rpl_utility.cc	2010-10-20 14:45:31 +0000
>> @@ -225,9 +225,10 @@ uint32 table_def::calc_field_size(uint c
>>         /*
>>           We are reading the actual size from the master_data record
>>           because this field has the actual lengh stored in the first
>> -        byte.
>> +        one or two bytes.
>>         */
>> -      length= (uint) *master_data + 1;
>> +      uint32 max_length= max_display_length_for_field(MYSQL_TYPE_STRING,
> m_field_metadata[col]);
>> +      length= (uint) (max_length>  255 ? 2 : 1) + *master_data;
>>
>
> If two bytes are used to represent the length, I think you need to read
> two bytes from the master data to compute the length... but you're just
> reading one.

Duh! You are right!

> Shouldn't it be:
>
>      if (max_length>  255)
>          length= *master_data + *(master_data + 1)<<  8 + 2;
>      else
>          length = *master_data + 1;
>
> or
>
>      length = *master_data + (max_length>  255 ? 2 + *(master_data + 1)
>      <<  8 : 1)
>
> whichever you prefer.

I'll go with:

+      length= max_display_length_for_field(MYSQL_TYPE_STRING, m_field_metadata[col]) >
255 ? 2 : 1;
+
+      /* As in Field_string::unpack */
+      length+= ((length == 1) ? *master_data : uint2korr(master_data));


Additionally, I have added one assertion while unpacking a row so
that, in debug builds, we always assert that unpack and
calc_field_size return the same amount of bytes. (and that revealed
another concealed issue - bad assertion when calculating the size
for varchar strings).

Please, find a new patch at: http://lists.mysql.com/commits/122298

Thanks for your valuable comments.

> Just my few cents,
> Mats Kindahl
>
>
>>         DBUG_ASSERT(length != 0);
>>       }
>>       break;
>>
>>
>>
>>
>>
>>
>

Thread
bzr commit into mysql-trunk-bugfixing branch (luis.soares:3288) Bug#53386Luis Soares20 Oct
  • Re: bzr commit into mysql-trunk-bugfixing branch (luis.soares:3288)Bug#53386He Zhenxing27 Oct
  • Re: bzr commit into mysql-trunk-bugfixing branch (luis.soares:3288)Bug#53386Mats Kindahl27 Oct
    • Re: bzr commit into mysql-trunk-bugfixing branch (luis.soares:3288)Bug#53386Luís Soares29 Oct