mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
WL#1012: All changes as one single changeset.
This includes both code and test cases.
This commit is contained in:
180
sql/sql_table.cc
180
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) ||
|
||||
|
Reference in New Issue
Block a user