diff options
-rw-r--r-- | include/my_base.h | 4 | ||||
-rw-r--r-- | mysql-test/extra/rpl_tests/rpl_row_tabledefs.test | 6 | ||||
-rw-r--r-- | mysql-test/suite/binlog/r/binlog_old_versions.result | 10 | ||||
-rw-r--r-- | mysql-test/suite/binlog/std_data/binlog_old_version_4_1.000001 | bin | 0 -> 149436 bytes | |||
-rw-r--r-- | mysql-test/suite/binlog/t/binlog_old_versions.test | 15 | ||||
-rw-r--r-- | mysql-test/suite/bugs/data/rpl_bug12691.dat | 3 | ||||
-rw-r--r-- | mysql-test/suite/bugs/r/rpl_bug12691.result | 34 | ||||
-rw-r--r-- | mysql-test/suite/bugs/t/rpl_bug12691.test | 53 | ||||
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_loaddata_map.result | 2 | ||||
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result | 16 | ||||
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result | 16 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_loaddata_map.test | 7 | ||||
-rw-r--r-- | sql/log_event.cc | 141 | ||||
-rw-r--r-- | sql/log_event.h | 14 | ||||
-rw-r--r-- | sql/log_event_old.cc | 4 | ||||
-rw-r--r-- | sql/rpl_record.cc | 16 | ||||
-rw-r--r-- | sql/rpl_record.h | 3 | ||||
-rw-r--r-- | sql/share/errmsg.txt | 2 | ||||
-rw-r--r-- | sql/sql_binlog.cc | 7 |
19 files changed, 269 insertions, 84 deletions
diff --git a/include/my_base.h b/include/my_base.h index 947f7695215..4f552fa5fe0 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -419,7 +419,9 @@ enum ha_base_keytype { statement */ #define HA_ERR_CORRUPT_EVENT 171 /* The event was corrupt, leading to illegal data being read */ -#define HA_ERR_LAST 171 /*Copy last error nr.*/ +#define HA_ERR_ROWS_EVENT_APPLY 172 /* The event could not be processed + no other hanlder error happened */ +#define HA_ERR_LAST 172 /*Copy last error nr.*/ /* Add error numbers before HA_ERR_LAST and change it accordingly. */ #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) diff --git a/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test b/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test index b5795cf525d..0e391cb0f37 100644 --- a/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test +++ b/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test @@ -46,7 +46,7 @@ ALTER TABLE t1_bit ALTER TABLE t1_char ADD x CHAR(20) DEFAULT 'Just a test'; # ... and add one non-nullable INT column last in table 't1_text' # with no default, -ALTER TABLE t1_nodef ADD x INT NOT NULL; +ALTER TABLE t1_nodef ADD x INT NOT NULL, ADD y INT NOT NULL, ADD z INT NOT NULL; # ... and remove the last column in t2 ALTER TABLE t2 DROP b; # ... change the type of the single column in table 't4' @@ -222,8 +222,8 @@ sync_slave_with_master; --echo **** On Slave **** connection slave; -INSERT INTO t1_nodef VALUES (1,2,3); -INSERT INTO t1_nodef VALUES (2,4,6); +INSERT INTO t1_nodef VALUES (1,2,3,4,5); +INSERT INTO t1_nodef VALUES (2,4,6,8,10); --echo **** On Master **** connection master; diff --git a/mysql-test/suite/binlog/r/binlog_old_versions.result b/mysql-test/suite/binlog/r/binlog_old_versions.result index a514f9278a6..77289252b4c 100644 --- a/mysql-test/suite/binlog/r/binlog_old_versions.result +++ b/mysql-test/suite/binlog/r/binlog_old_versions.result @@ -29,6 +29,16 @@ SELECT COUNT(*) FROM t3; COUNT(*) 17920 DROP TABLE t1, t2, t3; +==== Read binlog from version 4.1 ==== +SELECT * FROM t1 ORDER BY a; +a b +0 last_insert_id +4 four +190243 random +SELECT COUNT(*) FROM t3; +COUNT(*) +17920 +DROP TABLE t1, t3; ==== Read binlog from alcatel tree (mysql-5.1-wl2325-5.0-drop6) ==== SELECT * FROM t1 ORDER BY a; a b diff --git a/mysql-test/suite/binlog/std_data/binlog_old_version_4_1.000001 b/mysql-test/suite/binlog/std_data/binlog_old_version_4_1.000001 Binary files differnew file mode 100644 index 00000000000..66db9668d46 --- /dev/null +++ b/mysql-test/suite/binlog/std_data/binlog_old_version_4_1.000001 diff --git a/mysql-test/suite/binlog/t/binlog_old_versions.test b/mysql-test/suite/binlog/t/binlog_old_versions.test index 2d56ebd588d..465ca3be8ae 100644 --- a/mysql-test/suite/binlog/t/binlog_old_versions.test +++ b/mysql-test/suite/binlog/t/binlog_old_versions.test @@ -52,6 +52,21 @@ SELECT COUNT(*) FROM t3; DROP TABLE t1, t2, t3; +--echo ==== Read binlog from version 4.1 ==== + +# In this version, neither row-based binlogging nor Xid events +# existed, so the binlog was generated without the "row-based tests" +# part and the "get xid event" part, and it does not create table t2. + +# Read binlog. +--exec $MYSQL_BINLOG suite/binlog/std_data/binlog_old_version_4_1.000001 | $MYSQL +# Show result. +SELECT * FROM t1 ORDER BY a; +SELECT COUNT(*) FROM t3; +# Reset. +DROP TABLE t1, t3; + + --echo ==== Read binlog from alcatel tree (mysql-5.1-wl2325-5.0-drop6) ==== # In this version, it was not possible to switch between row-based and diff --git a/mysql-test/suite/bugs/data/rpl_bug12691.dat b/mysql-test/suite/bugs/data/rpl_bug12691.dat new file mode 100644 index 00000000000..de980441c3a --- /dev/null +++ b/mysql-test/suite/bugs/data/rpl_bug12691.dat @@ -0,0 +1,3 @@ +a +b +c diff --git a/mysql-test/suite/bugs/r/rpl_bug12691.result b/mysql-test/suite/bugs/r/rpl_bug12691.result new file mode 100644 index 00000000000..69d5e8009b0 --- /dev/null +++ b/mysql-test/suite/bugs/r/rpl_bug12691.result @@ -0,0 +1,34 @@ +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; + +**** On Master **** +CREATE TABLE t1 (b CHAR(10)); + +**** On Slave **** +STOP SLAVE; + +**** On Master **** +LOAD DATA INFILE FILENAME +SELECT COUNT(*) FROM t1; +COUNT(*) +3 +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Format_desc 1 # Server ver: # +master-bin.000001 # Query 1 # use `test`; CREATE TABLE t1 (b CHAR(10)) +master-bin.000001 # Begin_load_query 1 # ;file_id=#;block_len=# +master-bin.000001 # Execute_load_query 1 # use `test`; LOAD DATA INFILE FILENAME ;file_id=# + +**** On Slave **** +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; +SELECT COUNT(*) FROM t1; +COUNT(*) +0 + +**** On Master **** +DROP TABLE t1; diff --git a/mysql-test/suite/bugs/t/rpl_bug12691.test b/mysql-test/suite/bugs/t/rpl_bug12691.test new file mode 100644 index 00000000000..b29c85584a5 --- /dev/null +++ b/mysql-test/suite/bugs/t/rpl_bug12691.test @@ -0,0 +1,53 @@ +# Bug#12691: Exec_master_log_pos corrupted with SQL_SLAVE_SKIP_COUNTER +# Date: 01/31/2008 +# Added: Serge Kozlov <skozlov@mysql.com> + +--source include/master-slave.inc +--connection master +--source include/have_binlog_format_mixed_or_statement.inc + +--echo +--echo **** On Master **** +CREATE TABLE t1 (b CHAR(10)); +--echo +--echo **** On Slave **** +--sync_slave_with_master +STOP SLAVE; +--source include/wait_for_slave_to_stop.inc + +--connection master + +--echo +--echo **** On Master **** +--exec cp $MYSQL_TEST_DIR/suite/bugs/data/rpl_bug12691.dat $MYSQLTEST_VARDIR/tmp/ +--echo LOAD DATA INFILE FILENAME +--disable_query_log +--eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/rpl_bug12691.dat' INTO TABLE t1 FIELDS TERMINATED BY '|' +--enable_query_log +--remove_file $MYSQLTEST_VARDIR/tmp/rpl_bug12691.dat + +SELECT COUNT(*) FROM t1; + +--replace_column 2 # 5 # +--replace_regex /Server ver: .+/Server ver: #/ /table_id: [0-9]+/table_id: #/ /COMMIT.+xid=[0-9]+.+/#/ /file_id=[0-9]+/file_id=#/ /block_len=[0-9]+/block_len=#/ /'.+'/FILENAME/ +SHOW BINLOG EVENTS; + +--save_master_pos + +--connection slave +--echo +--echo **** On Slave **** +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; +--source include/wait_for_slave_to_start.inc +--sync_with_master + +SELECT COUNT(*) FROM t1; + +# Clean up +--connection master +--echo +--echo **** On Master **** +DROP TABLE t1; +--sync_slave_with_master + diff --git a/mysql-test/suite/rpl/r/rpl_loaddata_map.result b/mysql-test/suite/rpl/r/rpl_loaddata_map.result index e6ddc1ebedc..3809584c900 100644 --- a/mysql-test/suite/rpl/r/rpl_loaddata_map.result +++ b/mysql-test/suite/rpl/r/rpl_loaddata_map.result @@ -12,7 +12,7 @@ load data infile 'MYSQLTEST_VARDIR/tmp/bug30435_5k.txt' into table t2; select count(*) from t2 /* 5 000 */; count(*) 5000 -show binlog events in 'master-bin.000002' from 106; +show binlog events in 'master-bin.000002' from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000002 106 Query 1 # use `test`; create table t2 (id int not null primary key auto_increment) master-bin.000002 229 Begin_load_query 1 # ;file_id=#;block_len=8192 diff --git a/mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result b/mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result index 6859a406b16..e81d4f7454e 100644 --- a/mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result +++ b/mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result @@ -26,7 +26,7 @@ ADD x BIT(3) DEFAULT b'011', ADD y BIT(5) DEFAULT b'10101', ADD z BIT(2) DEFAULT b'10'; ALTER TABLE t1_char ADD x CHAR(20) DEFAULT 'Just a test'; -ALTER TABLE t1_nodef ADD x INT NOT NULL; +ALTER TABLE t1_nodef ADD x INT NOT NULL, ADD y INT NOT NULL, ADD z INT NOT NULL; ALTER TABLE t2 DROP b; ALTER TABLE t4 MODIFY a FLOAT; ALTER TABLE t5 MODIFY b FLOAT; @@ -393,8 +393,8 @@ INSERT INTO t1_nodef VALUES (1,2); INSERT INTO t1_nodef VALUES (2,4); SET SQL_LOG_BIN=1; **** On Slave **** -INSERT INTO t1_nodef VALUES (1,2,3); -INSERT INTO t1_nodef VALUES (2,4,6); +INSERT INTO t1_nodef VALUES (1,2,3,4,5); +INSERT INTO t1_nodef VALUES (2,4,6,8,10); **** On Master **** UPDATE t1_nodef SET b=2*b WHERE a=1; SELECT * FROM t1_nodef ORDER BY a; @@ -403,9 +403,9 @@ a b 2 4 **** On Slave **** SELECT * FROM t1_nodef ORDER BY a; -a b x -1 4 3 -2 4 6 +a b x y z +1 4 3 4 5 +2 4 6 8 10 **** On Master **** DELETE FROM t1_nodef WHERE a=2; SELECT * FROM t1_nodef ORDER BY a; @@ -413,8 +413,8 @@ a b 1 4 **** On Slave **** SELECT * FROM t1_nodef ORDER BY a; -a b x -1 4 3 +a b x y z +1 4 3 4 5 **** Cleanup **** DROP TABLE IF EXISTS t1_int,t1_bit,t1_char,t1_nodef; DROP TABLE IF EXISTS t2,t3,t4,t5,t6,t7,t8,t9; diff --git a/mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result b/mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result index 17b2a2f7b52..a6834be5a86 100644 --- a/mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result +++ b/mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result @@ -26,7 +26,7 @@ ADD x BIT(3) DEFAULT b'011', ADD y BIT(5) DEFAULT b'10101', ADD z BIT(2) DEFAULT b'10'; ALTER TABLE t1_char ADD x CHAR(20) DEFAULT 'Just a test'; -ALTER TABLE t1_nodef ADD x INT NOT NULL; +ALTER TABLE t1_nodef ADD x INT NOT NULL, ADD y INT NOT NULL, ADD z INT NOT NULL; ALTER TABLE t2 DROP b; ALTER TABLE t4 MODIFY a FLOAT; ALTER TABLE t5 MODIFY b FLOAT; @@ -393,8 +393,8 @@ INSERT INTO t1_nodef VALUES (1,2); INSERT INTO t1_nodef VALUES (2,4); SET SQL_LOG_BIN=1; **** On Slave **** -INSERT INTO t1_nodef VALUES (1,2,3); -INSERT INTO t1_nodef VALUES (2,4,6); +INSERT INTO t1_nodef VALUES (1,2,3,4,5); +INSERT INTO t1_nodef VALUES (2,4,6,8,10); **** On Master **** UPDATE t1_nodef SET b=2*b WHERE a=1; SELECT * FROM t1_nodef ORDER BY a; @@ -403,9 +403,9 @@ a b 2 4 **** On Slave **** SELECT * FROM t1_nodef ORDER BY a; -a b x -1 4 3 -2 4 6 +a b x y z +1 4 3 4 5 +2 4 6 8 10 **** On Master **** DELETE FROM t1_nodef WHERE a=2; SELECT * FROM t1_nodef ORDER BY a; @@ -413,8 +413,8 @@ a b 1 4 **** On Slave **** SELECT * FROM t1_nodef ORDER BY a; -a b x -1 4 3 +a b x y z +1 4 3 4 5 **** Cleanup **** DROP TABLE IF EXISTS t1_int,t1_bit,t1_char,t1_nodef; DROP TABLE IF EXISTS t2,t3,t4,t5,t6,t7,t8,t9; diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_map.test b/mysql-test/suite/rpl/t/rpl_loaddata_map.test index 3d6f09844b6..6a8378c8fdc 100644 --- a/mysql-test/suite/rpl/t/rpl_loaddata_map.test +++ b/mysql-test/suite/rpl/t/rpl_loaddata_map.test @@ -7,6 +7,7 @@ # BUG#33413 show binlog events fails if binlog has event size of close # to max_allowed_packet +source include/have_binlog_format_mixed_or_statement.inc; source include/master-slave.inc; source include/have_innodb.inc; source include/have_binlog_format_mixed_or_statement.inc; @@ -35,9 +36,9 @@ select count(*) from t2 /* 5 000 */; # the binglog will show fragmented Append_block events --let $binlog_start=106 ---replace_column 5 # ---replace_regex /\/\* xid=.* \*\//\/* XID *\// /file_id=[0-9]+/file_id=#/ ---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_column 2 # 4 # 5 # +--replace_regex /\/\* xid=.* \*\//\/* XID *\// /file_id=[0-9]+/file_id=#/ /block_len=[0-9]+/block_len=#/ +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR $binlog_start <binlog_start> --eval show binlog events in 'master-bin.000002' from $binlog_start diff --git a/sql/log_event.cc b/sql/log_event.cc index df0d1e8a020..62e04336d29 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -99,27 +99,51 @@ static const char *HA_ERR(int i) case HA_ERR_RECORD_IS_THE_SAME: return "HA_ERR_RECORD_IS_THE_SAME"; case HA_ERR_LOGGING_IMPOSSIBLE: return "HA_ERR_LOGGING_IMPOSSIBLE"; case HA_ERR_CORRUPT_EVENT: return "HA_ERR_CORRUPT_EVENT"; + case HA_ERR_ROWS_EVENT_APPLY : return "HA_ERR_ROWS_EVENT_APPLY"; } return 0; } /** - macro to call from different branches of Rows_log_event::do_apply_event + Error reporting facility for Rows_log_event::do_apply_event + + @param level error, warning or info + @param ha_error HA_ERR_ code + @param rli pointer to the active Relay_log_info instance + @param thd pointer to the slave thread's thd + @param table pointer to the event's table object + @param type the type of the event + @param log_name the master binlog file name + @param pos the master binlog file pos (the next after the event) + */ static void inline slave_rows_error_report(enum loglevel level, int ha_error, Relay_log_info const *rli, THD *thd, TABLE *table, const char * type, const char *log_name, ulong pos) { - const char *handler_error= HA_ERR(ha_error); + const char *handler_error= HA_ERR(ha_error); + char buff[MAX_SLAVE_ERRMSG], *slider; + const char *buff_end= buff + sizeof(buff); + uint len; + List_iterator_fast<MYSQL_ERROR> it(thd->warn_list); + MYSQL_ERROR *err; + buff[0]= 0; + + for (err= it++, slider= buff; err && slider < buff_end - 1; + slider += len, err= it++) + { + len= my_snprintf(slider, buff_end - slider, + " %s, Error_code: %d;", err->msg, err->code); + } + rli->report(level, thd->net.client_last_errno, "Could not execute %s event on table %s.%s;" - "%s%s handler error %s; " + "%s handler error %s; " "the event's master log %s, end_log_pos %lu", type, table->s->db.str, table->s->table_name.str, - thd->net.client_last_error[0] != 0 ? thd->net.client_last_error : "", - thd->net.client_last_error[0] != 0 ? ";" : "", + buff, handler_error == NULL? "<unknown>" : handler_error, log_name, pos); } @@ -212,9 +236,9 @@ uint debug_not_change_ts_if_art_event= 1; // bug#29309 simulation */ #ifdef MYSQL_CLIENT -static void pretty_print_str(IO_CACHE* cache, char* str, int len) +static void pretty_print_str(IO_CACHE* cache, const char* str, int len) { - char* end = str + len; + const char* end = str + len; my_b_printf(cache, "\'"); while (str < end) { @@ -277,9 +301,9 @@ inline int ignored_error_code(int err_code) */ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -static char *pretty_print_str(char *packet, char *str, int len) +static char *pretty_print_str(char *packet, const char *str, int len) { - char *end= str + len; + const char *end= str + len; char *pos= packet; *pos++= '\''; while (str < end) @@ -385,7 +409,7 @@ static void cleanup_load_tmpdir() write_str() */ -static bool write_str(IO_CACHE *file, char *str, uint length) +static bool write_str(IO_CACHE *file, const char *str, uint length) { uchar tmp[1]; tmp[0]= (uchar) length; @@ -2957,18 +2981,63 @@ Format_description_log_event(const char* buf, If post_header_len is null, it means malloc failed, and is_valid will fail, so there is no need to do anything. - The trees which have wrong event id's are: - mysql-5.1-wl2325-5.0-drop6p13-alpha, mysql-5.1-wl2325-5.0-drop6, - mysql-5.1-wl2325-5.0, mysql-5.1-wl2325-no-dd (`grep -C2 - BEGIN_LOAD_QUERY_EVENT /home/bk/ * /sql/log_event.h`). The - corresponding version (`grep mysql, configure.in` in those trees) - strings are 5.2.2-a_drop6p13-alpha, 5.2.2-a_drop6p13c, - 5.1.5-a_drop5p20, 5.1.2-a_drop5p5. + The trees in which events have wrong id's are: + + mysql-5.1-wl1012.old mysql-5.1-wl2325-5.0-drop6p13-alpha + mysql-5.1-wl2325-5.0-drop6 mysql-5.1-wl2325-5.0 + mysql-5.1-wl2325-no-dd + + (this was found by grepping for two lines in sequence where the + first matches "FORMAT_DESCRIPTION_EVENT," and the second matches + "TABLE_MAP_EVENT," in log_event.h in all trees) + + In these trees, the following server_versions existed since + TABLE_MAP_EVENT was introduced: + + 5.1.1-a_drop5p3 5.1.1-a_drop5p4 5.1.1-alpha + 5.1.2-a_drop5p10 5.1.2-a_drop5p11 5.1.2-a_drop5p12 + 5.1.2-a_drop5p13 5.1.2-a_drop5p14 5.1.2-a_drop5p15 + 5.1.2-a_drop5p16 5.1.2-a_drop5p16b 5.1.2-a_drop5p16c + 5.1.2-a_drop5p17 5.1.2-a_drop5p4 5.1.2-a_drop5p5 + 5.1.2-a_drop5p6 5.1.2-a_drop5p7 5.1.2-a_drop5p8 + 5.1.2-a_drop5p9 5.1.3-a_drop5p17 5.1.3-a_drop5p17b + 5.1.3-a_drop5p17c 5.1.4-a_drop5p18 5.1.4-a_drop5p19 + 5.1.4-a_drop5p20 5.1.4-a_drop6p0 5.1.4-a_drop6p1 + 5.1.4-a_drop6p2 5.1.5-a_drop5p20 5.2.0-a_drop6p3 + 5.2.0-a_drop6p4 5.2.0-a_drop6p5 5.2.0-a_drop6p6 + 5.2.1-a_drop6p10 5.2.1-a_drop6p11 5.2.1-a_drop6p12 + 5.2.1-a_drop6p6 5.2.1-a_drop6p7 5.2.1-a_drop6p8 + 5.2.2-a_drop6p13 5.2.2-a_drop6p13-alpha 5.2.2-a_drop6p13b + 5.2.2-a_drop6p13c + + (this was found by grepping for "mysql," in all historical + versions of configure.in in the trees listed above). + + There are 5.1.1-alpha versions that use the new event id's, so we + do not test that version string. So replication from 5.1.1-alpha + with the other event id's to a new version does not work. + Moreover, we can safely ignore the part after drop[56]. This + allows us to simplify the big list above to the following regexes: + + 5\.1\.[1-5]-a_drop5.* + 5\.1\.4-a_drop6.* + 5\.2\.[0-2]-a_drop6.* + + This is what we test for in the 'if' below. */ if (post_header_len && - (strncmp(server_version, "5.1.2-a_drop5", 13) == 0 || - strncmp(server_version, "5.1.5-a_drop5", 13) == 0 || - strncmp(server_version, "5.2.2-a_drop6", 13) == 0)) + server_version[0] == '5' && server_version[1] == '.' && + server_version[3] == '.' && + strncmp(server_version + 5, "-a_drop", 7) == 0 && + ((server_version[2] == '1' && + server_version[4] >= '1' && server_version[4] <= '5' && + server_version[12] == '5') || + (server_version[2] == '1' && + server_version[4] == '4' && + server_version[12] == '6') || + (server_version[2] == '2' && + server_version[4] >= '0' && server_version[4] <= '2' && + server_version[12] == '6'))) { if (number_of_event_types != 22) { @@ -6026,7 +6095,8 @@ bool sql_ex_info::write_data(IO_CACHE* file) sql_ex_info::init() */ -char *sql_ex_info::init(char *buf, char *buf_end, bool use_new_format) +const char *sql_ex_info::init(const char *buf, const char *buf_end, + bool use_new_format) { cached_new_format = use_new_format; if (use_new_format) @@ -6039,12 +6109,11 @@ char *sql_ex_info::init(char *buf, char *buf_end, bool use_new_format) the case when we have old format because we will be reusing net buffer to read the actual file before we write out the Create_file event. */ - const char *ptr= buf; - if (read_str(&ptr, buf_end, (const char **) &field_term, &field_term_len) || - read_str(&ptr, buf_end, (const char **) &enclosed, &enclosed_len) || - read_str(&ptr, buf_end, (const char **) &line_term, &line_term_len) || - read_str(&ptr, buf_end, (const char **) &line_start, &line_start_len) || - read_str(&ptr, buf_end, (const char **) &escaped, &escaped_len)) + if (read_str(&buf, buf_end, &field_term, &field_term_len) || + read_str(&buf, buf_end, &enclosed, &enclosed_len) || + read_str(&buf, buf_end, &line_term, &line_term_len) || + read_str(&buf, buf_end, &line_start, &line_start_len) || + read_str(&buf, buf_end, &escaped, &escaped_len)) return 0; opt_flags = *buf++; } @@ -7646,7 +7715,7 @@ Rows_log_event::write_row(const Relay_log_info *const rli, /* fill table->record[0] with default values */ - if ((error= prepare_record(rli, table, m_width, + if ((error= prepare_record(table, m_width, TRUE /* check if columns have def. values */))) DBUG_RETURN(error); @@ -7964,13 +8033,17 @@ int Rows_log_event::find_row(const Relay_log_info *rli) DBUG_ASSERT(m_table && m_table->in_use != NULL); TABLE *table= m_table; - int error; - - /* unpack row - missing fields get default values */ + int error= 0; - // TODO: shall we check and report errors here? - prepare_record(NULL,table,m_width,FALSE /* don't check errors */); - error= unpack_current_row(rli); + /* + rpl_row_tabledefs.test specifies that + if the extra field on the slave does not have a default value + and this is okay with Delete or Update events. + Todo: fix wl3228 hld that requires defauls for all types of events + */ + + prepare_record(table, m_width, FALSE); + error= unpack_current_row(rli); #ifndef DBUG_OFF DBUG_PRINT("info",("looking for the following record")); diff --git a/sql/log_event.h b/sql/log_event.h index efb8675780e..59d58d47bad 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -152,11 +152,11 @@ struct old_sql_ex struct sql_ex_info { sql_ex_info() {} /* Remove gcc warning */ - char* field_term; - char* enclosed; - char* line_term; - char* line_start; - char* escaped; + const char* field_term; + const char* enclosed; + const char* line_term; + const char* line_start; + const char* escaped; int cached_new_format; uint8 field_term_len,enclosed_len,line_term_len,line_start_len, escaped_len; char opt_flags; @@ -171,7 +171,7 @@ struct sql_ex_info line_start_len + escaped_len + 6 : 7); } bool write_data(IO_CACHE* file); - char* init(char* buf,char* buf_end,bool use_new_format); + const char* init(const char* buf, const char* buf_end, bool use_new_format); bool new_format() { return ((cached_new_format != -1) ? cached_new_format : @@ -3131,6 +3131,8 @@ protected: ASSERT_OR_RETURN_ERROR(m_curr_row < m_rows_end, HA_ERR_CORRUPT_EVENT); int const result= ::unpack_row(rli, m_table, m_width, m_curr_row, &m_cols, &m_curr_row_end, &m_master_reclength); + if (m_curr_row_end > m_rows_end) + my_error(ER_SLAVE_CORRUPT_EVENT, MYF(0)); ASSERT_OR_RETURN_ERROR(m_curr_row_end <= m_rows_end, HA_ERR_CORRUPT_EVENT); return result; } diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index 7621bdc6291..13f9763debe 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -2078,7 +2078,7 @@ Old_rows_log_event::write_row(const Relay_log_info *const rli, /* fill table->record[0] with default values */ - if ((error= prepare_record(rli, table, m_width, + if ((error= prepare_record(table, m_width, TRUE /* check if columns have def. values */))) DBUG_RETURN(error); @@ -2289,7 +2289,7 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli) /* unpack row - missing fields get default values */ // TODO: shall we check and report errors here? - prepare_record(NULL,table,m_width,FALSE /* don't check errors */); + prepare_record(table, m_width, FALSE /* don't check errors */); error= unpack_current_row(rli); #ifndef DBUG_OFF diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index eb32897f937..7c74dcba5a0 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -307,17 +307,15 @@ unpack_row(Relay_log_info const *rli, If @c check is true, fields are explicitly initialized only if they have default value or can be NULL. Otherwise error is reported. - @param log Used to report errors. @param table Table whose record[0] buffer is prepared. @param skip Number of columns for which default value initialization should be skipped. @param check Indicates if errors should be checked when setting default values. - @returns 0 on success. + @returns 0 on success or a handler level error code */ -int prepare_record(const Slave_reporting_capability *const log, - TABLE *const table, +int prepare_record(TABLE *const table, const uint skip, const bool check) { DBUG_ENTER("prepare_record"); @@ -337,14 +335,8 @@ int prepare_record(const Slave_reporting_capability *const log, if (check && ((f->flags & mask) == mask)) { - DBUG_ASSERT(log); - error= ER_NO_DEFAULT_FOR_FIELD; - log->report(ERROR_LEVEL, error, - "Field `%s` of table `%s`.`%s` " - "has no default value and cannot be NULL", - f->field_name, table->s->db.str, - table->s->table_name.str); - my_error(error, MYF(0), f->field_name); + my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), f->field_name); + error = HA_ERR_ROWS_EVENT_APPLY; } else f->set_default(); diff --git a/sql/rpl_record.h b/sql/rpl_record.h index 0d6ceda7433..f9e64f0ab1d 100644 --- a/sql/rpl_record.h +++ b/sql/rpl_record.h @@ -30,8 +30,7 @@ int unpack_row(Relay_log_info const *rli, uchar const **const row_end, ulong *const master_reclength); // Fill table's record[0] with default values. -int prepare_record(const Slave_reporting_capability *const, TABLE *const, - const uint =0, const bool =FALSE); +int prepare_record(TABLE *const, const uint =0, const bool =FALSE); #endif #endif diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 026a0023660..ee3a7e6080a 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -6119,3 +6119,5 @@ ER_SLAVE_AMBIGOUS_EXEC_MODE ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT eng "The BINLOG statement of type `%s` was not preceded by a format description BINLOG statement." +ER_SLAVE_CORRUPT_EVENT + eng "Corrupted replication event was detected" diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc index 04f408453ea..4bfae16ba6d 100644 --- a/sql/sql_binlog.cc +++ b/sql/sql_binlog.cc @@ -152,14 +152,13 @@ void mysql_client_binlog_statement(THD* thd) */ if (!have_fd_event) { - if (bufptr[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT) + int type = bufptr[EVENT_TYPE_OFFSET]; + if (type == FORMAT_DESCRIPTION_EVENT || type == START_EVENT_V3) have_fd_event= TRUE; else { my_error(ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT, - MYF(0), - Log_event::get_type_str( - (Log_event_type)bufptr[EVENT_TYPE_OFFSET])); + MYF(0), Log_event::get_type_str((Log_event_type)type)); goto end; } } |