diff options
author | Luis Soares <luis.soares@sun.com> | 2010-01-21 17:20:24 +0000 |
---|---|---|
committer | Luis Soares <luis.soares@sun.com> | 2010-01-21 17:20:24 +0000 |
commit | 04ac86e366b8c95ebeb2ef2cbb7757724124a78d (patch) | |
tree | 3597ed3eef2a70d2e7de4980cbd95909097dbdbc /sql | |
parent | 22cff392741e4bdce19d53a57fa2530a7eac9894 (diff) | |
download | mariadb-git-04ac86e366b8c95ebeb2ef2cbb7757724124a78d.tar.gz |
BUG#49481: RBR: MyISAM and bit fields may cause slave to stop on delete:
cant find record
Some engines return data for the record. Despite the fact that
the null bit is set for some fields, their old value may still in
the row. This can happen when unpacking an AI from the binlog on
top of a previous record in which a field is set to NULL, which
previously contained a value. Ultimately, this may cause the
comparison of records to fail when the slave is doing an index or
range scan.
We fix this by deploying a call to reset() for each field that is
set to null while unpacking a row from the binary log.
Furthermore, we also add mixed mode test case to cover the
scenario where updating and setting a field to null through a
Query event and later searching it through a rows event will
succeed.
Finally, we also change the reset() method, from Field_bit class,
so that it takes into account bits stored among the null bits and
not only the ones stored in the record.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.h | 7 | ||||
-rw-r--r-- | sql/rpl_record.cc | 11 |
2 files changed, 17 insertions, 1 deletions
diff --git a/sql/field.h b/sql/field.h index ae074cc1a30..55604193687 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1926,7 +1926,12 @@ public: uint32 max_display_length() { return field_length; } uint size_of() const { return sizeof(*this); } Item_result result_type () const { return INT_RESULT; } - int reset(void) { bzero(ptr, bytes_in_rec); return 0; } + int reset(void) { + bzero(ptr, bytes_in_rec); + if (bit_ptr && (bit_len > 0)) // reset odd bits among null bits + clr_rec_bits(bit_ptr, bit_ofs, bit_len); + return 0; + } int store(const char *to, uint length, CHARSET_INFO *charset); int store(double nr); int store(longlong nr, bool unsigned_val); diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 8e80620dd2c..f6bf57cde3e 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -231,6 +231,17 @@ unpack_row(Relay_log_info const *rli, { DBUG_PRINT("debug", ("Was NULL; null mask: 0x%x; null bits: 0x%x", null_mask, null_bits)); + /** + Calling reset just in case one is unpacking on top a + record with data. + + This could probably go into set_null() but doing so, + (i) triggers assertion in other parts of the code at + the moment; (ii) it would make us reset the field, + always when setting null, which right now doesn't seem + needed anywhere else except here. + */ + f->reset(); f->set_null(); } else |