summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/item_cmpfunc.cc2
-rw-r--r--sql/log_event.cc11
-rw-r--r--sql/log_event.h10
-rw-r--r--sql/slave.cc154
-rw-r--r--sql/sp_head.cc5
-rw-r--r--sql/sql_delete.cc34
-rw-r--r--sql/sql_insert.cc25
-rw-r--r--sql/sql_load.cc58
-rw-r--r--sql/sql_update.cc120
9 files changed, 398 insertions, 21 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index e27127a5804..47649006ccf 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -4410,7 +4410,7 @@ Item_func_regex::regcomp(bool send_error)
res= &conv;
}
- if ((error= my_regcomp(&preg, res->c_ptr(),
+ if ((error= my_regcomp(&preg, res->c_ptr_safe(),
regex_lib_flags, regex_lib_charset)))
{
if (send_error)
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 53c877f28c0..e300de353b0 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -5472,12 +5472,13 @@ Begin_load_query_log_event::do_shall_skip(Relay_log_info *rli)
#ifndef MYSQL_CLIENT
Execute_load_query_log_event::
Execute_load_query_log_event(THD *thd_arg, const char* query_arg,
- ulong query_length_arg, uint fn_pos_start_arg,
- uint fn_pos_end_arg,
- enum_load_dup_handling dup_handling_arg,
- bool using_trans, bool suppress_use):
+ ulong query_length_arg, uint fn_pos_start_arg,
+ uint fn_pos_end_arg,
+ enum_load_dup_handling dup_handling_arg,
+ bool using_trans, bool suppress_use,
+ THD::killed_state killed_err_arg):
Query_log_event(thd_arg, query_arg, query_length_arg, using_trans,
- suppress_use),
+ suppress_use, killed_err_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 --git a/sql/log_event.h b/sql/log_event.h
index ab2424d8466..4bd496af2a4 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -2744,10 +2744,12 @@ public:
#ifndef MYSQL_CLIENT
Execute_load_query_log_event(THD* thd, const char* query_arg,
- ulong query_length, uint fn_pos_start_arg,
- uint fn_pos_end_arg,
- enum_load_dup_handling dup_handling_arg,
- bool using_trans, bool suppress_use);
+ ulong query_length, uint fn_pos_start_arg,
+ 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);
#ifdef HAVE_REPLICATION
void pack_info(Protocol* protocol);
#endif /* HAVE_REPLICATION */
diff --git a/sql/slave.cc b/sql/slave.cc
index 3b80a58676b..a3ac0c2f34f 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1807,6 +1807,58 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli)
/*
*/
+<<<<<<< gca sql/slave.cc 1.241.1.61
+ DBUG_PRINT("info",("type_code=%d, server_id=%d",type_code,ev->server_id));
+
+ if ((ev->server_id == (uint32) ::server_id &&
+ !replicate_same_server_id &&
+ type_code != FORMAT_DESCRIPTION_EVENT) ||
+ (rli->slave_skip_counter &&
+ type_code != ROTATE_EVENT && type_code != STOP_EVENT &&
+ type_code != START_EVENT_V3 && type_code!= FORMAT_DESCRIPTION_EVENT))
+ {
+ DBUG_PRINT("info", ("event skipped"));
+ if (thd->options & OPTION_BEGIN)
+ rli->inc_event_relay_log_pos();
+ else
+ {
+ rli->inc_group_relay_log_pos((type_code == ROTATE_EVENT ||
+ type_code == STOP_EVENT ||
+ type_code == FORMAT_DESCRIPTION_EVENT) ?
+ LL(0) : ev->log_pos,
+ 1/* skip lock*/);
+ flush_relay_log_info(rli);
+ }
+
+ /*
+ Protect against common user error of setting the counter to 1
+ instead of 2 while recovering from an insert which used auto_increment,
+ rand or user var.
+ */
+ if (rli->slave_skip_counter &&
+ !((type_code == INTVAR_EVENT ||
+ type_code == RAND_EVENT ||
+ type_code == USER_VAR_EVENT) &&
+ rli->slave_skip_counter == 1) &&
+ /*
+ The events from ourselves which have something to do with the relay
+ log itself must be skipped, true, but they mustn't decrement
+ rli->slave_skip_counter, because the user is supposed to not see
+ these events (they are not in the master's binlog) and if we
+ decremented, START SLAVE would for example decrement when it sees
+ the Rotate, so the event which the user probably wanted to skip
+ would not be skipped.
+ */
+ !(ev->server_id == (uint32) ::server_id &&
+ (type_code == ROTATE_EVENT || type_code == STOP_EVENT ||
+ type_code == START_EVENT_V3 || type_code == FORMAT_DESCRIPTION_EVENT)))
+ --rli->slave_skip_counter;
+ pthread_mutex_unlock(&rli->data_lock);
+ delete ev;
+ return 0; // avoid infinite update loops
+ }
+ pthread_mutex_unlock(&rli->data_lock);
+<<<<<<< local sql/slave.cc 1.321
DBUG_PRINT("exec_event",("%s(type_code: %d; server_id: %d)",
ev->get_type_str(), type_code, ev->server_id));
DBUG_PRINT("info", ("thd->options: %s%s; rli->last_event_start_time: %lu",
@@ -1839,6 +1891,108 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli)
log (remember that now the relay log starts with its Format_desc,
has a Rotate etc).
*/
+<<<<<<< remote sql/slave.cc 1.241.1.62
+ DBUG_PRINT("info",("type_code: %d; server_id: %d; slave_skip_counter: %d",
+ type_code, ev->server_id, rli->slave_skip_counter));
+
+ /*
+ If the slave skip counter is positive, we still need to set the
+ OPTION_BEGIN flag correctly and not skip the log events that
+ start or end a transaction. If we do this, the slave will not
+ notice that it is inside a transaction, and happily start
+ executing from inside the transaction.
+
+ Note that the code block below is strictly 5.0.
+ */
+#if MYSQL_VERSION_ID < 50100
+ if (unlikely(rli->slave_skip_counter > 0))
+ {
+ switch (type_code)
+ {
+ case QUERY_EVENT:
+ {
+ Query_log_event* const qev= (Query_log_event*) ev;
+ DBUG_PRINT("info", ("QUERY_EVENT { query: '%s', q_len: %u }",
+ qev->query, qev->q_len));
+ if (memcmp("BEGIN", qev->query, qev->q_len+1) == 0)
+ thd->options|= OPTION_BEGIN;
+ else if (memcmp("COMMIT", qev->query, qev->q_len+1) == 0 ||
+ memcmp("ROLLBACK", qev->query, qev->q_len+1) == 0)
+ thd->options&= ~OPTION_BEGIN;
+ }
+ break;
+
+ case XID_EVENT:
+ DBUG_PRINT("info", ("XID_EVENT"));
+ thd->options&= ~OPTION_BEGIN;
+ break;
+ }
+ }
+#endif
+
+ if ((ev->server_id == (uint32) ::server_id &&
+ !replicate_same_server_id &&
+ type_code != FORMAT_DESCRIPTION_EVENT) ||
+ (rli->slave_skip_counter &&
+ type_code != ROTATE_EVENT && type_code != STOP_EVENT &&
+ type_code != START_EVENT_V3 && type_code!= FORMAT_DESCRIPTION_EVENT))
+ {
+ DBUG_PRINT("info", ("event skipped"));
+ if (thd->options & OPTION_BEGIN)
+ rli->inc_event_relay_log_pos();
+ else
+ {
+ rli->inc_group_relay_log_pos((type_code == ROTATE_EVENT ||
+ type_code == STOP_EVENT ||
+ type_code == FORMAT_DESCRIPTION_EVENT) ?
+ LL(0) : ev->log_pos,
+ 1/* skip lock*/);
+ flush_relay_log_info(rli);
+ }
+
+ DBUG_PRINT("info", ("thd->options: %s",
+ (thd->options & OPTION_BEGIN) ? "OPTION_BEGIN" : ""))
+
+ /*
+ Protect against common user error of setting the counter to 1
+ instead of 2 while recovering from an insert which used auto_increment,
+ rand or user var.
+ */
+ if (rli->slave_skip_counter &&
+ !((type_code == INTVAR_EVENT ||
+ type_code == RAND_EVENT ||
+ type_code == USER_VAR_EVENT) &&
+ rli->slave_skip_counter == 1) &&
+#if MYSQL_VERSION_ID < 50100
+ /*
+ Decrease the slave skip counter only if we are not inside
+ a transaction or the slave skip counter is more than
+ 1. The slave skip counter will be decreased from 1 to 0
+ when reaching the final ROLLBACK, COMMIT, or XID_EVENT.
+ */
+ (!(thd->options & OPTION_BEGIN) || rli->slave_skip_counter > 1) &&
+#endif
+ /*
+ The events from ourselves which have something to do with the relay
+ log itself must be skipped, true, but they mustn't decrement
+ rli->slave_skip_counter, because the user is supposed to not see
+ these events (they are not in the master's binlog) and if we
+ decremented, START SLAVE would for example decrement when it sees
+ the Rotate, so the event which the user probably wanted to skip
+ would not be skipped.
+ */
+ !(ev->server_id == (uint32) ::server_id &&
+ (type_code == ROTATE_EVENT ||
+ type_code == STOP_EVENT ||
+ type_code == START_EVENT_V3 ||
+ type_code == FORMAT_DESCRIPTION_EVENT)))
+ --rli->slave_skip_counter;
+ pthread_mutex_unlock(&rli->data_lock);
+ delete ev;
+ return 0; // avoid infinite update loops
+ }
+ pthread_mutex_unlock(&rli->data_lock);
+>>>>>>>
thd->server_id = ev->server_id; // use the original server id for logging
thd->set_time(); // time the query
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 093544cdd0a..5f92dd3b3a5 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -102,8 +102,9 @@ sp_get_item_value(THD *thd, Item *item, String *str)
case REAL_RESULT:
case INT_RESULT:
case DECIMAL_RESULT:
- return item->val_str(str);
-
+ if (item->field_type() != MYSQL_TYPE_BIT)
+ return item->val_str(str);
+ else {/* Bit type is handled as binary string */}
case STRING_RESULT:
{
String *result= item->val_str(str);
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 0746a261de1..33d19852371 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -38,6 +38,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
ha_rows deleted= 0;
uint usable_index= MAX_KEY;
SELECT_LEX *select_lex= &thd->lex->select_lex;
+ THD::killed_state killed_status= THD::NOT_KILLED;
DBUG_ENTER("mysql_delete");
if (open_and_lock_tables(thd, table_list))
@@ -300,8 +301,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
else
table->file->unlock_row(); // Row failed selection, release lock on it
}
- if (thd->killed && !error)
- error= 1; // Aborted
+ killed_status= thd->killed;
+ error= (killed_status == THD::NOT_KILLED)? error : 1;
if (will_batch && (loc_error= table->file->end_bulk_delete()))
{
if (error != 1)
@@ -351,6 +352,11 @@ cleanup:
{
if (error < 0)
thd->clear_error();
+<<<<<<< gca sql/sql_delete.cc 1.144.1.57
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ transactional_table, FALSE);
+ if (mysql_bin_log.write(&qinfo) && transactional_table)
+<<<<<<< local sql/sql_delete.cc 1.230
/*
[binlog]: If 'handler::delete_all_rows()' was called and the
@@ -364,6 +370,11 @@ cleanup:
if (log_result && transactional_table)
{
+<<<<<<< remote sql/sql_delete.cc 1.144.1.58
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ transactional_table, FALSE, killed_status);
+ if (mysql_bin_log.write(&qinfo) && transactional_table)
+>>>>>>>
error=1;
}
}
@@ -764,7 +775,8 @@ void multi_delete::send_error(uint errcode,const char *err)
}
thd->transaction.all.modified_non_trans_table= true;
}
- DBUG_ASSERT(!normal_tables || !deleted || thd->transaction.stmt.modified_non_trans_table);
+ DBUG_ASSERT(!normal_tables || !deleted ||
+ thd->transaction.stmt.modified_non_trans_table);
DBUG_VOID_RETURN;
}
@@ -862,6 +874,7 @@ int multi_delete::do_deletes()
bool multi_delete::send_eof()
{
+ THD::killed_state killed_status= THD::NOT_KILLED;
thd->proc_info="deleting from reference tables";
/* Does deletes for the last n - 1 tables, returns 0 if ok */
@@ -869,7 +882,7 @@ bool multi_delete::send_eof()
/* compute a total error to know if something failed */
local_error= local_error || error;
-
+ killed_status= (local_error == 0)? THD::NOT_KILLED : thd->killed;
/* reset used flags */
thd->proc_info="end";
@@ -881,18 +894,29 @@ bool multi_delete::send_eof()
{
query_cache_invalidate3(thd, delete_tables, 1);
}
- DBUG_ASSERT(!normal_tables || !deleted || thd->transaction.stmt.modified_non_trans_table);
+ DBUG_ASSERT(!normal_tables || !deleted ||
+ thd->transaction.stmt.modified_non_trans_table);
if ((local_error == 0) || thd->transaction.stmt.modified_non_trans_table)
{
if (mysql_bin_log.is_open())
{
if (local_error == 0)
thd->clear_error();
+<<<<<<< gca sql/sql_delete.cc 1.144.1.57
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ transactional_tables, FALSE);
+ if (mysql_bin_log.write(&qinfo) && !normal_tables)
+<<<<<<< local sql/sql_delete.cc 1.230
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
thd->query, thd->query_length,
transactional_tables, FALSE) &&
!normal_tables)
{
+<<<<<<< remote sql/sql_delete.cc 1.144.1.58
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ transactional_tables, FALSE, killed_status);
+ if (mysql_bin_log.write(&qinfo) && !normal_tables)
+>>>>>>>
local_error=1; // Log write failed: roll back the SQL statement
}
}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 7e438ac3a7c..a631a82be1e 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -3084,10 +3084,19 @@ void select_insert::send_error(uint errcode,const char *err)
bool select_insert::send_eof()
{
+<<<<<<< gca sql/sql_insert.cc 1.146.1.105
+ int error, error2;
+ bool changed, transactional_table= table->file->has_transactions();
+<<<<<<< local sql/sql_insert.cc 1.300
int error;
bool const trans_table= table->file->has_transactions();
ulonglong id;
bool changed;
+<<<<<<< remote sql/sql_insert.cc 1.146.1.106
+ int error, error2;
+ bool changed, transactional_table= table->file->has_transactions();
+ THD::killed_state killed_status= thd->killed;
+>>>>>>>
DBUG_ENTER("select_insert::send_eof");
DBUG_PRINT("enter", ("trans_table=%d, table_type='%s'",
trans_table, table->file->table_type()));
@@ -3120,6 +3129,14 @@ bool select_insert::send_eof()
{
if (!error)
thd->clear_error();
+<<<<<<< gca sql/sql_insert.cc 1.146.1.105
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ transactional_table, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+ if ((error2=ha_autocommit_or_rollback(thd,error)) && ! error)
+ error=error2;
+<<<<<<< local sql/sql_insert.cc 1.300
thd->binlog_query(THD::ROW_QUERY_TYPE,
thd->query, thd->query_length,
trans_table, FALSE);
@@ -3138,6 +3155,14 @@ bool select_insert::send_eof()
}
table->file->ha_release_auto_increment();
+<<<<<<< remote sql/sql_insert.cc 1.146.1.106
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ transactional_table, FALSE, killed_status);
+ mysql_bin_log.write(&qinfo);
+ }
+ if ((error2=ha_autocommit_or_rollback(thd,error)) && ! error)
+ error=error2;
+>>>>>>>
if (error)
{
table->file->print_error(error,MYF(0));
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 23547349a37..3a4df7ccc9b 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -85,7 +85,8 @@ static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
#ifndef EMBEDDED_LIBRARY
static bool write_execute_load_query_log_event(THD *thd,
bool duplicates, bool ignore,
- bool transactional_table);
+ bool transactional_table,
+ THD::killed_state killed_status);
#endif /* EMBEDDED_LIBRARY */
/*
@@ -134,6 +135,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
char *tdb= thd->db ? thd->db : db; // Result is never null
ulong skip_lines= ex->skip_lines;
bool transactional_table;
+ THD::killed_state killed_status= THD::NOT_KILLED;
DBUG_ENTER("mysql_load");
#ifdef EMBEDDED_LIBRARY
@@ -403,7 +405,16 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
free_blobs(table); /* if pack_blob was used */
table->copy_blobs=0;
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
-
+ /*
+ simulated killing in the middle of per-row loop
+ must be effective for binlogging
+ */
+ DBUG_EXECUTE_IF("simulate_kill_bug27571",
+ {
+ error=1;
+ thd->killed= THD::KILL_QUERY;
+ };);
+ killed_status= (error == 0)? THD::NOT_KILLED : thd->killed;
/*
We must invalidate the table in query cache before binlog writing and
ha_autocommit_...
@@ -419,6 +430,12 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (mysql_bin_log.is_open())
{
{
+<<<<<<< gca sql/sql_load.cc 1.78.1.39
+ if (thd->transaction.stmt.modified_non_trans_table)
+ write_execute_load_query_log_event(thd, handle_duplicates,
+ ignore, transactional_table);
+ else
+<<<<<<< local sql/sql_load.cc 1.131
/*
Make sure last block (the one which caused the error) gets
logged. This is needed because otherwise after write of (to
@@ -444,6 +461,13 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
read_info.end_io_cache();
/* If the file was not empty, wrote_create_file is true */
if (lf_info.wrote_create_file)
+<<<<<<< remote sql/sql_load.cc 1.78.1.40
+ if (thd->transaction.stmt.modified_non_trans_table)
+ write_execute_load_query_log_event(thd, handle_duplicates,
+ ignore, transactional_table,
+ killed_status);
+ else
+>>>>>>>
{
if (thd->transaction.stmt.modified_non_trans_table)
write_execute_load_query_log_event(thd, handle_duplicates,
@@ -473,6 +497,16 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (mysql_bin_log.is_open())
{
/*
+<<<<<<< gca sql/sql_load.cc 1.78.1.39
+ As already explained above, we need to call end_io_cache() or the last
+ block will be logged only after Execute_load_query_log_event (which is
+ wrong), when read_info is destroyed.
+ */
+ read_info.end_io_cache();
+ if (lf_info.wrote_create_file)
+ write_execute_load_query_log_event(thd, handle_duplicates,
+ ignore, transactional_table);
+<<<<<<< local sql/sql_load.cc 1.131
We need to do the job that is normally done inside
binlog_query() here, which is to ensure that the pending event
is written before tables are unlocked and before any other
@@ -496,6 +530,17 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
ignore, transactional_table);
}
}
+<<<<<<< remote sql/sql_load.cc 1.78.1.40
+ As already explained above, we need to call end_io_cache() or the last
+ block will be logged only after Execute_load_query_log_event (which is
+ wrong), when read_info is destroyed.
+ */
+ read_info.end_io_cache();
+ if (lf_info.wrote_create_file)
+ write_execute_load_query_log_event(thd, handle_duplicates,
+ ignore, transactional_table,
+ killed_status);
+>>>>>>>
}
#endif /*!EMBEDDED_LIBRARY*/
if (transactional_table)
@@ -523,7 +568,8 @@ err:
/* Not a very useful function; just to avoid duplication of code */
static bool write_execute_load_query_log_event(THD *thd,
bool duplicates, bool ignore,
- bool transactional_table)
+ bool transactional_table,
+ THD::killed_state killed_err_arg)
{
Execute_load_query_log_event
e(thd, thd->query, thd->query_length,
@@ -531,8 +577,14 @@ static bool write_execute_load_query_log_event(THD *thd,
(char*)thd->lex->fname_end - (char*)thd->query,
(duplicates == DUP_REPLACE) ? LOAD_DUP_REPLACE :
(ignore ? LOAD_DUP_IGNORE : LOAD_DUP_ERROR),
+<<<<<<< gca sql/sql_load.cc 1.78.1.39
+ transactional_table, FALSE);
+<<<<<<< local sql/sql_load.cc 1.131
transactional_table, FALSE);
e.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
+<<<<<<< remote sql/sql_load.cc 1.78.1.40
+ transactional_table, FALSE, killed_err_arg);
+>>>>>>>
return mysql_bin_log.write(&e);
}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 0b97930efb9..f07437f044f 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -200,9 +200,18 @@ int mysql_update(THD *thd,
SQL_SELECT *select;
READ_RECORD info;
SELECT_LEX *select_lex= &thd->lex->select_lex;
+<<<<<<< gca sql/sql_update.cc 1.154.2.70
+ bool need_reopen;
+ List<Item> all_fields;
+<<<<<<< local sql/sql_update.cc 1.258
bool need_reopen;
ulonglong id;
List<Item> all_fields;
+<<<<<<< remote sql/sql_update.cc 1.154.2.71
+ bool need_reopen;
+ List<Item> all_fields;
+ THD::killed_state killed_status= THD::NOT_KILLED;
+>>>>>>>
DBUG_ENTER("mysql_update");
for ( ; ; )
@@ -713,11 +722,66 @@ int mysql_update(THD *thd,
table->file->unlock_row();
thd->row_count++;
}
+<<<<<<< gca sql/sql_update.cc 1.154.2.70
+<<<<<<< local sql/sql_update.cc 1.258
dup_key_found= 0;
+<<<<<<< remote sql/sql_update.cc 1.154.2.71
+ /*
+ Caching the killed status to pass as the arg to query event constuctor;
+ The cached value can not change whereas the killed status can
+ (externally) since this point and change of the latter won't affect
+ binlogging.
+ It's assumed that if an error was set in combination with an effective
+ killed status then the error is due to killing.
+ */
+ killed_status= thd->killed; // get the status of the volatile
+ // simulated killing after the loop must be ineffective for binlogging
+ DBUG_EXECUTE_IF("simulate_kill_bug27571",
+ {
+ thd->killed= THD::KILL_QUERY;
+ };);
+ error= (killed_status == THD::NOT_KILLED)? error : 1;
+
+>>>>>>>
if (!transactional_table && updated > 0)
thd->transaction.stmt.modified_non_trans_table= TRUE;
+<<<<<<< gca sql/sql_update.cc 1.154.2.70
+
+ /*
+ todo bug#27571: to avoid asynchronization of `error' and
+ `error_code' of binlog event constructor
+
+ The concept, which is a bit different for insert(!), is to
+ replace `error' assignment with the following lines
+
+ killed_status= thd->killed; // get the status of the volatile
+
+ Notice: thd->killed is type of "state" whereas the lhs has
+ "status" the suffix which translates according to WordNet: a state
+ at a particular time - at the time of the end of per-row loop in
+ our case. Binlogging ops are conducted with the status.
+
+ error= (killed_status == THD::NOT_KILLED)? error : 1;
+
+ which applies to most mysql_$query functions.
+ Event's constructor will accept `killed_status' as an argument:
+
+ Query_log_event qinfo(..., killed_status);
+
+ thd->killed might be changed after killed_status had got cached and this
+ won't affect binlogging event but other effects remain.
+
+ Open issue: In a case the error happened not because of KILLED -
+ and then KILLED was caught later still within the loop - we shall
+ do something to avoid binlogging of incorrect ER_SERVER_SHUTDOWN
+ error_code.
+ */
+
+ if (thd->killed && !error)
+ error= 1; // Aborted
+<<<<<<< local sql/sql_update.cc 1.258
/*
todo bug#27571: to avoid asynchronization of `error' and
@@ -774,6 +838,8 @@ int mysql_update(THD *thd,
if (will_batch)
table->file->end_bulk_update();
table->file->try_semi_consistent_read(0);
+<<<<<<< remote sql/sql_update.cc 1.154.2.71
+>>>>>>>
end_read_record(&info);
delete select;
thd->proc_info= "end";
@@ -803,6 +869,12 @@ int mysql_update(THD *thd,
{
if (error < 0)
thd->clear_error();
+<<<<<<< gca sql/sql_update.cc 1.154.2.70
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ transactional_table, FALSE);
+ if (mysql_bin_log.write(&qinfo) && transactional_table)
+ error=1; // Rollback update
+<<<<<<< local sql/sql_update.cc 1.258
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
thd->query, thd->query_length,
transactional_table, FALSE) &&
@@ -810,6 +882,12 @@ int mysql_update(THD *thd,
{
error=1; // Rollback update
}
+<<<<<<< remote sql/sql_update.cc 1.154.2.71
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ transactional_table, FALSE, killed_status);
+ if (mysql_bin_log.write(&qinfo) && transactional_table)
+ error=1; // Rollback update
+>>>>>>>
}
if (thd->transaction.stmt.modified_non_trans_table)
thd->transaction.all.modified_non_trans_table= TRUE;
@@ -1751,9 +1829,24 @@ void multi_update::send_error(uint errcode,const char *err)
*/
if (mysql_bin_log.is_open())
{
+<<<<<<< gca sql/sql_update.cc 1.154.2.70
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ transactional_tables, FALSE);
+ mysql_bin_log.write(&qinfo);
+<<<<<<< local sql/sql_update.cc 1.258
thd->binlog_query(THD::ROW_QUERY_TYPE,
thd->query, thd->query_length,
transactional_tables, FALSE);
+<<<<<<< remote sql/sql_update.cc 1.154.2.71
+ /*
+ THD::killed status might not have been set ON at time of an error
+ got caught and if happens later the killed error is written
+ into repl event.
+ */
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ transactional_tables, FALSE);
+ mysql_bin_log.write(&qinfo);
+>>>>>>>
}
thd->transaction.all.modified_non_trans_table= TRUE;
}
@@ -1946,12 +2039,25 @@ err2:
bool multi_update::send_eof()
{
char buff[STRING_BUFFER_USUAL_SIZE];
+<<<<<<< gca sql/sql_update.cc 1.154.2.70
+<<<<<<< local sql/sql_update.cc 1.258
ulonglong id;
DBUG_ENTER("multi_update::send_eof");
+<<<<<<< remote sql/sql_update.cc 1.154.2.71
+ THD::killed_state killed_status= THD::NOT_KILLED;
+>>>>>>>
thd->proc_info="updating reference tables";
- /* Does updates for the last n - 1 tables, returns 0 if ok */
+ /*
+ Does updates for the last n - 1 tables, returns 0 if ok;
+ error takes into account killed status gained in do_updates()
+ */
int local_error = (table_count) ? do_updates(0) : 0;
+ /*
+ if local_error is not set ON until after do_updates() then
+ later carried out killing should not affect binlogging.
+ */
+ killed_status= (local_error == 0)? THD::NOT_KILLED : thd->killed;
thd->proc_info= "end";
/* We must invalidate the query cache before binlog writing and
@@ -1978,6 +2084,12 @@ bool multi_update::send_eof()
{
if (local_error == 0)
thd->clear_error();
+<<<<<<< gca sql/sql_update.cc 1.154.2.70
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ transactional_tables, FALSE);
+ if (mysql_bin_log.write(&qinfo) && trans_safe)
+ local_error= 1; // Rollback update
+<<<<<<< local sql/sql_update.cc 1.258
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
thd->query, thd->query_length,
transactional_tables, FALSE) &&
@@ -1985,6 +2097,12 @@ bool multi_update::send_eof()
{
local_error= 1; // Rollback update
}
+<<<<<<< remote sql/sql_update.cc 1.154.2.71
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ transactional_tables, FALSE, killed_status);
+ if (mysql_bin_log.write(&qinfo) && trans_safe)
+ local_error= 1; // Rollback update
+>>>>>>>
}
if (thd->transaction.stmt.modified_non_trans_table)
thd->transaction.all.modified_non_trans_table= TRUE;