summaryrefslogtreecommitdiff
path: root/sql/sql_table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r--sql/sql_table.cc180
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) ||