summaryrefslogtreecommitdiff
path: root/sql/sql_rename.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_rename.cc')
-rw-r--r--sql/sql_rename.cc138
1 files changed, 117 insertions, 21 deletions
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index f6766aec285..f34ec83b29c 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -31,10 +31,13 @@ static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list);
second entry is the new name.
*/
-bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
+bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
{
bool error= 1;
TABLE_LIST *ren_table= 0;
+ int to_table;
+ char *rename_log_table[2]= {NULL, NULL};
+ int disable_logs= 0;
DBUG_ENTER("mysql_rename_tables");
/*
@@ -51,6 +54,96 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
if (wait_if_global_read_lock(thd,0,1))
DBUG_RETURN(1);
+
+ if (logger.is_log_table_enabled(QUERY_LOG_GENERAL) ||
+ logger.is_log_table_enabled(QUERY_LOG_SLOW))
+ {
+
+ /*
+ Rules for rename of a log table:
+
+ IF 1. Log tables are enabled
+ AND 2. Rename operates on the log table and nothing is being
+ renamed to the log table.
+ DO 3. Throw an error message.
+ ELSE 4. Perform rename.
+ */
+
+ for (to_table= 0, ren_table= table_list; ren_table;
+ to_table= 1 - to_table, ren_table= ren_table->next_local)
+ {
+ int log_table_rename= 0;
+
+ if ((log_table_rename=
+ check_if_log_table(ren_table->db_length, ren_table->db,
+ ren_table->table_name_length,
+ ren_table->table_name, 1)))
+ {
+ /*
+ Log table encoutered we will need to disable and lock logs
+ for duration of rename.
+ */
+ disable_logs= TRUE;
+
+ /*
+ as we use log_table_rename as an array index, we need it to start
+ with 0, while QUERY_LOG_SLOW == 1 and QUERY_LOG_GENERAL == 2.
+ So, we shift the value to start with 0;
+ */
+ log_table_rename--;
+ if (rename_log_table[log_table_rename])
+ {
+ if (to_table)
+ rename_log_table[log_table_rename]= NULL;
+ else
+ {
+ /*
+ Two renames of "log_table TO" w/o rename "TO log_table" in
+ between.
+ */
+ my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), ren_table->table_name,
+ ren_table->table_name);
+ DBUG_RETURN(1);
+ }
+ }
+ else
+ {
+ if (to_table)
+ {
+ /*
+ Attempt to rename a table TO log_table w/o renaming
+ log_table TO some table.
+ */
+ my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), ren_table->table_name,
+ ren_table->table_name);
+ DBUG_RETURN(1);
+ }
+ else
+ {
+ /* save the name of the log table to report an error */
+ rename_log_table[log_table_rename]= ren_table->table_name;
+ }
+ }
+ }
+ }
+ if (rename_log_table[0] || rename_log_table[1])
+ {
+ if (rename_log_table[0])
+ my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), rename_log_table[0],
+ rename_log_table[0]);
+ else
+ my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), rename_log_table[1],
+ rename_log_table[1]);
+ DBUG_RETURN(1);
+ }
+
+ if (disable_logs)
+ {
+ logger.lock();
+ logger.tmp_close_log_tables(thd);
+ }
+ }
+
VOID(pthread_mutex_lock(&LOCK_open));
if (lock_table_names(thd, table_list))
goto err;
@@ -79,13 +172,13 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
}
/* Lets hope this doesn't fail as the result will be messy */
- if (!error)
+ if (!silent && !error)
{
if (mysql_bin_log.is_open())
{
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
- mysql_bin_log.write(&qinfo);
+ thd->binlog_query(THD::STMT_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
}
send_ok(thd);
}
@@ -94,6 +187,13 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
err:
pthread_mutex_unlock(&LOCK_open);
+ /* enable logging back if needed */
+ if (disable_logs)
+ {
+ if (logger.reopen_log_tables())
+ error= TRUE;
+ logger.unlock();
+ }
start_waiting_global_read_lock(thd);
DBUG_RETURN(error);
}
@@ -152,7 +252,7 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name,
char name[FN_REFLEN];
const char *new_alias, *old_alias;
frm_type_enum frm_type;
- db_type table_type;
+ enum legacy_db_type table_type;
DBUG_ENTER("do_rename");
@@ -166,30 +266,25 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name,
old_alias= ren_table->table_name;
new_alias= new_table_name;
}
- sprintf(name,"%s/%s/%s%s",mysql_data_home,
- new_db, new_alias, reg_ext);
- unpack_filename(name, name);
+ build_table_filename(name, sizeof(name),
+ new_db, new_alias, reg_ext, 0);
if (!access(name,F_OK))
{
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
DBUG_RETURN(1); // This can't be skipped
}
- sprintf(name,"%s/%s/%s%s",mysql_data_home,
- ren_table->db, old_alias,
- reg_ext);
- unpack_filename(name, name);
+ build_table_filename(name, sizeof(name),
+ ren_table->db, old_alias, reg_ext, 0);
frm_type= mysql_frm_type(thd, name, &table_type);
switch (frm_type)
{
case FRMTYPE_TABLE:
- {
- if (table_type == DB_TYPE_UNKNOWN)
- my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno);
- else
{
- if (!(rc= mysql_rename_table(table_type, ren_table->db, old_alias,
- new_db, new_alias)))
+ if (!(rc= mysql_rename_table(ha_resolve_by_legacy_type(thd,
+ table_type),
+ ren_table->db, old_alias,
+ new_db, new_alias, 0)))
{
if ((rc= Table_triggers_list::change_table_name(thd, ren_table->db,
old_alias,
@@ -202,13 +297,14 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name,
triggers appropriately. So let us revert operations on .frm
and handler's data and report about failure to rename table.
*/
- (void) mysql_rename_table(table_type, new_db, new_alias,
- ren_table->db, old_alias);
+ (void) mysql_rename_table(ha_resolve_by_legacy_type(thd,
+ table_type),
+ new_db, new_alias,
+ ren_table->db, old_alias, 0);
}
}
}
break;
- }
case FRMTYPE_VIEW:
/* change of schema is not allowed */
if (strcmp(ren_table->db, new_db))