diff options
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r-- | sql/sql_table.cc | 180 |
1 files changed, 158 insertions, 22 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0e811d63b36..3ac0d3ae466 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -22,6 +22,7 @@ #include <my_dir.h> #include "sp_head.h" #include "sql_trigger.h" +#include "sql_show.h" #ifdef __WIN__ #include <io.h> @@ -53,14 +54,15 @@ static bool check_engine(THD *thd, const char *table_name, file */ -static void write_bin_log(THD *thd, bool clear_error) +static void write_bin_log(THD *thd, bool clear_error, + char const* query, ulong query_length) { if (mysql_bin_log.is_open()) { if (clear_error) thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE); - mysql_bin_log.write(&qinfo); + thd->binlog_query(THD::STMT_QUERY_TYPE, + query, query_length, FALSE, FALSE); } } @@ -277,9 +279,19 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, char path[FN_REFLEN], *alias; String wrong_tables; int error; + int non_temp_tables_count= 0; bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0; + String built_query; DBUG_ENTER("mysql_rm_table_part2"); + if (binlog_row_based && !dont_log_query) + { + built_query.set_charset(system_charset_info); + if (if_exists) + built_query.append("DROP TABLE IF EXISTS "); + else + built_query.append("DROP TABLE "); + } /* If we have the table in the definition cache, we don't have to check the .frm file to find if the table is a normal table (not view) and what @@ -313,6 +325,30 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, continue; // removed temporary table } + /* + If row-based replication is used and the table is not a + temporary table, we add the table name to the drop statement + being built. The string always end in a comma and the comma + will be chopped off before being written to the binary log. + */ + if (binlog_row_based && !dont_log_query) + { + ++non_temp_tables_count; + /* + Don't write the database name if it is the current one (or if + thd->db is NULL). + */ + built_query.append("`"); + if (thd->db == NULL || strcmp(db,thd->db) != 0) + { + built_query.append(db); + built_query.append("`.`"); + } + + built_query.append(table->table_name); + built_query.append("`,"); + } + error=0; table_type= table->db_type; if (!drop_temporary) @@ -401,12 +437,48 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, if (some_tables_deleted || tmp_table_deleted || !error) { query_cache_invalidate3(thd, tables, 0); - if (!dont_log_query && mysql_bin_log.is_open()) + if (!dont_log_query) { - if (!error) - thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE); - mysql_bin_log.write(&qinfo); + if (!binlog_row_based || + non_temp_tables_count > 0 && !tmp_table_deleted) + { + /* + In this case, we are either using statement-based + replication or using row-based replication but have only + deleted one or more non-temporary tables (and no temporary + tables). In this case, we can write the original query into + the binary log. + */ + write_bin_log(thd, !error, thd->query, thd->query_length); + } + else if (binlog_row_based && + non_temp_tables_count > 0 && + tmp_table_deleted) + { + /* + In this case we have deleted both temporary and + non-temporary tables, so: + - since we have deleted a non-temporary table we have to + binlog the statement, but + - since we have deleted a temporary table we cannot binlog + the statement (since the table has not been created on the + slave, this might cause the slave to stop). + + Instead, we write a built statement, only containing the + non-temporary tables, to the binary log + */ + built_query.chop(); // Chop of the last comma + built_query.append(" /* generated by server */"); + write_bin_log(thd, !error, built_query.ptr(), built_query.length()); + } + /* + The remaining cases are: + - no tables where deleted and + - only temporary tables where deleted and row-based + replication is used. + In both these cases, nothing should be written to the binary + log. + */ } } @@ -1837,13 +1909,17 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name, } thd->tmp_table_used= 1; } - if (!internal_tmp_table && mysql_bin_log.is_open()) - { - thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE); - mysql_bin_log.write(&qinfo); - } + /* + Don't write statement if: + - It is an internal temporary table, + - Row-based logging is used and it we are creating a temporary table, or + - The binary log is not open. + */ + if (!internal_tmp_table && + !(binlog_row_based && + (create_info->options & HA_LEX_CREATE_TMP_TABLE))) + write_bin_log(thd, TRUE, thd->query, thd->query_length); error= FALSE; unlock_and_end: VOID(pthread_mutex_unlock(&LOCK_open)); @@ -2982,8 +3058,63 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, goto err; /* purecov: inspected */ } - // Must be written before unlock - write_bin_log(thd, TRUE); + /* + We have to write the query before we unlock the tables. + */ + if (binlog_row_based) + { + /* + Since temporary tables are not replicated under row-based + replication, CREATE TABLE ... LIKE ... needs special + treatement. We have four cases to consider, according to the + following decision table: + + ==== ========= ========= ============================== + Case Target Source Write to binary log + ==== ========= ========= ============================== + 1 normal normal Original statement + 2 normal temporary Generated statement + 3 temporary normal Nothing + 4 temporary temporary Nothing + ==== ========= ========= ============================== + + The variable 'tmp_table' below is used to see if the source + table is a temporary table: if it is set, then the source table + was a temporary table and we can take apropriate actions. + */ + if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) + { + if (tmp_table) // Case 2 + { + char buf[2048]; + String query(buf, sizeof(buf), system_charset_info); + query.length(0); // Have to zero it since constructor doesn't + TABLE *table_ptr; + int error; + + /* + Let's open and lock the table: it will be closed (and + unlocked) by close_thread_tables() at the end of the + statement anyway. + */ + if (!(table_ptr= open_ltable(thd, table, TL_READ_NO_INSERT))) + goto err; + + int result= store_create_info(thd, table, &query, create_info); + + DBUG_ASSERT(result == 0); // store_create_info() always return 0 + write_bin_log(thd, TRUE, query.ptr(), query.length()); + } + else // Case 1 + write_bin_log(thd, TRUE, thd->query, thd->query_length); + } + /* + Case 3 and 4 does nothing under RBR + */ + } + else if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) + write_bin_log(thd, TRUE, thd->query, thd->query_length); + res= FALSE; goto err; @@ -3089,7 +3220,7 @@ mysql_discard_or_import_tablespace(THD *thd, error=1; if (error) goto err; - write_bin_log(thd, FALSE); + write_bin_log(thd, FALSE, thd->query, thd->query_length); err: close_thread_tables(thd); thd->tablespace_op=FALSE; @@ -4057,7 +4188,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, } if (!error) { - write_bin_log(thd, TRUE); + write_bin_log(thd, TRUE, thd->query, thd->query_length); if (do_send_ok) send_ok(thd); } @@ -4472,7 +4603,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if (!error) { close_thread_tables(thd); - write_bin_log(thd, FALSE); + write_bin_log(thd, FALSE, thd->query, thd->query_length); send_ok(thd); DBUG_RETURN(FALSE); } @@ -4609,7 +4740,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, my_free((gptr) new_table,MYF(0)); goto err; } - write_bin_log(thd, TRUE); + /* We don't replicate alter table statement on temporary tables */ + if (!binlog_row_based) + write_bin_log(thd, TRUE, thd->query, thd->query_length); goto end_temporary; } @@ -4751,7 +4884,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, goto err; } thd->proc_info="end"; - write_bin_log(thd, TRUE); + + DBUG_ASSERT(!(mysql_bin_log.is_open() && binlog_row_based && + (create_info->options & HA_LEX_CREATE_TMP_TABLE))); + write_bin_log(thd, TRUE, thd->query, thd->query_length); VOID(pthread_cond_broadcast(&COND_refresh)); VOID(pthread_mutex_unlock(&LOCK_open)); /* @@ -4928,7 +5064,7 @@ copy_data_between_tables(TABLE *from,TABLE *to, { copy_ptr->do_copy(copy_ptr); } - if ((error=to->file->write_row((byte*) to->record[0]))) + if ((error=to->file->ha_write_row((byte*) to->record[0]))) { if ((!ignore && handle_duplicates != DUP_REPLACE) || |