Skip to content

Commit

Permalink
MDEV-35854: Clarify row_rename_table_for_mysql()
Browse files Browse the repository at this point in the history
enum rename_fk: Replaces the "bool use_fk" parameter of
row_rename_table_for_mysql() and innobase_rename_table():

RENAME_IGNORE_FK: Replaces use_fk=false when the operation cannot
involve any FOREIGN KEY constraints, that is, it is a partitioned
table or an internal table for FULLTEXT INDEX.

RENAME_REBUILD: Replaces use_fk=false when the table may contain
FOREIGN KEY constraints, which must not be modified in the data
dictionary tables SYS_FOREIGN and SYS_FOREIGN_COLS.

RENAME_ALTER_COPY: Replaces use_fk=true. This is only specified
in ha_innobase::rename_table(), which may be invoked as part of
ALTER TABLE…ALGORITHM=COPY, but also during RENAME TABLE.

An alternative value RENAME_FK could be useful to specify in
ha_innobase::rename_table() when it is executed as part of
CREATE OR REPLACE TABLE, which currently is not an atomic operation.

Reviewed by: Debarun Banerjee
  • Loading branch information
dr-m committed Jan 23, 2025
1 parent d4da659 commit 2543be6
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 18 deletions.
4 changes: 2 additions & 2 deletions storage/innobase/fts/fts0fts.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1392,7 +1392,7 @@ static dberr_t fts_drop_table(trx_t *trx, const char *table_name, bool rename)
char *tmp= dict_mem_create_temporary_tablename(heap, table->name.m_name,
table->id);
dberr_t err= row_rename_table_for_mysql(table->name.m_name, tmp, trx,
false);
RENAME_IGNORE_FK);
mem_heap_free(heap);
if (err != DB_SUCCESS)
{
Expand Down Expand Up @@ -1450,7 +1450,7 @@ fts_rename_one_aux_table(
fts_table_new_name[table_new_name_len] = 0;

return row_rename_table_for_mysql(
fts_table_old_name, fts_table_new_name, trx, false);
fts_table_old_name, fts_table_new_name, trx, RENAME_IGNORE_FK);
}

/****************************************************************//**
Expand Down
15 changes: 9 additions & 6 deletions storage/innobase/handler/ha_innodb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13889,10 +13889,10 @@ int ha_innobase::delete_table(const char *name)
@param[in,out] trx InnoDB data dictionary transaction
@param[in] from old table name
@param[in] to new table name
@param[in] use_fk whether to enforce FOREIGN KEY
@param[in] fk how to handle FOREIGN KEY
@return DB_SUCCESS or error code */
static dberr_t innobase_rename_table(trx_t *trx, const char *from,
const char *to, bool use_fk)
const char *to, rename_fk fk)
{
dberr_t error;
char norm_to[FN_REFLEN];
Expand All @@ -13910,7 +13910,7 @@ static dberr_t innobase_rename_table(trx_t *trx, const char *from,

ut_ad(trx->will_lock);

error = row_rename_table_for_mysql(norm_from, norm_to, trx, use_fk);
error = row_rename_table_for_mysql(norm_from, norm_to, trx, fk);

if (error != DB_SUCCESS) {
if (error == DB_TABLE_NOT_FOUND
Expand All @@ -13936,7 +13936,8 @@ static dberr_t innobase_rename_table(trx_t *trx, const char *from,
#endif /* _WIN32 */
trx_start_if_not_started(trx, true);
error = row_rename_table_for_mysql(
par_case_name, norm_to, trx, false);
par_case_name, norm_to, trx,
RENAME_IGNORE_FK);
}
}

Expand Down Expand Up @@ -14132,7 +14133,8 @@ int ha_innobase::truncate()

if (error == DB_SUCCESS)
{
error= innobase_rename_table(trx, ib_table->name.m_name, temp_name, false);
error= innobase_rename_table(trx, ib_table->name.m_name, temp_name,
RENAME_REBUILD);
if (error == DB_SUCCESS)
error= trx->drop_table(*ib_table);
}
Expand Down Expand Up @@ -14330,7 +14332,8 @@ ha_innobase::rename_table(
row_mysql_lock_data_dictionary(trx);

if (error == DB_SUCCESS) {
error = innobase_rename_table(trx, from, to, true);
error = innobase_rename_table(trx, from, to,
RENAME_ALTER_COPY);
}

DEBUG_SYNC(thd, "after_innobase_rename_table");
Expand Down
6 changes: 4 additions & 2 deletions storage/innobase/handler/handler0alter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10414,10 +10414,12 @@ commit_try_rebuild(
char* old_name= mem_heap_strdup(ctx->heap, user_table->name.m_name);

dberr_t error = row_rename_table_for_mysql(user_table->name.m_name,
ctx->tmp_name, trx, false);
ctx->tmp_name, trx,
RENAME_REBUILD);
if (error == DB_SUCCESS) {
error = row_rename_table_for_mysql(
rebuilt_table->name.m_name, old_name, trx, false);
rebuilt_table->name.m_name, old_name, trx,
RENAME_REBUILD);
if (error == DB_SUCCESS) {
/* The statistics for the surviving indexes will be
re-inserted in alter_stats_rebuild(). */
Expand Down
11 changes: 10 additions & 1 deletion storage/innobase/include/row0mysql.h
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,15 @@ row_import_tablespace_for_mysql(
row_prebuilt_t* prebuilt) /*!< in: prebuilt struct in MySQL */
MY_ATTRIBUTE((nonnull, warn_unused_result));

enum rename_fk {
/** ignore FOREIGN KEY constraints */
RENAME_IGNORE_FK= 0,
/** Rename a table as part of a native table-rebuilding DDL operation */
RENAME_REBUILD,
/** Rename as part of ALTER TABLE...ALGORITHM=COPY */
RENAME_ALTER_COPY
};

/*********************************************************************//**
Renames a table for MySQL.
@return error code or DB_SUCCESS */
Expand All @@ -379,7 +388,7 @@ row_rename_table_for_mysql(
const char* old_name, /*!< in: old table name */
const char* new_name, /*!< in: new table name */
trx_t* trx, /*!< in/out: transaction */
bool use_fk) /*!< in: whether to parse and enforce
rename_fk fk) /*!< in: how to handle
FOREIGN KEY constraints */
MY_ATTRIBUTE((nonnull, warn_unused_result));

Expand Down
15 changes: 8 additions & 7 deletions storage/innobase/row/row0mysql.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2554,7 +2554,7 @@ row_rename_table_for_mysql(
const char* old_name, /*!< in: old table name */
const char* new_name, /*!< in: new table name */
trx_t* trx, /*!< in/out: transaction */
bool use_fk) /*!< in: whether to parse and enforce
rename_fk fk) /*!< in: how to handle
FOREIGN KEY constraints */
{
dict_table_t* table = NULL;
Expand All @@ -2579,6 +2579,8 @@ row_rename_table_for_mysql(
old_is_tmp = dict_table_t::is_temporary_name(old_name);
new_is_tmp = dict_table_t::is_temporary_name(new_name);

ut_ad(fk != RENAME_IGNORE_FK || !new_is_tmp);

table = dict_table_open_on_name(old_name, true,
DICT_ERR_IGNORE_FK_NOKEY);

Expand Down Expand Up @@ -2638,10 +2640,9 @@ row_rename_table_for_mysql(
<< TROUBLESHOOTING_MSG;

goto funct_exit;

} else if (use_fk && !old_is_tmp && new_is_tmp) {
/* MySQL is doing an ALTER TABLE command and it renames the
original table to a temporary table name. We want to preserve
} else if (fk == RENAME_ALTER_COPY && !old_is_tmp && new_is_tmp) {
/* Non-native ALTER TABLE is renaming the
original table to a temporary name. We want to preserve
the original foreign key constraint definitions despite the
name change. An exception is those constraints for which
the ALTER TABLE contained DROP FOREIGN KEY <foreign key id>.*/
Expand Down Expand Up @@ -2685,7 +2686,7 @@ row_rename_table_for_mysql(
goto rollback_and_exit;
}

if (!new_is_tmp) {
if (/* fk == RENAME_IGNORE_FK || */ !new_is_tmp) {
/* Rename all constraints. */
char new_table_name[MAX_TABLE_NAME_LEN + 1];
char old_table_utf8[MAX_TABLE_NAME_LEN + 1];
Expand Down Expand Up @@ -2859,7 +2860,7 @@ row_rename_table_for_mysql(
err = dict_load_foreigns(
new_name, nullptr, trx->id,
!old_is_tmp || trx->check_foreigns,
use_fk
fk == RENAME_ALTER_COPY
? DICT_ERR_IGNORE_NONE
: DICT_ERR_IGNORE_FK_NOKEY,
fk_tables);
Expand Down

0 comments on commit 2543be6

Please sign in to comment.