Handle null bits for record comparison in row events the same way as in handler::calculate_checksum(), forcing bits that can be undefined to 1. These bits are the trailing unused bits, as well as the first bit for tables not using HA_OPTION_PACK_RECORD. The csv storage engine leaves these bits at 0, while the row-based replication has them set to 1, which otherwise cause can't find record error. Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org> --- mysql-test/suite/rpl/r/rpl_csv.result | 13 +++++++++++ mysql-test/suite/rpl/t/rpl_csv.test | 16 ++++++++++++++ sql/log_event_server.cc | 32 ++++++++++++++++++--------- 3 files changed, 51 insertions(+), 10 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_csv.result create mode 100644 mysql-test/suite/rpl/t/rpl_csv.test diff --git a/mysql-test/suite/rpl/r/rpl_csv.result b/mysql-test/suite/rpl/r/rpl_csv.result new file mode 100644 index 00000000000..39b78186df3 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_csv.result @@ -0,0 +1,13 @@ +include/master-slave.inc +[connection master] +*** MDEV-35233: RBR does not work with CSV tables +CREATE TABLE t (a INT NOT NULL) ENGINE=CSV; +INSERT INTO t VALUES (1),(2); +DELETE FROM t where a=1; +connection slave; +SELECT * FROM t ORDER BY a; +a +2 +connection master; +DROP TABLE t; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_csv.test b/mysql-test/suite/rpl/t/rpl_csv.test new file mode 100644 index 00000000000..82f745d549e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_csv.test @@ -0,0 +1,16 @@ +--source include/have_csv.inc +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +--echo *** MDEV-35233: RBR does not work with CSV tables +CREATE TABLE t (a INT NOT NULL) ENGINE=CSV; +INSERT INTO t VALUES (1),(2); +DELETE FROM t where a=1; + +--sync_slave_with_master +SELECT * FROM t ORDER BY a; + +# Cleanup +--connection master +DROP TABLE t; +--source include/rpl_end.inc diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 8b976ba5e14..d5773687e82 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -7089,6 +7089,14 @@ static bool record_compare(TABLE *table, bool vers_from_plain= false) bool result= false; bool all_values_set= bitmap_is_set_all(&table->has_value_set); + if (table->s->null_bytes > 0) + { + table->record[0][table->s->null_bytes - 1]|= + 256U - (1U << table->s->last_null_bit_pos); + if (!(table->s->db_create_options & HA_OPTION_PACK_RECORD)) + table->record[0][0] |= 1; + } + /** Compare full record only if: - all fields were given values @@ -7552,6 +7560,20 @@ int Rows_log_event::find_row(rpl_group_info *rgi) // We can't use position() - try other methods. + /* + We need to set the null bytes to ensure that the filler bit are + all set when returning. There are storage engines that just set + the necessary bits on the bytes and don't set the filler bits + correctly. + */ + if (table->s->null_bytes > 0) + { + table->record[0][table->s->null_bytes - 1]|= + 256U - (1U << table->s->last_null_bit_pos); + if (!(table->s->db_create_options & HA_OPTION_PACK_RECORD)) + table->record[0][0] |= 1; + } + /* Save copy of the record in table->record[1]. It might be needed later if linear search is used to find exact match. @@ -7588,16 +7610,6 @@ int Rows_log_event::find_row(rpl_group_info *rgi) DBUG_DUMP("key data", m_key, m_key_info->key_length); #endif - /* - We need to set the null bytes to ensure that the filler bit are - all set when returning. There are storage engines that just set - the necessary bits on the bytes and don't set the filler bits - correctly. - */ - if (table->s->null_bytes > 0) - table->record[0][table->s->null_bytes - 1]|= - 256U - (1U << table->s->last_null_bit_pos); - const enum ha_rkey_function find_flag= m_usable_key_parts == m_key_info->user_defined_key_parts ? HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT; -- 2.39.5