diff -Naur mysql50/mysql-test/r/rpl_kill_ddl.result fixed/mysql-test/r/rpl_kill_ddl.result --- mysql50/mysql-test/r/rpl_kill_ddl.result 1969-12-31 16:00:00.000000000 -0800 +++ fixed/mysql-test/r/rpl_kill_ddl.result 2009-01-12 14:48:56.000000000 -0800 @@ -0,0 +1,38 @@ +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 foo(i int) engine=innodb; +insert into foo values(4); +insert into foo values(3); +insert into foo values(2); +insert into foo values(1); +create table bar (i int) engine=innodb; +kill id; +drop table bar; +kill id; +alter table foo add column (j varchar(16)); +kill id; +create index part_of_j on foo (j(8)); +kill id; +drop index part_of_j on foo; +kill id; +select * from foo; +i j +4 NULL +3 NULL +2 NULL +1 NULL +select * from bar; +ERROR 42S02: Table 'test.bar' doesn't exist +select * from foo; +i j +4 NULL +3 NULL +2 NULL +1 NULL +select * from bar; +ERROR 42S02: Table 'test.bar' doesn't exist +drop table foo; diff -Naur mysql50/mysql-test/t/rpl_kill_ddl-master.opt fixed/mysql-test/t/rpl_kill_ddl-master.opt --- mysql50/mysql-test/t/rpl_kill_ddl-master.opt 1969-12-31 16:00:00.000000000 -0800 +++ fixed/mysql-test/t/rpl_kill_ddl-master.opt 2009-01-12 14:48:59.000000000 -0800 @@ -0,0 +1 @@ +--debug=d,sleep_before_binlog_bug --innodb diff -Naur mysql50/mysql-test/t/rpl_kill_ddl-slave.opt fixed/mysql-test/t/rpl_kill_ddl-slave.opt --- mysql50/mysql-test/t/rpl_kill_ddl-slave.opt 1969-12-31 16:00:00.000000000 -0800 +++ fixed/mysql-test/t/rpl_kill_ddl-slave.opt 2009-01-12 14:48:59.000000000 -0800 @@ -0,0 +1 @@ +--innodb diff -Naur mysql50/mysql-test/t/rpl_kill_ddl.test fixed/mysql-test/t/rpl_kill_ddl.test --- mysql50/mysql-test/t/rpl_kill_ddl.test 1969-12-31 16:00:00.000000000 -0800 +++ fixed/mysql-test/t/rpl_kill_ddl.test 2009-01-12 14:48:59.000000000 -0800 @@ -0,0 +1,132 @@ +# This tests a fix for MySQL bug 37145 -- killing a DDL +# statement may produce a binlog event with error_code=1053 and that +# halts replication on all slaves. +# +# The test uses a my.cnf variable that makes a session sleep for +# 3 seconds for DDL immediately before creating a binlog event. +# This allows the test to switch to another connection and kill +# the DDL connection. When the DDL connection wakes up, THD::killed +# should be set. You can confirm that this has been done by grep'ing +# var/log/master.err for 'sleep' and you will see output like the +# following, with one 'killed=1053' line for each DDL operation that +# was killed. +# create table sleep, killed=1053 +# drop table sleep, killed=1053 +# alter table sleep, killed=1053 +# +# When this test runs, all binlog events should be created with +# error_code=0 and the confirmation for this is that the slave can +# sync with the master at the end of the test. A second test is +# that the contents of the tables on the master and slave are the +# same. +# +# This is a debug-only test as it uses a my.cnf variable that only +# has an effect in debug mode. + +-- source include/have_innodb.inc +-- source include/master-slave.inc +-- source include/not_embedded.inc +-- source include/have_debug.inc + +create table foo(i int) engine=innodb; +let $i=4; +while ($i) +{ + eval insert into foo values($i); + dec $i; +} + +enable_reconnect; + +# Test create table + +connect (con1, localhost, root,,); +connection con1; +let $id= query_get_value(select connection_id() as Id, Id, 1); +send create table bar (i int) engine=innodb; + +connection default; +sleep 1; +--replace_result $id id +eval kill $id; +connection con1; +--error 0,2013 +reap; + +# Test drop table + +connect (con2, localhost, root,,); +connection con2; +let $id= query_get_value(select connection_id() as Id, Id, 1); +send drop table bar; + +connection default; +sleep 1; +--replace_result $id id +eval kill $id; +connection con2; +--error 0,2013 +reap; + +# Test alter table + +connect (con3, localhost, root,,); +connection con3; +let $id= query_get_value(select connection_id() as Id, Id, 1); +send alter table foo add column (j varchar(16)); + +connection default; +# alter table hits 2 sleeps so wait 4 instead of 1 +sleep 4; +--replace_result $id id +eval kill $id; +connection con3; +--error 0,2013 +reap; + +# Test create index (maps to an alter table) + +connect (con4, localhost, root,,); +connection con4; +let $id= query_get_value(select connection_id() as Id, Id, 1); +send create index part_of_j on foo (j(8)); + +connection default; +sleep 4; +--replace_result $id id +eval kill $id; +connection con4; +--error 0,2013 +reap; + +# Test drop index (maps to an alter table) + +connect (con5, localhost, root,,); +connection con5; +let $id= query_get_value(select connection_id() as Id, Id, 1); +send drop index part_of_j on foo; + +connection default; +sleep 4; +--replace_result $id id +eval kill $id; +connection con4; +--error 0,2013 +reap; + +# Confirm that the slave replays all events +connection default; +sync_slave_with_master slave; + +# Confirm table contents match between master and slave +connection slave; +select * from foo; +--error 1146 +select * from bar; + +connection default; +select * from foo; +--error 1146 +select * from bar; + +drop table foo; diff -Naur mysql50/sql/log.cc fixed/sql/log.cc --- mysql50/sql/log.cc 2009-01-12 14:16:13.000000000 -0800 +++ fixed/sql/log.cc 2009-01-12 14:48:41.000000000 -0800 @@ -182,8 +182,11 @@ */ if (all || !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { - Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE); - qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE) + /* + See comment in MYSQL_LOG::write(THD, IO_CACHE) on error_code = 0 + */ + Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE, + /*error_code*/0); DBUG_RETURN(binlog_end_trans(thd, trans_log, &qev)); } else @@ -226,8 +229,11 @@ */ if (unlikely(thd->transaction.all.modified_non_trans_table)) { - Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE); - qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE) + /* + See comment in MYSQL_LOG::write(THD, IO_CACHE) on error_code = 0 + */ + Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE, + /*error_code*/0); error= binlog_end_trans(thd, trans_log, &qev); } else @@ -264,7 +270,9 @@ *(my_off_t *)sv= my_b_tell(trans_log); /* Write it to the binary log */ - Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE, + Query_log_event::binlog_event_errno(thd, + thd->killed)); DBUG_RETURN(mysql_bin_log.write(&qinfo)); } @@ -281,7 +289,9 @@ */ if (unlikely(thd->transaction.all.modified_non_trans_table)) { - Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE, + Query_log_event::binlog_event_errno(thd, + thd->killed)); DBUG_RETURN(mysql_bin_log.write(&qinfo)); } reinit_io_cache(trans_log, WRITE_CACHE, *(my_off_t *)sv, 0, 0); @@ -2758,7 +2768,6 @@ transaction is either a BEGIN..COMMIT block or a single statement in autocommit mode. */ - Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, FALSE); /* Imagine this is rollback due to net timeout, after all statements of the transaction succeeded. Then we want a @@ -2767,10 +2776,9 @@ events, there is no need to put it also in this internally generated event, and as this event is generated late it would lead to false alarms. - - This is safer than thd->clear_error() against kills at shutdown. */ - qinfo.error_code= 0; + Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, FALSE, + /*error_code*/0); /* Set the event's group_id. Above constructor used more than just here so chose to not change it and instead set the group_id here. diff -Naur mysql50/sql/log_event.cc fixed/sql/log_event.cc --- mysql50/sql/log_event.cc 2009-01-12 14:16:13.000000000 -0800 +++ fixed/sql/log_event.cc 2009-01-12 14:48:41.000000000 -0800 @@ -1558,7 +1558,7 @@ */ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, bool using_trans, - bool suppress_use, THD::killed_state killed_status_arg) + bool suppress_use, uint16 error_code_arg) :Log_event(thd_arg, ((thd_arg->tmp_table_used || thd_arg->thread_specific_used) ? LOG_EVENT_THREAD_SPECIFIC_F : 0) | @@ -1574,17 +1574,10 @@ auto_increment_increment(thd_arg->variables.auto_increment_increment), auto_increment_offset(thd_arg->variables.auto_increment_offset), lc_time_names_number(thd_arg->variables.lc_time_names->number), - charset_database_number(0) + charset_database_number(0), error_code(error_code_arg) { time_t end_time; - if (killed_status_arg == THD::KILLED_NO_VALUE) - killed_status_arg= thd_arg->killed; - error_code= - (killed_status_arg == THD::NOT_KILLED) ? thd_arg->net.last_errno : - ((thd_arg->system_thread & SYSTEM_THREAD_DELAYED_INSERT) ? 0 : - thd->killed_errno()); - time(&end_time); exec_time = (ulong) (end_time - thd->start_time); catalog_len = (catalog) ? (uint32) strlen(catalog) : 0; @@ -5365,9 +5358,9 @@ uint fn_pos_end_arg, enum_load_dup_handling dup_handling_arg, bool using_trans, bool suppress_use, - THD::killed_state killed_err_arg): + uint16 error_code_arg): Query_log_event(thd_arg, query_arg, query_length_arg, using_trans, - suppress_use, killed_err_arg), + suppress_use, error_code_arg), file_id(thd_arg->file_id), fn_pos_start(fn_pos_start_arg), fn_pos_end(fn_pos_end_arg), dup_handling(dup_handling_arg) { diff -Naur mysql50/sql/log_event.h fixed/sql/log_event.h --- mysql50/sql/log_event.h 2009-01-12 14:16:13.000000000 -0800 +++ fixed/sql/log_event.h 2009-01-12 14:48:41.000000000 -0800 @@ -866,10 +866,20 @@ uint charset_database_number; #ifndef MYSQL_CLIENT + /* Returns the value to use for the error_code field of the binlog event. + * This was extracted from the Query_log_event constructor. + */ + static uint16 binlog_event_errno(THD *thd, + THD::killed_state killed_status_arg) + { + return (killed_status_arg == THD::NOT_KILLED) ? thd->net.last_errno : + ((thd->system_thread & SYSTEM_THREAD_DELAYED_INSERT) ? 0 : + thd->killed_errno()); + } Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, bool using_trans, bool suppress_use, - THD::killed_state killed_err_arg= THD::KILLED_NO_VALUE); + uint16 error_code_arg); const char* get_db() { return db; } #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol); @@ -1714,8 +1724,7 @@ uint fn_pos_end_arg, enum_load_dup_handling dup_handling_arg, bool using_trans, bool suppress_use, - THD::killed_state - killed_err_arg= THD::KILLED_NO_VALUE); + uint16 error_code_arg); #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol); int exec_event(struct st_relay_log_info* rli); diff -Naur mysql50/sql/sp.cc fixed/sql/sp.cc --- mysql50/sql/sp.cc 2009-01-12 14:16:14.000000000 -0800 +++ fixed/sql/sp.cc 2009-01-12 14:48:41.000000000 -0800 @@ -645,7 +645,7 @@ /* Such a statement can always go directly to binlog, no trans cache */ Query_log_event qinfo(thd, log_query.c_ptr(), log_query.length(), 0, - FALSE); + FALSE, /*error_code*/0); mysql_bin_log.write(&qinfo); } @@ -679,7 +679,8 @@ if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE, + /*error_code*/0); mysql_bin_log.write(&qinfo); } } @@ -724,7 +725,8 @@ if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE, + /*error_code*/0); mysql_bin_log.write(&qinfo); } } @@ -1938,4 +1940,3 @@ *dbchangedp= ret == 0; DBUG_RETURN(ret); } - diff -Naur mysql50/sql/sp_head.cc fixed/sql/sp_head.cc --- mysql50/sql/sp_head.cc 2009-01-12 14:16:14.000000000 -0800 +++ fixed/sql/sp_head.cc 2009-01-12 14:48:41.000000000 -0800 @@ -1623,7 +1623,9 @@ if (need_binlog_call && thd->binlog_evt_union.unioned_events) { Query_log_event qinfo(thd, binlog_buf.ptr(), binlog_buf.length(), - thd->binlog_evt_union.unioned_events_trans, FALSE); + thd->binlog_evt_union.unioned_events_trans, FALSE, + Query_log_event::binlog_event_errno(thd, + thd->killed)); if (mysql_bin_log.write(&qinfo) && thd->binlog_evt_union.unioned_events_trans) { @@ -3805,4 +3807,3 @@ lex->add_to_query_tables(table); return table; } - diff -Naur mysql50/sql/sql_acl.cc fixed/sql/sql_acl.cc --- mysql50/sql/sql_acl.cc 2009-01-12 14:16:14.000000000 -0800 +++ fixed/sql/sql_acl.cc 2009-01-12 14:48:42.000000000 -0800 @@ -1974,7 +1974,7 @@ acl_user->host.hostname ? acl_user->host.hostname : "", new_password)); thd->clear_error(); - Query_log_event qinfo(thd, buff, query_length, 0, FALSE); + Query_log_event qinfo(thd, buff, query_length, 0, FALSE, /*error_code*/0); mysql_bin_log.write(&qinfo); } end: @@ -3593,7 +3593,8 @@ if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE, + /*error_code*/0); mysql_bin_log.write(&qinfo); } } @@ -3760,7 +3761,8 @@ if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE, + /*error_code*/0); mysql_bin_log.write(&qinfo); } } @@ -3873,7 +3875,8 @@ if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE, + /*error_code*/0); mysql_bin_log.write(&qinfo); } } @@ -6206,7 +6209,11 @@ if (some_users_created && mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + uint16 error_code = 0; + if (result) + error_code = Query_log_event::binlog_event_errno(thd, thd->killed); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE, + error_code); mysql_bin_log.write(&qinfo); } @@ -6301,7 +6308,11 @@ if (some_users_deleted && mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + uint16 error_code = 0; + if (result) + error_code = Query_log_event::binlog_event_errno(thd, thd->killed); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE, + error_code); mysql_bin_log.write(&qinfo); } @@ -6384,7 +6395,11 @@ if (some_users_renamed && mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + uint16 error_code = 0; + if (result) + error_code = Query_log_event::binlog_event_errno(thd, thd->killed); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE, + error_code); mysql_bin_log.write(&qinfo); } @@ -6563,7 +6578,11 @@ if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + uint16 error_code = 0; + if (result) + error_code = Query_log_event::binlog_event_errno(thd, thd->killed); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE, + error_code); mysql_bin_log.write(&qinfo); } diff -Naur mysql50/sql/sql_base.cc fixed/sql/sql_base.cc --- mysql50/sql/sql_base.cc 2009-01-12 14:16:14.000000000 -0800 +++ fixed/sql/sql_base.cc 2009-01-12 14:48:42.000000000 -0800 @@ -801,10 +801,6 @@ thd->clear_error(); CHARSET_INFO *cs_save= thd->variables.character_set_client; thd->variables.character_set_client= system_charset_info; - Query_log_event qinfo(thd, s_query.ptr(), - s_query.length() - 1 /* to remove trailing ',' */, - 0, FALSE); - thd->variables.character_set_client= cs_save; /* Imagine the thread had created a temp table, then was doing a SELECT, and the SELECT was killed. Then it's not clever to mark the statement above as @@ -814,7 +810,10 @@ master, then this real update will be logged with error_code=killed, rightfully causing the slave to stop. */ - qinfo.error_code= 0; + Query_log_event qinfo(thd, s_query.ptr(), + s_query.length() - 1 /* to remove trailing ',' */, + 0, FALSE, /*error_code*/0); + thd->variables.character_set_client= cs_save; mysql_bin_log.write(&qinfo); } else @@ -2590,7 +2589,8 @@ { end = strxmov(strmov(query, "DELETE FROM `"), db,"`.`",name,"`", NullS); - Query_log_event qinfo(thd, query, (ulong)(end-query), 0, FALSE); + Query_log_event qinfo(thd, query, (ulong)(end-query), 0, FALSE, + /*error_code*/0); mysql_bin_log.write(&qinfo); my_free(query, MYF(0)); } diff -Naur mysql50/sql/sql_db.cc fixed/sql/sql_db.cc --- mysql50/sql/sql_db.cc 2009-01-12 14:16:14.000000000 -0800 +++ fixed/sql/sql_db.cc 2009-01-12 14:48:42.000000000 -0800 @@ -70,8 +70,7 @@ static inline void write_to_binlog(THD *thd, char *query, uint q_len, char *db, uint db_len) { - Query_log_event qinfo(thd, query, q_len, 0, 0); - qinfo.error_code= 0; + Query_log_event qinfo(thd, query, q_len, 0, 0, /*error_code*/0); qinfo.db= db; qinfo.db_len= db_len; mysql_bin_log.write(&qinfo); @@ -561,8 +560,8 @@ } if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, query, query_length, 0, - /* suppress_use */ TRUE); + Query_log_event qinfo(thd, query, query_length, 0, + /* suppress_use */ TRUE, /*error_code*/0); /* Write should use the database being created as the "current @@ -644,8 +643,9 @@ if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0, - /* suppress_use */ TRUE); + /* suppress_use */ TRUE, /*error_code*/0); /* Write should use the database being created as the "current @@ -655,7 +655,6 @@ qinfo.db = db; qinfo.db_len = strlen(db); - thd->clear_error(); /* These DDL methods and logging protected with LOCK_mysql_create_db */ mysql_bin_log.write(&qinfo); } @@ -769,8 +768,9 @@ } if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, query, query_length, 0, - /* suppress_use */ TRUE); + thd->clear_error(); + Query_log_event qinfo(thd, query, query_length, 0, + /* suppress_use */ TRUE, /*error_code*/0); /* Write should use the database being created as the "current database" and not the threads current database, which is the @@ -779,7 +779,6 @@ qinfo.db = db; qinfo.db_len = strlen(db); - thd->clear_error(); /* These DDL methods and logging protected with LOCK_mysql_create_db */ mysql_bin_log.write(&qinfo); } diff -Naur mysql50/sql/sql_delete.cc fixed/sql/sql_delete.cc --- mysql50/sql/sql_delete.cc 2009-01-12 14:16:14.000000000 -0800 +++ fixed/sql/sql_delete.cc 2009-01-12 14:48:42.000000000 -0800 @@ -334,10 +334,13 @@ { if (mysql_bin_log.is_open()) { + uint16 error_code = 0; if (error < 0) thd->clear_error(); + else + error_code = Query_log_event::binlog_event_errno(thd, killed_status); Query_log_event qinfo(thd, thd->query, thd->query_length, - transactional_table, FALSE, killed_status); + transactional_table, FALSE, error_code); if (mysql_bin_log.write(&qinfo) && transactional_table) error=1; } @@ -736,7 +739,9 @@ if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, - transactional_tables, FALSE); + transactional_tables, FALSE, + Query_log_event::binlog_event_errno(thd, + thd->killed)); mysql_bin_log.write(&qinfo); } thd->transaction.all.modified_non_trans_table= true; @@ -857,10 +862,13 @@ { if (mysql_bin_log.is_open()) { + uint16 error_code = 0; if (local_error == 0) thd->clear_error(); + else + error_code = Query_log_event::binlog_event_errno(thd, killed_status); Query_log_event qinfo(thd, thd->query, thd->query_length, - transactional_tables, FALSE, killed_status); + transactional_tables, FALSE, error_code); if (mysql_bin_log.write(&qinfo) && !normal_tables) local_error=1; // Log write failed: roll back the SQL statement } @@ -970,7 +978,7 @@ { thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, - 0, FALSE); + 0, FALSE, /*error_code*/0); mysql_bin_log.write(&qinfo); } send_ok(thd); // This should return record count diff -Naur mysql50/sql/sql_insert.cc fixed/sql/sql_insert.cc --- mysql50/sql/sql_insert.cc 2009-01-12 14:16:14.000000000 -0800 +++ fixed/sql/sql_insert.cc 2009-01-12 14:48:42.000000000 -0800 @@ -896,6 +896,7 @@ { if (mysql_bin_log.is_open()) { + uint16 error_code = 0; if (error <= 0) { /* @@ -910,21 +911,24 @@ /* todo: consider removing */ thd->clear_error(); } - /* bug#22725: - - A query which per-row-loop can not be interrupted with - KILLED, like INSERT, and that does not invoke stored - routines can be binlogged with neglecting the KILLED error. - - If there was no error (error == zero) until after the end of - inserting loop the KILLED flag that appeared later can be - disregarded since previously possible invocation of stored - routines did not result in any error due to the KILLED. In - such case the flag is ignored for constructing binlog event. - */ + else + { + /* bug#22725: + + A query which per-row-loop can not be interrupted with + KILLED, like INSERT, and that does not invoke stored + routines can be binlogged with neglecting the KILLED error. + + If there was no error (error == zero) until after the end of + inserting loop the KILLED flag that appeared later can be + disregarded since previously possible invocation of stored + routines did not result in any error due to the KILLED. In + such case the flag is ignored for constructing binlog event. + */ + error_code = Query_log_event::binlog_event_errno(thd, thd->killed); + } Query_log_event qinfo(thd, thd->query, thd->query_length, - transactional_table, FALSE, - (error>0) ? thd->killed : THD::NOT_KILLED); + transactional_table, FALSE, error_code); DBUG_ASSERT(thd->killed != THD::KILL_BAD_DATA || error > 0); if (mysql_bin_log.write(&qinfo) && transactional_table) error=1; @@ -2525,7 +2529,9 @@ } if (row->query && row->log_query && using_bin_log) { - Query_log_event qinfo(&thd, row->query, row->query_length, 0, FALSE); + Query_log_event qinfo(&thd, row->query, row->query_length, 0, FALSE, + Query_log_event::binlog_event_errno(&thd, + thd.killed)); mysql_bin_log.write(&qinfo); } if (table->s->blob_fields) @@ -3013,10 +3019,13 @@ /* Write to binlog before commiting transaction */ if (mysql_bin_log.is_open()) { + uint16 error_code = 0; if (!error) thd->clear_error(); + else + error_code = Query_log_event::binlog_event_errno(thd, killed_status); Query_log_event qinfo(thd, thd->query, thd->query_length, - transactional_table, FALSE, killed_status); + transactional_table, FALSE, error_code); mysql_bin_log.write(&qinfo); } if ((error2=ha_autocommit_or_rollback(thd,error)) && ! error) @@ -3083,7 +3092,9 @@ if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, - transactional_table, FALSE); + transactional_table, FALSE, + Query_log_event::binlog_event_errno(thd, + thd->killed)); mysql_bin_log.write(&qinfo); } if (thd->transaction.stmt.modified_non_trans_table) diff -Naur mysql50/sql/sql_load.cc fixed/sql/sql_load.cc --- mysql50/sql/sql_load.cc 2009-01-12 14:16:14.000000000 -0800 +++ fixed/sql/sql_load.cc 2009-01-12 14:48:42.000000000 -0800 @@ -86,7 +86,8 @@ static bool write_execute_load_query_log_event(THD *thd, bool duplicates, bool ignore, bool transactional_table, - THD::killed_state killed_status); + uint16 error_code_arg); + #endif /* EMBEDDED_LIBRARY */ /* @@ -457,10 +458,12 @@ /* If the file was not empty, wrote_create_file is true */ if (lf_info.wrote_create_file) { + uint16 error_code = Query_log_event::binlog_event_errno(thd, + killed_status); if (thd->transaction.stmt.modified_non_trans_table) write_execute_load_query_log_event(thd, handle_duplicates, ignore, transactional_table, - killed_status); + error_code); else { Delete_file_log_event d(thd, db, transactional_table); @@ -492,7 +495,7 @@ if (lf_info.wrote_create_file) write_execute_load_query_log_event(thd, handle_duplicates, ignore, transactional_table, - killed_status); + /*error_code*/0); } #endif /*!EMBEDDED_LIBRARY*/ if (transactional_table) @@ -520,7 +523,7 @@ static bool write_execute_load_query_log_event(THD *thd, bool duplicates, bool ignore, bool transactional_table, - THD::killed_state killed_err_arg) + uint16 error_code_arg) { Execute_load_query_log_event e(thd, thd->query, thd->query_length, @@ -528,7 +531,7 @@ (char*)thd->lex->fname_end - (char*)thd->query, (duplicates == DUP_REPLACE) ? LOAD_DUP_REPLACE : (ignore ? LOAD_DUP_IGNORE : LOAD_DUP_ERROR), - transactional_table, FALSE, killed_err_arg); + transactional_table, FALSE, error_code_arg); return mysql_bin_log.write(&e); } diff -Naur mysql50/sql/sql_parse.cc fixed/sql/sql_parse.cc --- mysql50/sql/sql_parse.cc 2009-01-12 14:16:14.000000000 -0800 +++ fixed/sql/sql_parse.cc 2009-01-12 14:48:42.000000000 -0800 @@ -4813,7 +4813,8 @@ if (mysql_bin_log.is_open()) { thd->clear_error(); // No binlog error generated - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE, + /*error_code*/0); mysql_bin_log.write(&qinfo); } } @@ -4848,7 +4849,8 @@ if (mysql_bin_log.is_open()) { thd->clear_error(); // No binlog error generated - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE, + /*error_code*/0); mysql_bin_log.write(&qinfo); } } @@ -4874,7 +4876,8 @@ if (mysql_bin_log.is_open()) { thd->clear_error(); // No binlog error generated - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE, + /*error_code*/0); mysql_bin_log.write(&qinfo); } } @@ -5742,7 +5745,8 @@ { if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE, + /*error_code*/0); mysql_bin_log.write(&qinfo); } } @@ -9830,4 +9834,3 @@ } DBUG_RETURN(0); } - diff -Naur mysql50/sql/sql_rename.cc fixed/sql/sql_rename.cc --- mysql50/sql/sql_rename.cc 2009-01-12 14:16:14.000000000 -0800 +++ fixed/sql/sql_rename.cc 2009-01-12 14:48:42.000000000 -0800 @@ -84,7 +84,8 @@ if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE, + /*error_code*/0); mysql_bin_log.write(&qinfo); } send_ok(thd); diff -Naur mysql50/sql/sql_table.cc fixed/sql/sql_table.cc --- mysql50/sql/sql_table.cc 2009-01-12 14:16:15.000000000 -0800 +++ fixed/sql/sql_table.cc 2009-01-12 14:48:42.000000000 -0800 @@ -326,14 +326,23 @@ error= 1; } + DBUG_EXECUTE_IF("sleep_before_binlog_bug", + sleep(3); + fprintf(stderr, "drop table sleep, killed=%d\n", + thd->killed);); + if (some_tables_deleted || tmp_table_deleted || !error) { query_cache_invalidate3(thd, tables, 0); if (!dont_log_query && mysql_bin_log.is_open()) { + uint16 error_code = 0; if (!error) thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE); + else + error_code = Query_log_event::binlog_event_errno(thd, thd->killed); + Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE, + error_code); mysql_bin_log.write(&qinfo); } } @@ -1809,10 +1818,17 @@ } thd->tmp_table_used= 1; } + + DBUG_EXECUTE_IF("sleep_before_binlog_bug", + sleep(3); + fprintf(stderr, "create table sleep, killed=%d\n", + thd->killed);); + if (!internal_tmp_table && mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE, + /*error_code*/0); mysql_bin_log.write(&qinfo); } error= FALSE; @@ -2890,7 +2906,8 @@ if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE, + /*error_code*/0); mysql_bin_log.write(&qinfo); } res= FALSE; @@ -2999,7 +3016,8 @@ goto err; if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE, + /*error_code*/0); mysql_bin_log.write(&qinfo); } err: @@ -3155,7 +3173,8 @@ if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE, + /*error_code*/0); mysql_bin_log.write(&qinfo); } send_ok(thd); @@ -3347,7 +3366,8 @@ if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE, + /*error_code*/0); mysql_bin_log.write(&qinfo); } send_ok(thd); @@ -3861,7 +3881,8 @@ if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE, + /*error_code*/0); mysql_bin_log.write(&qinfo); } goto end_temporary; @@ -3993,10 +4014,17 @@ } } thd_proc_info(thd, "end"); + + DBUG_EXECUTE_IF("sleep_before_binlog_bug", + sleep(3); + fprintf(stderr, "alter table sleep, killed=%d\n", + thd->killed);); + if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE, + /*error_code*/0); mysql_bin_log.write(&qinfo); } broadcast_refresh(); diff -Naur mysql50/sql/sql_trigger.cc fixed/sql/sql_trigger.cc --- mysql50/sql/sql_trigger.cc 2009-01-12 14:16:15.000000000 -0800 +++ fixed/sql/sql_trigger.cc 2009-01-12 14:48:42.000000000 -0800 @@ -304,7 +304,7 @@ /* Such a statement can always go directly to binlog, no trans cache. */ Query_log_event qinfo(thd, stmt_query.ptr(), stmt_query.length(), 0, - FALSE); + FALSE, /*error_code*/0); mysql_bin_log.write(&qinfo); } } diff -Naur mysql50/sql/sql_update.cc fixed/sql/sql_update.cc --- mysql50/sql/sql_update.cc 2009-01-12 14:16:15.000000000 -0800 +++ fixed/sql/sql_update.cc 2009-01-12 14:48:42.000000000 -0800 @@ -573,10 +573,13 @@ { if (mysql_bin_log.is_open()) { + uint16 error_code = 0; if (error < 0) thd->clear_error(); + else + error_code = Query_log_event::binlog_event_errno(thd, killed_status); Query_log_event qinfo(thd, thd->query, thd->query_length, - transactional_table, FALSE, killed_status); + transactional_table, FALSE, error_code); if (mysql_bin_log.write(&qinfo) && transactional_table) error=1; // Rollback update } @@ -1524,7 +1527,9 @@ into repl event. */ Query_log_event qinfo(thd, thd->query, thd->query_length, - transactional_tables, FALSE); + transactional_tables, FALSE, + Query_log_event::binlog_event_errno(thd, + thd->killed)); mysql_bin_log.write(&qinfo); } thd->transaction.all.modified_non_trans_table= TRUE; @@ -1751,10 +1756,13 @@ { if (mysql_bin_log.is_open()) { + uint16 error_code = 0; if (local_error == 0) thd->clear_error(); + else + error_code = Query_log_event::binlog_event_errno(thd, killed_status); Query_log_event qinfo(thd, thd->query, thd->query_length, - transactional_tables, FALSE, killed_status); + transactional_tables, FALSE, error_code); if (mysql_bin_log.write(&qinfo) && trans_safe) local_error= 1; // Rollback update } diff -Naur mysql50/sql/sql_view.cc fixed/sql/sql_view.cc --- mysql50/sql/sql_view.cc 2009-01-12 14:16:15.000000000 -0800 +++ fixed/sql/sql_view.cc 2009-01-12 14:48:42.000000000 -0800 @@ -662,7 +662,9 @@ else if (views->with_check == VIEW_CHECK_CASCADED) buff.append(STRING_WITH_LEN(" WITH CASCADED CHECK OPTION")); - Query_log_event qinfo(thd, buff.ptr(), buff.length(), 0, FALSE); + Query_log_event qinfo(thd, buff.ptr(), buff.length(), 0, FALSE, + Query_log_event::binlog_event_errno(thd, + thd->killed)); mysql_bin_log.write(&qinfo); } @@ -1561,9 +1563,13 @@ something_wrong= error || wrong_object_name || non_existant_views.length(); if (some_views_deleted || !something_wrong) { + uint16 error_code = 0; if (!something_wrong) thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + else + error_code = Query_log_event::binlog_event_errno(thd, thd->killed); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE, + error_code); mysql_bin_log.write(&qinfo); }