diff options
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r-- | sql/sql_table.cc | 55 |
1 files changed, 44 insertions, 11 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e0e778a6baf..45d9c5dc091 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2207,6 +2207,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, bool non_tmp_error= 0; bool trans_tmp_table_deleted= 0, non_trans_tmp_table_deleted= 0; bool non_tmp_table_deleted= 0; + bool is_drop_tmp_if_exists_added= 0; String built_query; String built_trans_tmp_query, built_non_trans_tmp_query; DBUG_ENTER("mysql_rm_table_no_locks"); @@ -2236,6 +2237,15 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, table stems from the fact that such drop does not commit an ongoing transaction and changes to non-transactional tables must be written ahead of the transaction in some circumstances. + + 6- Slave SQL thread ignores all replicate-* filter rules + for temporary tables with 'IF EXISTS' clause. (See sql/sql_parse.cc: + mysql_execute_command() for details). These commands will be binlogged + as they are, even if the default database (from USE `db`) is not present + on the Slave. This can cause point in time recovery failures later + when user uses the slave's binlog to re-apply. Hence at the time of binary + logging, these commands will be written with fully qualified table names + and use `db` will be suppressed. */ if (!dont_log_query) { @@ -2259,6 +2269,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, if (thd->is_current_stmt_binlog_format_row() || if_exists) { + is_drop_tmp_if_exists_added= true; built_trans_tmp_query.set_charset(system_charset_info); built_trans_tmp_query.append("DROP TEMPORARY TABLE IF EXISTS "); built_non_trans_tmp_query.set_charset(system_charset_info); @@ -2335,10 +2346,12 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, String *built_ptr_query= (is_trans ? &built_trans_tmp_query : &built_non_trans_tmp_query); /* - Don't write the database name if it is the current one (or if - thd->db is NULL). + Write the database name if it is not the current one or if + thd->db is NULL or 'IF EXISTS' clause is present in 'DROP TEMPORARY' + query. */ - if (thd->db == NULL || strcmp(db,thd->db) != 0) + if (thd->db == NULL || strcmp(db,thd->db) != 0 + || is_drop_tmp_if_exists_added ) { append_identifier(thd, built_ptr_query, db, db_length); built_ptr_query->append("."); @@ -2553,7 +2566,9 @@ err: error |= thd->binlog_query(THD::STMT_QUERY_TYPE, built_non_trans_tmp_query.ptr(), built_non_trans_tmp_query.length(), - FALSE, FALSE, FALSE, 0); + FALSE, FALSE, + is_drop_tmp_if_exists_added, + 0); } if (trans_tmp_table_deleted) { @@ -2563,7 +2578,9 @@ err: error |= thd->binlog_query(THD::STMT_QUERY_TYPE, built_trans_tmp_query.ptr(), built_trans_tmp_query.length(), - TRUE, FALSE, FALSE, 0); + TRUE, FALSE, + is_drop_tmp_if_exists_added, + 0); } if (non_tmp_table_deleted) { @@ -5202,7 +5219,6 @@ int mysql_discard_or_import_tablespace(THD *thd, error= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); err: - trans_rollback_stmt(thd); thd->tablespace_op=FALSE; if (error == 0) @@ -9059,6 +9075,12 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, Protocol *protocol= thd->protocol; DBUG_ENTER("mysql_checksum_table"); + /* + CHECKSUM TABLE returns results and rollbacks statement transaction, + so it should not be used in stored function or trigger. + */ + DBUG_ASSERT(! thd->in_sub_stmt); + field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2)); item->maybe_null= 1; field_list.push_back(item= new Item_int("Checksum", @@ -9097,7 +9119,6 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, open_and_lock_tables(thd, table, FALSE, 0)) { t= NULL; - thd->clear_error(); // these errors shouldn't get client } else t= table->table; @@ -9111,7 +9132,6 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, { /* Table didn't exist */ protocol->store_null(); - thd->clear_error(); } else { @@ -9199,11 +9219,24 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, t->file->ha_rnd_end(); } } - thd->clear_error(); - if (! thd->in_sub_stmt) - trans_rollback_stmt(thd); + trans_rollback_stmt(thd); close_thread_tables(thd); } + + if (thd->transaction_rollback_request) + { + /* + If transaction rollback was requested we honor it. To do this we + abort statement and return error as not only CHECKSUM TABLE is + rolled back but the whole transaction in which it was used. + */ + thd->protocol->remove_last_row(); + goto err; + } + + /* Hide errors from client. Return NULL for problematic tables instead. */ + thd->clear_error(); + if (protocol->write()) goto err; } |