diff options
Diffstat (limited to 'sql/sql_rename.cc')
-rw-r--r-- | sql/sql_rename.cc | 145 |
1 files changed, 82 insertions, 63 deletions
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 1b1d138546c..620b5ef3d75 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -19,6 +19,7 @@ Atomic rename of table; RENAME TABLE t1 to t2, tmp to t1 [,...] */ +#include <my_global.h> #include "sql_priv.h" #include "unireg.h" #include "sql_rename.h" @@ -29,16 +30,19 @@ #include "lock.h" // MYSQL_OPEN_SKIP_TEMPORARY #include "sql_base.h" // tdc_remove_table, lock_table_names, #include "sql_handler.h" // mysql_ha_rm_tables -#include "datadict.h" +#include "sql_statistics.h" static TABLE_LIST *rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error); +static bool do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, + char *new_table_name, char *new_table_alias, + bool skip_error); static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list); /* - Every second entry in the table_list is the original name and every - second entry is the new name. + Every two entries in the table_list form a pair of original name and + the new name. */ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) @@ -81,12 +85,8 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) 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))) + int log_table_rename; + if ((log_table_rename= check_if_log_table(ren_table, TRUE, NullS))) { /* as we use log_table_rename as an array index, we need it to start @@ -142,13 +142,9 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) } if (lock_table_names(thd, table_list, 0, thd->variables.lock_wait_timeout, - MYSQL_OPEN_SKIP_TEMPORARY)) + 0)) goto err; - for (ren_table= table_list; ren_table; ren_table= ren_table->next_local) - tdc_remove_table(thd, TDC_RT_REMOVE_ALL, ren_table->db, - ren_table->table_name, FALSE); - error=0; /* An exclusive lock on table names is satisfactory to ensure @@ -216,6 +212,28 @@ static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list) } +static bool +do_rename_temporary(THD *thd, TABLE_LIST *ren_table, TABLE_LIST *new_table, + bool skip_error) +{ + const char *new_alias; + DBUG_ENTER("do_rename_temporary"); + + new_alias= (lower_case_table_names == 2) ? new_table->alias : + new_table->table_name; + + if (find_temporary_table(thd, new_table)) + { + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias); + DBUG_RETURN(1); // This can't be skipped + } + + + DBUG_RETURN(rename_temporary_table(thd, ren_table->table, + new_table->db, new_alias)); +} + + /* Rename a single table or a view @@ -236,16 +254,13 @@ static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list) true rename failed */ -bool +static bool do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name, char *new_table_alias, bool skip_error) { int rc= 1; - char new_name[FN_REFLEN + 1], old_name[FN_REFLEN + 1]; + handlerton *hton; const char *new_alias, *old_alias; - frm_type_enum frm_type; - enum legacy_db_type table_type; - DBUG_ENTER("do_rename"); if (lower_case_table_names == 2) @@ -260,47 +275,49 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name, } DBUG_ASSERT(new_alias); - build_table_filename(new_name, sizeof(new_name) - 1, - new_db, new_alias, reg_ext, 0); - build_table_filename(old_name, sizeof(old_name) - 1, - ren_table->db, old_alias, reg_ext, 0); - if (check_table_file_presence(old_name, - new_name, new_db, new_alias, new_alias, TRUE)) + if (ha_table_exists(thd, new_db, new_alias)) { - DBUG_RETURN(1); // This can't be skipped + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias); + DBUG_RETURN(1); // This can't be skipped } - frm_type= dd_frm_type(thd, old_name, &table_type); - switch (frm_type) + if (ha_table_exists(thd, ren_table->db, old_alias, &hton) && hton) { - case FRMTYPE_TABLE: + DBUG_ASSERT(!thd->locked_tables_mode); + tdc_remove_table(thd, TDC_RT_REMOVE_ALL, + ren_table->db, ren_table->table_name, false); + + if (hton != view_pseudo_hton) + { + if (!(rc= mysql_rename_table(hton, ren_table->db, old_alias, + new_db, new_alias, 0))) { - if (!(rc= mysql_rename_table(ha_resolve_by_legacy_type(thd, - table_type), - ren_table->db, old_alias, - new_db, new_alias, 0))) + LEX_STRING db_name= { ren_table->db, ren_table->db_length }; + LEX_STRING table_name= { ren_table->table_name, + ren_table->table_name_length }; + LEX_STRING new_table= { (char *) new_alias, strlen(new_alias) }; + LEX_STRING new_db_name= { (char*)new_db, strlen(new_db)}; + (void) rename_table_in_stat_tables(thd, &db_name, &table_name, + &new_db_name, &new_table); + if ((rc= Table_triggers_list::change_table_name(thd, ren_table->db, + old_alias, + ren_table->table_name, + new_db, + new_alias))) { - if ((rc= Table_triggers_list::change_table_name(thd, ren_table->db, - old_alias, - ren_table->table_name, - new_db, - new_alias))) - { - /* - We've succeeded in renaming table's .frm and in updating - corresponding handler data, but have failed to update table's - triggers appropriately. So let us revert operations on .frm - and handler's data and report about failure to rename table. - */ - (void) mysql_rename_table(ha_resolve_by_legacy_type(thd, - table_type), - new_db, new_alias, - ren_table->db, old_alias, NO_FK_CHECKS); - } + /* + We've succeeded in renaming table's .frm and in updating + corresponding handler data, but have failed to update table's + triggers appropriately. So let us revert operations on .frm + and handler's data and report about failure to rename table. + */ + (void) mysql_rename_table(hton, new_db, new_alias, + ren_table->db, old_alias, NO_FK_CHECKS); } } - break; - case FRMTYPE_VIEW: + } + else + { /* change of schema is not allowed except of ALTER ...UPGRADE DATA DIRECTORY NAME command @@ -308,23 +325,22 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name, */ if (thd->lex->sql_command != SQLCOM_ALTER_DB_UPGRADE && strcmp(ren_table->db, new_db)) - my_error(ER_FORBID_SCHEMA_CHANGE, MYF(0), ren_table->db, - new_db); + my_error(ER_FORBID_SCHEMA_CHANGE, MYF(0), ren_table->db, new_db); else rc= mysql_rename_view(thd, new_db, new_alias, ren_table); - break; - default: - DBUG_ASSERT(0); // should never happen - case FRMTYPE_ERROR: - my_error(ER_FILE_NOT_FOUND, MYF(0), old_name, my_errno); - break; + } + } + else + { + my_error(ER_NO_SUCH_TABLE, MYF(0), ren_table->db, old_alias); } if (rc && !skip_error) DBUG_RETURN(1); DBUG_RETURN(0); - } + + /* Rename all tables in list; Return pointer to wrong entry if something goes wrong. Note that the table_list may be empty! @@ -359,8 +375,11 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error) for (ren_table= table_list; ren_table; ren_table= new_table->next_local) { new_table= ren_table->next_local; - if (do_rename(thd, ren_table, new_table->db, new_table->table_name, - new_table->alias, skip_error)) + + if (is_temporary_table(ren_table) ? + do_rename_temporary(thd, ren_table, new_table, skip_error) : + do_rename(thd, ren_table, new_table->db, new_table->table_name, + new_table->alias, skip_error)) DBUG_RETURN(ren_table); } DBUG_RETURN(0); |