1
0
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:
lars@mysql.com
2005-12-22 06:39:02 +01:00
parent 0f8f444b8b
commit ad126d90e0
447 changed files with 34742 additions and 3216 deletions

View File

@ -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) ||