Skip to content

Commit

Permalink
feat: add MigrateColumnUnique (#6640)
Browse files Browse the repository at this point in the history
* feat: add MigrateColumnUnique

* feat: define new methods

* delete debug in test
  • Loading branch information
black-06 authored Oct 30, 2023
1 parent 5adc0ce commit 9fea15a
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 5 deletions.
2 changes: 2 additions & 0 deletions migrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ type Migrator interface {
DropColumn(dst interface{}, field string) error
AlterColumn(dst interface{}, field string) error
MigrateColumn(dst interface{}, field *schema.Field, columnType ColumnType) error
// MigrateColumnUnique migrate column's UNIQUE constraint, it's part of MigrateColumn.
MigrateColumnUnique(dst interface{}, field *schema.Field, columnType ColumnType) error
HasColumn(dst interface{}, field string) bool
RenameColumn(dst interface{}, oldName, field string) error
ColumnTypes(dst interface{}) ([]ColumnType, error)
Expand Down
22 changes: 22 additions & 0 deletions migrator/migrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ var regFullDataType = regexp.MustCompile(`\D*(\d+)\D?`)

// TODO:? Create const vars for raw sql queries ?

var _ gorm.Migrator = (*Migrator)(nil)

// Migrator m struct
type Migrator struct {
Config
Expand Down Expand Up @@ -539,6 +541,26 @@ func (m Migrator) MigrateColumn(value interface{}, field *schema.Field, columnTy
return nil
}

func (m Migrator) MigrateColumnUnique(value interface{}, field *schema.Field, columnType gorm.ColumnType) error {
unique, ok := columnType.Unique()
if !ok || field.PrimaryKey {
return nil // skip primary key
}
// By default, ColumnType's Unique is not affected by UniqueIndex, so we don't care about UniqueIndex.
return m.RunWithValue(value, func(stmt *gorm.Statement) error {
// We're currently only receiving boolean values on `Unique` tag,
// so the UniqueConstraint name is fixed
constraint := m.DB.NamingStrategy.UniqueName(stmt.Table, field.DBName)
if unique && !field.Unique {
return m.DB.Migrator().DropConstraint(value, constraint)
}
if !unique && field.Unique {
return m.DB.Migrator().CreateConstraint(value, constraint)
}
return nil
})
}

// ColumnTypes return columnTypes []gorm.ColumnType and execErr error
func (m Migrator) ColumnTypes(value interface{}) ([]gorm.ColumnType, error) {
columnTypes := make([]gorm.ColumnType, 0)
Expand Down
8 changes: 8 additions & 0 deletions schema/naming.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@ type Namer interface {
RelationshipFKName(Relationship) string
CheckerName(table, column string) string
IndexName(table, column string) string
UniqueName(table, column string) string
}

// Replacer replacer interface like strings.Replacer
type Replacer interface {
Replace(name string) string
}

var _ Namer = (*NamingStrategy)(nil)

// NamingStrategy tables, columns naming strategy
type NamingStrategy struct {
TablePrefix string
Expand Down Expand Up @@ -85,6 +88,11 @@ func (ns NamingStrategy) IndexName(table, column string) string {
return ns.formatName("idx", table, ns.toDBName(column))
}

// UniqueName generate unique constraint name
func (ns NamingStrategy) UniqueName(table, column string) string {
return ns.formatName("uni", table, ns.toDBName(column))
}

func (ns NamingStrategy) formatName(prefix, table, name string) string {
formattedName := strings.ReplaceAll(strings.Join([]string{
prefix, table, name,
Expand Down
2 changes: 0 additions & 2 deletions tests/associations_belongs_to_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,6 @@ func TestBelongsToAssociationUnscoped(t *testing.T) {
t.Fatalf("failed to create items, got error: %v", err)
}

tx = tx.Debug()

// test replace
if err := tx.Model(&item).Association("ItemParent").Unscoped().Replace(&ItemParent{
Logo: "updated logo",
Expand Down
2 changes: 1 addition & 1 deletion tests/count_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestCountWithGroup(t *testing.T) {
}

var count2 int64
if err := DB.Debug().Model(&Company{}).Where("name in ?", []string{"company_count_group_b", "company_count_group_c"}).Group("name").Count(&count2).Error; err != nil {
if err := DB.Model(&Company{}).Where("name in ?", []string{"company_count_group_b", "company_count_group_c"}).Group("name").Count(&count2).Error; err != nil {
t.Errorf(fmt.Sprintf("Count should work, but got err %v", err))
}
if count2 != 2 {
Expand Down
1 change: 0 additions & 1 deletion tests/preload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,6 @@ func TestEmbedPreload(t *testing.T) {
},
}

DB = DB.Debug()
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actual := Org{}
Expand Down
2 changes: 1 addition & 1 deletion tests/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -838,7 +838,7 @@ func TestSaveWithHooks(t *testing.T) {
saveTokenOwner := func(owner *TokenOwner) (*TokenOwner, error) {
var newOwner TokenOwner
if err := DB.Transaction(func(tx *gorm.DB) error {
if err := tx.Debug().Session(&gorm.Session{FullSaveAssociations: true}).Save(owner).Error; err != nil {
if err := tx.Session(&gorm.Session{FullSaveAssociations: true}).Save(owner).Error; err != nil {
return err
}
if err := tx.Preload("Token").First(&newOwner, owner.ID).Error; err != nil {
Expand Down

0 comments on commit 9fea15a

Please sign in to comment.