Skip to content

Commit 9fea15a

Browse files
authoredOct 30, 2023
feat: add MigrateColumnUnique (go-gorm#6640)
* feat: add MigrateColumnUnique * feat: define new methods * delete debug in test
1 parent 5adc0ce commit 9fea15a

7 files changed

+34
-5
lines changed
 

‎migrator.go

+2
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ type Migrator interface {
8787
DropColumn(dst interface{}, field string) error
8888
AlterColumn(dst interface{}, field string) error
8989
MigrateColumn(dst interface{}, field *schema.Field, columnType ColumnType) error
90+
// MigrateColumnUnique migrate column's UNIQUE constraint, it's part of MigrateColumn.
91+
MigrateColumnUnique(dst interface{}, field *schema.Field, columnType ColumnType) error
9092
HasColumn(dst interface{}, field string) bool
9193
RenameColumn(dst interface{}, oldName, field string) error
9294
ColumnTypes(dst interface{}) ([]ColumnType, error)

‎migrator/migrator.go

+22
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ var regFullDataType = regexp.MustCompile(`\D*(\d+)\D?`)
2727

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

30+
var _ gorm.Migrator = (*Migrator)(nil)
31+
3032
// Migrator m struct
3133
type Migrator struct {
3234
Config
@@ -539,6 +541,26 @@ func (m Migrator) MigrateColumn(value interface{}, field *schema.Field, columnTy
539541
return nil
540542
}
541543

544+
func (m Migrator) MigrateColumnUnique(value interface{}, field *schema.Field, columnType gorm.ColumnType) error {
545+
unique, ok := columnType.Unique()
546+
if !ok || field.PrimaryKey {
547+
return nil // skip primary key
548+
}
549+
// By default, ColumnType's Unique is not affected by UniqueIndex, so we don't care about UniqueIndex.
550+
return m.RunWithValue(value, func(stmt *gorm.Statement) error {
551+
// We're currently only receiving boolean values on `Unique` tag,
552+
// so the UniqueConstraint name is fixed
553+
constraint := m.DB.NamingStrategy.UniqueName(stmt.Table, field.DBName)
554+
if unique && !field.Unique {
555+
return m.DB.Migrator().DropConstraint(value, constraint)
556+
}
557+
if !unique && field.Unique {
558+
return m.DB.Migrator().CreateConstraint(value, constraint)
559+
}
560+
return nil
561+
})
562+
}
563+
542564
// ColumnTypes return columnTypes []gorm.ColumnType and execErr error
543565
func (m Migrator) ColumnTypes(value interface{}) ([]gorm.ColumnType, error) {
544566
columnTypes := make([]gorm.ColumnType, 0)

‎schema/naming.go

+8
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@ type Namer interface {
1919
RelationshipFKName(Relationship) string
2020
CheckerName(table, column string) string
2121
IndexName(table, column string) string
22+
UniqueName(table, column string) string
2223
}
2324

2425
// Replacer replacer interface like strings.Replacer
2526
type Replacer interface {
2627
Replace(name string) string
2728
}
2829

30+
var _ Namer = (*NamingStrategy)(nil)
31+
2932
// NamingStrategy tables, columns naming strategy
3033
type NamingStrategy struct {
3134
TablePrefix string
@@ -85,6 +88,11 @@ func (ns NamingStrategy) IndexName(table, column string) string {
8588
return ns.formatName("idx", table, ns.toDBName(column))
8689
}
8790

91+
// UniqueName generate unique constraint name
92+
func (ns NamingStrategy) UniqueName(table, column string) string {
93+
return ns.formatName("uni", table, ns.toDBName(column))
94+
}
95+
8896
func (ns NamingStrategy) formatName(prefix, table, name string) string {
8997
formattedName := strings.ReplaceAll(strings.Join([]string{
9098
prefix, table, name,

‎tests/associations_belongs_to_test.go

-2
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,6 @@ func TestBelongsToAssociationUnscoped(t *testing.T) {
278278
t.Fatalf("failed to create items, got error: %v", err)
279279
}
280280

281-
tx = tx.Debug()
282-
283281
// test replace
284282
if err := tx.Model(&item).Association("ItemParent").Unscoped().Replace(&ItemParent{
285283
Logo: "updated logo",

‎tests/count_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func TestCountWithGroup(t *testing.T) {
2929
}
3030

3131
var count2 int64
32-
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 {
32+
if err := DB.Model(&Company{}).Where("name in ?", []string{"company_count_group_b", "company_count_group_c"}).Group("name").Count(&count2).Error; err != nil {
3333
t.Errorf(fmt.Sprintf("Count should work, but got err %v", err))
3434
}
3535
if count2 != 2 {

‎tests/preload_test.go

-1
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,6 @@ func TestEmbedPreload(t *testing.T) {
429429
},
430430
}
431431

432-
DB = DB.Debug()
433432
for _, test := range tests {
434433
t.Run(test.name, func(t *testing.T) {
435434
actual := Org{}

‎tests/update_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,7 @@ func TestSaveWithHooks(t *testing.T) {
838838
saveTokenOwner := func(owner *TokenOwner) (*TokenOwner, error) {
839839
var newOwner TokenOwner
840840
if err := DB.Transaction(func(tx *gorm.DB) error {
841-
if err := tx.Debug().Session(&gorm.Session{FullSaveAssociations: true}).Save(owner).Error; err != nil {
841+
if err := tx.Session(&gorm.Session{FullSaveAssociations: true}).Save(owner).Error; err != nil {
842842
return err
843843
}
844844
if err := tx.Preload("Token").First(&newOwner, owner.ID).Error; err != nil {

0 commit comments

Comments
 (0)
Please sign in to comment.