diff --git a/mysql-test/suite/bugs/r/rpl_bug31583.result b/mysql-test/suite/bugs/r/rpl_bug31583.result new file mode 100644 index 00000000000..a5e38e9b2d8 --- /dev/null +++ b/mysql-test/suite/bugs/r/rpl_bug31583.result @@ -0,0 +1,15 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +CREATE TABLE t1 ( a INT, b INT DEFAULT -3 ); +INSERT INTO t1 VALUES (1, DEFAULT); +UPDATE t1 SET a = 3; +SELECT * FROM t1 ORDER BY a; +a b +3 -3 +SELECT * FROM t1 ORDER BY a; +a b +3 -3 diff --git a/mysql-test/suite/bugs/t/rpl_bug31583.test b/mysql-test/suite/bugs/t/rpl_bug31583.test new file mode 100644 index 00000000000..a8f4a5538ca --- /dev/null +++ b/mysql-test/suite/bugs/t/rpl_bug31583.test @@ -0,0 +1,21 @@ +# +# BUG#31583: 5.1-telco-6.1 -> 5.1.22. Slave returns Error in unknown event + +# This is a problem for any update statement replicating from an old +# server to a new server. The bug consisted of a new slave trying to +# read two column bitmaps, but there is only one available in the old +# format. + +# This test case should be executed replicating from an old server to +# a new server, so make sure you have one handy. + +source include/master-slave.inc; + +CREATE TABLE t1 ( a INT, b INT DEFAULT -3 ); + +INSERT INTO t1 VALUES (1, DEFAULT); +UPDATE t1 SET a = 3; +SELECT * FROM t1 ORDER BY a; +sync_slave_with_master; +SELECT * FROM t1 ORDER BY a; + diff --git a/sql/log_event.cc b/sql/log_event.cc index d3b0f7ed3b4..c7963fe803a 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -490,6 +490,9 @@ const char* Log_event::get_type_str() case USER_VAR_EVENT: return "User var"; case FORMAT_DESCRIPTION_EVENT: return "Format_desc"; case TABLE_MAP_EVENT: return "Table_map"; + case PRE_GA_WRITE_ROWS_EVENT: return "Write_rows_event_old"; + case PRE_GA_UPDATE_ROWS_EVENT: return "Update_rows_event_old"; + case PRE_GA_DELETE_ROWS_EVENT: return "Delete_rows_event_old"; case WRITE_ROWS_EVENT: return "Write_rows"; case UPDATE_ROWS_EVENT: return "Update_rows"; case DELETE_ROWS_EVENT: return "Delete_rows"; @@ -1015,6 +1018,8 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len, DBUG_ENTER("Log_event::read_log_event(char*,...)"); DBUG_ASSERT(description_event != 0); DBUG_PRINT("info", ("binlog_version: %d", description_event->binlog_version)); + DBUG_DUMP("data", (unsigned char*) buf, event_len); + /* Check the integrity */ if (event_len < EVENT_LEN_OFFSET || buf[EVENT_TYPE_OFFSET] >= ENUM_END_EVENT || diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index b16af43f24e..12c3b2a6dc3 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -1317,6 +1317,7 @@ Old_rows_log_event::Old_rows_log_event(const char *buf, uint event_len, post_header_len)); const char *post_start= buf + common_header_len; + DBUG_DUMP("post_header", (uchar*) post_start, post_header_len); post_start+= RW_MAPID_OFFSET; if (post_header_len == 6) { @@ -1358,38 +1359,11 @@ Old_rows_log_event::Old_rows_log_event(const char *buf, uint event_len, DBUG_VOID_RETURN; } - m_cols_ai.bitmap= m_cols.bitmap; /* See explanation in is_valid() */ - - if (event_type == PRE_GA_UPDATE_ROWS_EVENT) - { - DBUG_PRINT("debug", ("Reading from %p", ptr_after_width)); - - /* if bitmap_init fails, caught in is_valid() */ - if (likely(!bitmap_init(&m_cols_ai, - m_width <= sizeof(m_bitbuf_ai)*8 ? m_bitbuf_ai : NULL, - m_width, - false))) - { - DBUG_PRINT("debug", ("Reading from %p", ptr_after_width)); - memcpy(m_cols_ai.bitmap, ptr_after_width, (m_width + 7) / 8); - create_last_word_mask(&m_cols_ai); - ptr_after_width+= (m_width + 7) / 8; - DBUG_DUMP("m_cols_ai", (uchar*) m_cols_ai.bitmap, - no_bytes_in_map(&m_cols_ai)); - } - else - { - // Needed because bitmap_init() does not set it to null on failure - m_cols_ai.bitmap= 0; - DBUG_VOID_RETURN; - } - } - const uchar* const ptr_rows_data= (const uchar*) ptr_after_width; - size_t const data_size= event_len - (ptr_rows_data - (const uchar *) buf); DBUG_PRINT("info",("m_table_id: %lu m_flags: %d m_width: %lu data_size: %lu", m_table_id, m_flags, m_width, (ulong) data_size)); + DBUG_DUMP("rows_data", (uchar*) ptr_rows_data, data_size); m_rows_buf= (uchar*) my_malloc(data_size, MYF(MY_WME)); if (likely((bool)m_rows_buf)) @@ -1419,24 +1393,18 @@ Old_rows_log_event::~Old_rows_log_event() int Old_rows_log_event::get_data_size() { - int const type_code= get_type_code(); - uchar buf[sizeof(m_width)+1]; uchar *end= net_store_length(buf, (m_width + 7) / 8); DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", return 6 + no_bytes_in_map(&m_cols) + (end - buf) + - (type_code == PRE_GA_UPDATE_ROWS_EVENT ? no_bytes_in_map(&m_cols_ai) : 0) + (m_rows_cur - m_rows_buf);); int data_size= ROWS_HEADER_LEN; data_size+= no_bytes_in_map(&m_cols); data_size+= end - buf; - if (type_code == PRE_GA_UPDATE_ROWS_EVENT) - data_size+= no_bytes_in_map(&m_cols_ai); - data_size+= (m_rows_cur - m_rows_buf); - return data_size; + return data_size; } @@ -2011,16 +1979,6 @@ bool Old_rows_log_event::write_data_body(IO_CACHE*file) DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols)); res= res || my_b_safe_write(file, (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols)); - /* - TODO[refactor write]: Remove the "down cast" here (and elsewhere). - */ - if (get_type_code() == PRE_GA_UPDATE_ROWS_EVENT) - { - DBUG_DUMP("m_cols_ai", (uchar*) m_cols_ai.bitmap, - no_bytes_in_map(&m_cols_ai)); - res= res || my_b_safe_write(file, (uchar*) m_cols_ai.bitmap, - no_bytes_in_map(&m_cols_ai)); - } DBUG_DUMP("rows", m_rows_buf, data_size); res= res || my_b_safe_write(file, m_rows_buf, (size_t) data_size); @@ -2831,38 +2789,10 @@ Update_rows_log_event_old::Update_rows_log_event_old(THD *thd_arg, // This constructor should not be reached. assert(0); - - init(cols); -} - - -void Update_rows_log_event_old::init(MY_BITMAP const *cols) -{ - /* if bitmap_init fails, caught in is_valid() */ - if (likely(!bitmap_init(&m_cols_ai, - m_width <= sizeof(m_bitbuf_ai)*8 ? m_bitbuf_ai : NULL, - m_width, - false))) - { - /* Cols can be zero if this is a dummy binrows event */ - if (likely(cols != NULL)) - { - memcpy(m_cols_ai.bitmap, cols->bitmap, no_bytes_in_map(cols)); - create_last_word_mask(&m_cols_ai); - } - } } #endif /* !defined(MYSQL_CLIENT) */ -Update_rows_log_event_old::~Update_rows_log_event_old() -{ - if (m_cols_ai.bitmap == m_bitbuf_ai) // no my_malloc happened - m_cols_ai.bitmap= 0; // so no my_free in bitmap_free - bitmap_free(&m_cols_ai); // To pair with bitmap_init(). -} - - /* Constructor used by slave to read the event from the binary log. */ diff --git a/sql/log_event_old.h b/sql/log_event_old.h index efb2be29ee4..719802a80fb 100644 --- a/sql/log_event_old.h +++ b/sql/log_event_old.h @@ -175,14 +175,6 @@ protected: ulong m_table_id; /* Table ID */ MY_BITMAP m_cols; /* Bitmap denoting columns available */ ulong m_width; /* The width of the columns bitmap */ - /* - Bitmap for columns available in the after image, if present. These - fields are only available for Update_rows events. Observe that the - width of both the before image COLS vector and the after image - COLS vector is the same: the number of columns of the table on the - master. - */ - MY_BITMAP m_cols_ai; ulong m_master_reclength; /* Length of record on master side */ @@ -442,12 +434,8 @@ public: Update_rows_log_event_old(THD*, TABLE*, ulong table_id, MY_BITMAP const *cols, bool is_transactional); - - void init(MY_BITMAP const *cols); #endif - virtual ~Update_rows_log_event_old(); - #ifdef HAVE_REPLICATION Update_rows_log_event_old(const char *buf, uint event_len, const Format_description_log_event *description_event); @@ -466,11 +454,6 @@ public: } #endif - virtual bool is_valid() const - { - return Old_rows_log_event::is_valid() && m_cols_ai.bitmap; - } - protected: #ifdef MYSQL_CLIENT void print(FILE *file, PRINT_EVENT_INFO *print_event_info);