Skip to content

Commit

Permalink
drop anonymous unique index
Browse files Browse the repository at this point in the history
  • Loading branch information
shogo82148 committed Oct 14, 2022
1 parent 4ed0d4e commit cf69641
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 36 deletions.
58 changes: 26 additions & 32 deletions diff/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ func (ctx *alterCtx) dropTableIndexes() error {
indexes := ctx.fromIndexes.Difference(ctx.toIndexes)
// drop index after drop constraint.
// because cannot drop index if needed in a foreign key constraint
lazy := make([]*model.Index, 0, indexes.Cardinality())
lazy := make([]model.Ident, 0, indexes.Cardinality())
for _, index := range indexes.ToSlice() {
indexStmt, ok := ctx.from.LookupIndex(index)
if !ok {
Expand All @@ -455,37 +455,30 @@ func (ctx *alterCtx) dropTableIndexes() error {
continue
}

var indexName model.Ident
if indexStmt.ConstraintName.Valid {
indexName = indexStmt.ConstraintName.Ident
} else if indexStmt.Name.Valid {
indexName = indexStmt.Name.Ident
} else {
var err error
indexName, err = ctx.guessDropTableIndexName(indexStmt)
indexName := getIndexName(indexStmt)
if !indexName.Valid {
name, err := ctx.guessDropTableIndexName(indexStmt)
if err != nil {
return err
}
indexName.Valid = true
indexName.Ident = name
}
if indexStmt.Kind != model.IndexKindForeignKey {
lazy = append(lazy, indexStmt)
lazy = append(lazy, indexName.Ident)
continue
}

ctx.begin()
ctx.writeString("DROP FOREIGN KEY ")
ctx.writeIdent(indexName)
ctx.writeIdent(indexName.Ident)
}

// drop index after drop CONSTRAINT
for _, indexStmt := range lazy {
for _, indexName := range lazy {
ctx.begin()
ctx.writeString("DROP INDEX ")
if !indexStmt.Name.Valid {
ctx.writeIdent(indexStmt.ConstraintName.Ident)
} else {
ctx.writeIdent(indexStmt.Name.Ident)
}
ctx.writeIdent(indexName)
}

return nil
Expand Down Expand Up @@ -538,33 +531,34 @@ LOOP:
continue
}

var name model.Ident
if idx.ConstraintName.Valid {
name = idx.ConstraintName.Ident
} else if idx.Name.Valid {
name = idx.Name.Ident
} else {
name := getIndexName(idx)
if !name.Valid {
continue
}

// this name should not be used in the "from".
for _, idx2 := range ctx.from.Indexes {
if idx2.ConstraintName.Valid {
if idx2.ConstraintName.Ident == name {
continue LOOP
}
} else if idx2.Name.Valid {
if idx2.Name.Ident == name {
continue LOOP
}
name2 := getIndexName(idx2)
if name2.Valid && name2.Ident == name.Ident {
continue LOOP
}
}

return name, nil // found
return name.Ident, nil // found
}
return "", fmt.Errorf("can not drop index without name: %q", indexStmt.ID())
}

func getIndexName(idx *model.Index) model.MaybeIdent {
if idx.Name.Valid {
return idx.Name
}
if idx.ConstraintName.Valid {
return idx.ConstraintName
}
return model.MaybeIdent{}
}

// equalIndex returns whether index a and b have same definition, excluding their names.
func equalIndex(a, b *model.Index) bool {
if a.Table != b.Table {
Expand Down
53 changes: 49 additions & 4 deletions diff/diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -522,14 +522,31 @@ type AutoNamedSpec struct {

var autoSpecs = []AutoNamedSpec{
{
Name: "remove FOREIGN KEY that MySQL named automatically",
Name: "drop anonymous unique key",
Before: []string{
"CREATE TABLE `fuga` ( `id` INTEGER NOT NULL, UNIQUE KEY (`id`) )",
},
Current: []string{"CREATE TABLE `fuga` (" +
"`id` int NOT NULL," +
"UNIQUE KEY `id` (`id`)" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci",
},
After: []string{
"CREATE TABLE `fuga` ( `id` INTEGER NOT NULL )",
},
Expect: []string{
"ALTER TABLE `fuga` DROP INDEX `id`",
},
},
{
Name: "remove anonymous FOREIGN KEY",
Before: []string{
"CREATE TABLE `f` ( `id` INTEGER NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`) )",
"CREATE TABLE `fuga` ( `id` INTEGER NOT NULL, `fid` INTEGER NOT NULL, FOREIGN KEY (fid) REFERENCES f (id) )",
},
Current: []string{
"CREATE TABLE `f` ( `id` int NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci",
"Create Table: CREATE TABLE `fuga` (" +
"CREATE TABLE `fuga` (" +
"`id` int NOT NULL," +
"`fid` int NOT NULL," +
"KEY `fid` (`fid`)," +
Expand All @@ -542,13 +559,41 @@ var autoSpecs = []AutoNamedSpec{
},
Expect: []string{
"ALTER TABLE `fuga` " +
"DROP FOREIGN KEY `fk`, " +
"DROP INDEX `fk`, " +
"DROP FOREIGN KEY `fuga_ibfk_1`, " +
"ADD INDEX `fid` (`fid`)",
},
},
}

func TestDiffWithAutoNamedObjects(t *testing.T) {
var buf bytes.Buffer
for _, spec := range autoSpecs {
t.Run(spec.Name, func(t *testing.T) {
buf.Reset()
before := joinQueries(spec.Before)
after := joinQueries(spec.After)
current := joinQueries(spec.Current)
expect := joinQueries(spec.Expect)

err := diff.Strings(&buf, before, after, diff.WithCurrentSchema(current))
if err != nil {
t.Errorf("spec %s failed: %v", spec.Name, err)
return
}

actual := buf.String()
if diff := cmp.Diff(expect, actual); diff != "" {
t.Errorf(
"spec %s mismatch (-want/+got)\n%s\n"+
"before = %q\n"+
"after = %q",
spec.Name, diff, spec.Before, spec.After,
)
}
})
}
}

func TestDiffWithAutoNamedObjects_Integrated(t *testing.T) {
database.SkipIfNoTestDatabase(t)

Expand Down

0 comments on commit cf69641

Please sign in to comment.