Skip to content

Commit 3c578b0

Browse files
montywivuvova
authored andcommitted
Check if we can rename triggers before doing an ALTER TABLE ... RENAME
ALTER TABLE .. RENAME, when used with the inplace algorithm, does: - Do an inplace or online alter to the new definition - Rename to new name - Update triggers. If update triggers would fail, we would rename the table back. The problem with this approach is that the table would have the new definition but the rename would fail. The binary log would also not be updated. The solution to this is to very early check if we can rename triggers and give an error if this would fail. Both ALTER TABLE ... RENAME and RENAME TABLE is fixed. This was implemented by moving the pre-check of rename table in triggers from Table_triggers_list::change_table_name() to Table_triggers_list::prepare_for_rename().
1 parent c844a76 commit 3c578b0

File tree

5 files changed

+176
-63
lines changed

5 files changed

+176
-63
lines changed

sql/ddl_log.cc

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,7 @@ static int ddl_log_execute_action(THD *thd, MEM_ROOT *mem_root,
11601160
case DDL_RENAME_PHASE_TRIGGER:
11611161
{
11621162
MDL_request mdl_request;
1163+
TRIGGER_RENAME_PARAM trigger_param;
11631164

11641165
build_filename_and_delete_tmp_file(to_path, sizeof(to_path),
11651166
&ddl_log_entry->db,
@@ -1195,14 +1196,20 @@ static int ddl_log_execute_action(THD *thd, MEM_ROOT *mem_root,
11951196
error= thd->mdl_context.acquire_lock(&mdl_request, 1);
11961197
/* acquire_locks() should never fail during recovery */
11971198
DBUG_ASSERT(error == 0);
1198-
1199+
(void) Table_triggers_list::prepare_for_rename(thd,
1200+
&trigger_param,
1201+
&ddl_log_entry->db,
1202+
&to_table,
1203+
&to_converted_name,
1204+
&ddl_log_entry->from_db,
1205+
&from_table);
11991206
(void) Table_triggers_list::change_table_name(thd,
1207+
&trigger_param,
12001208
&ddl_log_entry->db,
12011209
&to_table,
12021210
&to_converted_name,
12031211
&ddl_log_entry->from_db,
12041212
&from_table);
1205-
12061213
thd->mdl_context.release_lock(mdl_request.ticket);
12071214
}
12081215
if (ddl_log_increment_phase_no_lock(entry_pos))
@@ -1726,7 +1733,6 @@ static int ddl_log_execute_action(THD *thd, MEM_ROOT *mem_root,
17261733
}
17271734
break;
17281735
}
1729-
}
17301736
default:
17311737
DBUG_ASSERT(0);
17321738
break;

sql/sql_rename.cc

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
Copyright (c) 2000, 2013, Oracle and/or its affiliates.
3-
Copyright (c) 2011, 2013, Monty Program Ab.
3+
Copyright (c) 2011, 2021, Monty Program Ab.
44
55
This program is free software; you can redistribute it and/or modify
66
it under the terms of the GNU General Public License as published by
@@ -339,6 +339,7 @@ do_rename(THD *thd, rename_param *param, DDL_LOG_STATE *ddl_log_state,
339339
int rc= 1;
340340
handlerton *hton;
341341
LEX_CSTRING *old_alias, *new_alias;
342+
TRIGGER_RENAME_PARAM rename_param;
342343
DBUG_ENTER("do_rename");
343344
DBUG_PRINT("enter", ("skip_error: %d", (int) skip_error));
344345

@@ -361,6 +362,15 @@ do_rename(THD *thd, rename_param *param, DDL_LOG_STATE *ddl_log_state,
361362
if (hton->flags & HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE)
362363
*force_if_exists= 1;
363364

365+
/* Check if we can rename triggers */
366+
if (Table_triggers_list::prepare_for_rename(thd, &rename_param,
367+
&ren_table->db,
368+
old_alias,
369+
&ren_table->table_name,
370+
new_db,
371+
new_alias))
372+
DBUG_RETURN(!skip_error);
373+
364374
thd->replication_flags= 0;
365375

366376
if (ddl_log_rename_table(thd, ddl_log_state, hton,
@@ -379,7 +389,9 @@ do_rename(THD *thd, rename_param *param, DDL_LOG_STATE *ddl_log_state,
379389

380390
debug_crash_here("ddl_log_rename_before_rename_trigger");
381391

382-
if (!(rc= Table_triggers_list::change_table_name(thd, &ren_table->db,
392+
if (!(rc= Table_triggers_list::change_table_name(thd,
393+
&rename_param,
394+
&ren_table->db,
383395
old_alias,
384396
&ren_table->table_name,
385397
new_db,

sql/sql_table.cc

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7058,6 +7058,7 @@ static bool mysql_inplace_alter_table(THD *thd,
70587058
TABLE *altered_table,
70597059
Alter_inplace_info *ha_alter_info,
70607060
MDL_request *target_mdl_request,
7061+
TRIGGER_RENAME_PARAM *trigger_param,
70617062
Alter_table_ctx *alter_ctx)
70627063
{
70637064
Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN | MYSQL_OPEN_IGNORE_KILLED);
@@ -7330,7 +7331,7 @@ static bool mysql_inplace_alter_table(THD *thd,
73307331
*/
73317332
DBUG_RETURN(true);
73327333
}
7333-
if (Table_triggers_list::change_table_name(thd,
7334+
if (Table_triggers_list::change_table_name(thd, trigger_param,
73347335
&alter_ctx->db,
73357336
&alter_ctx->alias,
73367337
&alter_ctx->table_name,
@@ -7343,7 +7344,8 @@ static bool mysql_inplace_alter_table(THD *thd,
73437344
*/
73447345
(void) mysql_rename_table(db_type,
73457346
&alter_ctx->new_db, &alter_ctx->new_alias,
7346-
&alter_ctx->db, &alter_ctx->alias, NO_FK_CHECKS);
7347+
&alter_ctx->db, &alter_ctx->alias,
7348+
NO_FK_CHECKS);
73477349
DBUG_RETURN(true);
73487350
}
73497351
rename_table_in_stat_tables(thd, &alter_ctx->db, &alter_ctx->alias,
@@ -8849,6 +8851,7 @@ simple_tmp_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
88498851
static bool
88508852
simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
88518853
Alter_info::enum_enable_or_disable keys_onoff,
8854+
TRIGGER_RENAME_PARAM *trigger_param,
88528855
Alter_table_ctx *alter_ctx)
88538856
{
88548857
TABLE *table= table_list->table;
@@ -8895,7 +8898,7 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
88958898
if (mysql_rename_table(old_db_type, &alter_ctx->db, &alter_ctx->table_name,
88968899
&alter_ctx->new_db, &alter_ctx->new_alias, 0))
88978900
error= -1;
8898-
else if (Table_triggers_list::change_table_name(thd,
8901+
else if (Table_triggers_list::change_table_name(thd, trigger_param,
88998902
&alter_ctx->db,
89008903
&alter_ctx->alias,
89018904
&alter_ctx->table_name,
@@ -9080,6 +9083,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
90809083
MDL_request target_mdl_request;
90819084
MDL_ticket *mdl_ticket= 0;
90829085
Alter_table_prelocking_strategy alter_prelocking_strategy;
9086+
TRIGGER_RENAME_PARAM trigger_param;
90839087
DBUG_ENTER("mysql_alter_table");
90849088

90859089
/*
@@ -9504,6 +9508,16 @@ do_continue:;
95049508
create_info))
95059509
DBUG_RETURN(true);
95069510

9511+
/* Check if rename of triggers are supported */
9512+
if (alter_ctx.is_table_renamed() &&
9513+
Table_triggers_list::prepare_for_rename(thd, &trigger_param,
9514+
&alter_ctx.db,
9515+
&alter_ctx.alias,
9516+
&alter_ctx.table_name,
9517+
&alter_ctx.new_db,
9518+
&alter_ctx.new_alias))
9519+
DBUG_RETURN(true);
9520+
95079521
/*
95089522
Look if we have to do anything at all.
95099523
ALTER can become NOOP after handling
@@ -9549,6 +9563,7 @@ do_continue:;
95499563
}
95509564
res= simple_rename_or_index_change(thd, table_list,
95519565
alter_info->keys_onoff,
9566+
&trigger_param,
95529567
&alter_ctx);
95539568
}
95549569
else
@@ -9805,7 +9820,7 @@ do_continue:;
98059820
&altered_table))
98069821
goto err_new_table_cleanup;
98079822
/*
9808-
Avoid creating frm again in ha_create_table() if inline alter will not
9823+
Avoid creating frm again in ha_create_table() if inplace alter will not
98099824
be used.
98109825
*/
98119826
frm_is_created= 1;
@@ -9879,9 +9894,12 @@ do_continue:;
98799894
*/
98809895
enum_check_fields org_count_cuted_fields= thd->count_cuted_fields;
98819896
thd->count_cuted_fields= CHECK_FIELD_WARN;
9882-
int res= mysql_inplace_alter_table(thd, table_list, table, &altered_table,
9897+
int res= mysql_inplace_alter_table(thd,
9898+
table_list, table, &altered_table,
98839899
&ha_alter_info,
9884-
&target_mdl_request, &alter_ctx);
9900+
&target_mdl_request,
9901+
&trigger_param,
9902+
&alter_ctx);
98859903
thd->count_cuted_fields= org_count_cuted_fields;
98869904
my_free(const_cast<uchar*>(frm.str));
98879905

@@ -10216,7 +10234,7 @@ do_continue:;
1021610234
// Check if we renamed the table and if so update trigger files.
1021710235
if (alter_ctx.is_table_renamed())
1021810236
{
10219-
if (Table_triggers_list::change_table_name(thd,
10237+
if (Table_triggers_list::change_table_name(thd, &trigger_param,
1022010238
&alter_ctx.db,
1022110239
&alter_ctx.alias,
1022210240
&alter_ctx.table_name,

0 commit comments

Comments
 (0)