add MigrateColumnUnique to Migrator interface
This commit is contained in:
parent
56eb4be78e
commit
c7db4af98c
@ -87,6 +87,8 @@ type Migrator interface {
|
|||||||
DropColumn(dst interface{}, field string) error
|
DropColumn(dst interface{}, field string) error
|
||||||
AlterColumn(dst interface{}, field string) error
|
AlterColumn(dst interface{}, field string) error
|
||||||
MigrateColumn(dst interface{}, field *schema.Field, columnType ColumnType) 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
|
HasColumn(dst interface{}, field string) bool
|
||||||
RenameColumn(dst interface{}, oldName, field string) error
|
RenameColumn(dst interface{}, oldName, field string) error
|
||||||
ColumnTypes(dst interface{}) ([]ColumnType, error)
|
ColumnTypes(dst interface{}) ([]ColumnType, error)
|
||||||
|
@ -26,8 +26,6 @@ type Migrator struct {
|
|||||||
// Config schema config
|
// Config schema config
|
||||||
type Config struct {
|
type Config struct {
|
||||||
CreateIndexAfterCreateTable bool
|
CreateIndexAfterCreateTable bool
|
||||||
// Unique in ColumnType is affected by UniqueIndex, e.g. MySQL
|
|
||||||
UniqueAffectedByUniqueIndex bool
|
|
||||||
DB *gorm.DB
|
DB *gorm.DB
|
||||||
gorm.Dialector
|
gorm.Dialector
|
||||||
}
|
}
|
||||||
@ -97,15 +95,20 @@ func (m Migrator) FullDataTypeOf(field *schema.Field) (expr clause.Expr) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m Migrator) GetQueryAndExecTx() (queryTx, execTx *gorm.DB) {
|
||||||
|
queryTx = m.DB.Session(&gorm.Session{})
|
||||||
|
execTx = queryTx
|
||||||
|
if m.DB.DryRun {
|
||||||
|
queryTx.DryRun = false
|
||||||
|
execTx = m.DB.Session(&gorm.Session{Logger: &printSQLLogger{Interface: m.DB.Logger}})
|
||||||
|
}
|
||||||
|
return queryTx, execTx
|
||||||
|
}
|
||||||
|
|
||||||
// AutoMigrate auto migrate values
|
// AutoMigrate auto migrate values
|
||||||
func (m Migrator) AutoMigrate(values ...interface{}) error {
|
func (m Migrator) AutoMigrate(values ...interface{}) error {
|
||||||
for _, value := range m.ReorderModels(values, true) {
|
for _, value := range m.ReorderModels(values, true) {
|
||||||
queryTx := m.DB.Session(&gorm.Session{})
|
queryTx, execTx := m.GetQueryAndExecTx()
|
||||||
execTx := queryTx
|
|
||||||
if m.DB.DryRun {
|
|
||||||
queryTx.DryRun = false
|
|
||||||
execTx = m.DB.Session(&gorm.Session{Logger: &printSQLLogger{Interface: m.DB.Logger}})
|
|
||||||
}
|
|
||||||
if !queryTx.Migrator().HasTable(value) {
|
if !queryTx.Migrator().HasTable(value) {
|
||||||
if err := execTx.Migrator().CreateTable(value); err != nil {
|
if err := execTx.Migrator().CreateTable(value); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -528,7 +531,7 @@ func (m Migrator) MigrateColumn(value interface{}, field *schema.Field, columnTy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := m.MigrateColumnUnique(value, field, columnType); err != nil {
|
if err := m.DB.Migrator().MigrateColumnUnique(value, field, columnType); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -540,82 +543,16 @@ func (m Migrator) MigrateColumnUnique(value interface{}, field *schema.Field, co
|
|||||||
if !ok || field.PrimaryKey {
|
if !ok || field.PrimaryKey {
|
||||||
return nil // skip primary key
|
return nil // skip primary key
|
||||||
}
|
}
|
||||||
|
// By default, ColumnType's Unique is not affected by UniqueIndex, so we don't care about UniqueIndex.
|
||||||
queryTx := m.DB.Session(&gorm.Session{})
|
|
||||||
execTx := queryTx
|
|
||||||
if m.DB.DryRun {
|
|
||||||
queryTx.DryRun = false
|
|
||||||
execTx = m.DB.Session(&gorm.Session{Logger: &printSQLLogger{Interface: m.DB.Logger}})
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.RunWithValue(value, func(stmt *gorm.Statement) error {
|
return m.RunWithValue(value, func(stmt *gorm.Statement) error {
|
||||||
// We're currently only receiving boolean values on `Unique` tag,
|
// We're currently only receiving boolean values on `Unique` tag,
|
||||||
// so the UniqueConstraint name is fixed
|
// so the UniqueConstraint name is fixed
|
||||||
constraint := m.DB.NamingStrategy.UniqueName(stmt.Table, field.DBName)
|
constraint := m.DB.NamingStrategy.UniqueName(stmt.Table, field.DBName)
|
||||||
if m.UniqueAffectedByUniqueIndex {
|
if unique && !field.Unique {
|
||||||
if unique {
|
return m.DB.Migrator().DropConstraint(value, constraint)
|
||||||
// Clean up redundant unique indexes
|
}
|
||||||
indexes, _ := queryTx.Migrator().GetIndexes(value)
|
if !unique && field.Unique {
|
||||||
for _, index := range indexes {
|
return m.DB.Migrator().CreateConstraint(value, constraint)
|
||||||
if uni, ok := index.Unique(); !ok || !uni {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if columns := index.Columns(); len(columns) != 1 || columns[0] != field.DBName {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if name := index.Name(); name == constraint || name == field.UniqueIndex {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := execTx.Migrator().DropIndex(value, index.Name()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hasConstraint := queryTx.Migrator().HasConstraint(value, constraint)
|
|
||||||
switch {
|
|
||||||
case field.Unique && !hasConstraint:
|
|
||||||
if field.Unique {
|
|
||||||
if err := execTx.Migrator().CreateConstraint(value, constraint); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// field isn't Unique but ColumnType's Unique is reported by UniqueConstraint.
|
|
||||||
case !field.Unique && hasConstraint:
|
|
||||||
if err := execTx.Migrator().DropConstraint(value, constraint); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if field.UniqueIndex != "" {
|
|
||||||
if err := execTx.Migrator().CreateIndex(value, field.UniqueIndex); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if field.UniqueIndex != "" && !queryTx.Migrator().HasIndex(value, field.UniqueIndex) {
|
|
||||||
if err := execTx.Migrator().CreateIndex(value, field.UniqueIndex); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if field.Unique {
|
|
||||||
if err := execTx.Migrator().CreateConstraint(value, constraint); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if field.UniqueIndex != "" {
|
|
||||||
if err := execTx.Migrator().CreateIndex(value, field.UniqueIndex); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if unique && !field.Unique {
|
|
||||||
return execTx.Migrator().DropConstraint(value, constraint)
|
|
||||||
}
|
|
||||||
if !unique && field.Unique {
|
|
||||||
return execTx.Migrator().CreateConstraint(value, constraint)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user