Skip to content

Commit

Permalink
entc/integration/migrate: add example for renaming columns (#2496)
Browse files Browse the repository at this point in the history
  • Loading branch information
a8m committed Apr 24, 2022
1 parent 7d153c7 commit 04e0dc9
Show file tree
Hide file tree
Showing 22 changed files with 636 additions and 13 deletions.
53 changes: 53 additions & 0 deletions doc/md/migrate.md
Expand Up @@ -300,6 +300,8 @@ options for hooking into schema migration steps.
![atlas-migration-process](https://entgo.io/images/assets/migrate-atlas-process.png)


#### Atlas `Diff` and `Apply` Hooks

Here are two examples that show how to hook into the Atlas `Diff` and `Apply` steps.

```go
Expand Down Expand Up @@ -363,3 +365,54 @@ func main() {
}
}
```

In case a field was renamed in the `ent/schema`, Ent won't detect this change as renaming and will propose `DropColumn`
and `AddColumn` changes in the diff stage. One way to get over this is to use the
[StorageKey](schema-fields.md#storage-key) option on the field and keep the old column name in the database table.
However, using Atlas `Diff` hooks allow replacing the `DropColumn` and `AddColumn` changes with a `RenameColumn` change.

```go
func main() {
client, err := ent.Open("mysql", "root:pass@tcp(localhost:3306)/test")
if err != nil {
log.Fatalf("failed connecting to mysql: %v", err)
}
defer client.Close()
// ...
if err := client.Schema.Create(ctx, schema.WithDiffHook(renameColumnHook)); err != nil {
log.Fatalf("failed creating schema resources: %v", err)
}
}

func renameColumnHook(next schema.Differ) schema.Differ {
return schema.DiffFunc(func(current, desired *atlas.Schema) ([]atlas.Change, error) {
changes, err := next.Diff(current, desired)
if err != nil {
return nil, err
}
for _, c := range changes {
m, ok := c.(*atlas.ModifyTable)
// Skip if the change is not a ModifyTable,
// or if the table is not the "users" table.
if !ok || m.T.Name != user.Table {
continue
}
changes := atlas.Changes(m.Changes)
switch i, j := changes.IndexDropColumn("old_name"), changes.IndexAddColumn("new_name"); {
case i != -1 && j != -1:
// Append a new renaming change.
changes = append(changes, &atlas.RenameColumn{
From: changes[i].(*atlas.DropColumn).C,
To: changes[j].(*atlas.AddColumn).C,
})
// Remove the drop and add changes.
changes.RemoveIndex(i, j)
m.Changes = changes
case i != -1 || j != -1:
return nil, errors.New("old_name and new_name must be present or absent")
}
}
return changes, nil
})
}
```
5 changes: 3 additions & 2 deletions entc/integration/migrate/entv1/migrate/schema.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 55 additions & 1 deletion entc/integration/migrate/entv1/mutation.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions entc/integration/migrate/entv1/runtime.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions entc/integration/migrate/entv1/schema/user.go
Expand Up @@ -11,6 +11,7 @@ import (
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/index"
"github.com/google/uuid"
)

// User holds the schema definition for the User entity.
Expand All @@ -34,6 +35,8 @@ func (User) Fields() []ent.Field {
Optional(),
field.String("renamed").
Optional(),
field.String("old_token").
DefaultFunc(uuid.NewString),
field.Bytes("blob").
Optional().
MaxLen(255),
Expand Down
12 changes: 11 additions & 1 deletion entc/integration/migrate/entv1/user.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions entc/integration/migrate/entv1/user/user.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 04e0dc9

Please sign in to comment.