Skip to content

Commit 6f85089

Browse files
authored
Online DDL shadow table: rename referenced table name in self referencing FK (#16205)
Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com>
1 parent adef4c2 commit 6f85089

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

go/vt/vttablet/onlineddl/executor.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -996,7 +996,6 @@ func (e *Executor) cutOverVReplMigration(ctx context.Context, s *VReplStream, sh
996996
}
997997

998998
renameQuery := sqlparser.BuildParsedQuery(sqlSwapTables, onlineDDL.Table, sentryTableName, vreplTable, onlineDDL.Table, sentryTableName, vreplTable)
999-
1000999
waitForRenameProcess := func() error {
10011000
// This function waits until it finds the RENAME TABLE... query running in MySQL's PROCESSLIST, or until timeout
10021001
// The function assumes that one of the renamed tables is locked, thus causing the RENAME to block. If nothing
@@ -1404,6 +1403,25 @@ func (e *Executor) duplicateCreateTable(ctx context.Context, onlineDDL *schema.O
14041403
}
14051404
newCreateTable = sqlparser.Clone(originalCreateTable)
14061405
newCreateTable.SetTable(newCreateTable.GetTable().Qualifier.CompliantName(), newTableName)
1406+
1407+
// If this table has a self-referencing foreign key constraint, ensure the referenced table gets renamed:
1408+
renameSelfFK := func(node sqlparser.SQLNode) (kontinue bool, err error) {
1409+
switch node := node.(type) {
1410+
case *sqlparser.ConstraintDefinition:
1411+
fk, ok := node.Details.(*sqlparser.ForeignKeyDefinition)
1412+
if !ok {
1413+
return true, nil
1414+
}
1415+
if referencedTableName := fk.ReferenceDefinition.ReferencedTable.Name.String(); referencedTableName == originalCreateTable.Table.Name.String() {
1416+
// This is a self-referencing foreign key
1417+
// We need to rename the referenced table as well
1418+
fk.ReferenceDefinition.ReferencedTable.Name = sqlparser.NewIdentifierCS(newTableName)
1419+
}
1420+
}
1421+
return true, nil
1422+
}
1423+
_ = sqlparser.Walk(renameSelfFK, newCreateTable)
1424+
14071425
// manipulate CreateTable statement: take care of constraints names which have to be
14081426
// unique across the schema
14091427
constraintMap, err = e.validateAndEditCreateTableStatement(onlineDDL, newCreateTable)

go/vt/vttablet/onlineddl/executor_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,24 @@ func TestDuplicateCreateTable(t *testing.T) {
370370
expectSQL: "create table mytable (\n\tid int primary key,\n\ti int,\n\tconstraint f_bjj16562shq086ozik3zf6kjg foreign key (i) references parent (id) on delete cascade\n)",
371371
expectMapSize: 1,
372372
},
373+
{
374+
sql: "create table self (id int primary key, i int, constraint f foreign key (i) references self (id))",
375+
newName: "mytable",
376+
expectSQL: "create table mytable (\n\tid int primary key,\n\ti int,\n\tconstraint f_8aymb58nzb78l5jhq600veg6y foreign key (i) references mytable (id)\n)",
377+
expectMapSize: 1,
378+
},
379+
{
380+
sql: "create table self (id int primary key, i1 int, i2 int, constraint f1 foreign key (i1) references self (id), constraint f1 foreign key (i2) references parent (id))",
381+
newName: "mytable",
382+
expectSQL: `create table mytable (
383+
id int primary key,
384+
i1 int,
385+
i2 int,
386+
constraint f1_1rlsg9yls1t91i35zq5gyeoq7 foreign key (i1) references mytable (id),
387+
constraint f1_59t4lvb1ncti6fxy27drad4jp foreign key (i2) references parent (id)
388+
)`,
389+
expectMapSize: 1,
390+
},
373391
}
374392
for _, tcase := range tcases {
375393
t.Run(tcase.sql, func(t *testing.T) {

0 commit comments

Comments
 (0)