fix(migrator): ignore relationships when migrating #5913 (#5946)

This commit is contained in:
Haibo 2023-01-01 19:54:28 +08:00 committed by GitHub
parent 7da24d1d52
commit da2b2861de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 99 additions and 22 deletions

View File

@ -37,6 +37,8 @@ type Config struct {
DisableAutomaticPing bool DisableAutomaticPing bool
// DisableForeignKeyConstraintWhenMigrating // DisableForeignKeyConstraintWhenMigrating
DisableForeignKeyConstraintWhenMigrating bool DisableForeignKeyConstraintWhenMigrating bool
// IgnoreRelationshipsWhenMigrating
IgnoreRelationshipsWhenMigrating bool
// DisableNestedTransaction disable nested transaction // DisableNestedTransaction disable nested transaction
DisableNestedTransaction bool DisableNestedTransaction bool
// AllowGlobalUpdate allow global update // AllowGlobalUpdate allow global update

View File

@ -143,8 +143,11 @@ func (m Migrator) AutoMigrate(values ...interface{}) error {
} }
} }
for _, rel := range stmt.Schema.Relationships.Relations { if !m.DB.DisableForeignKeyConstraintWhenMigrating && !m.DB.IgnoreRelationshipsWhenMigrating {
if !m.DB.Config.DisableForeignKeyConstraintWhenMigrating { for _, rel := range stmt.Schema.Relationships.Relations {
if rel.Field.IgnoreMigration {
continue
}
if constraint := rel.ParseConstraint(); constraint != nil && if constraint := rel.ParseConstraint(); constraint != nil &&
constraint.Schema == stmt.Schema && !queryTx.Migrator().HasConstraint(value, constraint.Name) { constraint.Schema == stmt.Schema && !queryTx.Migrator().HasConstraint(value, constraint.Name) {
if err := execTx.Migrator().CreateConstraint(value, constraint.Name); err != nil { if err := execTx.Migrator().CreateConstraint(value, constraint.Name); err != nil {
@ -244,8 +247,11 @@ func (m Migrator) CreateTable(values ...interface{}) error {
} }
} }
for _, rel := range stmt.Schema.Relationships.Relations { if !m.DB.DisableForeignKeyConstraintWhenMigrating && !m.DB.IgnoreRelationshipsWhenMigrating {
if !m.DB.DisableForeignKeyConstraintWhenMigrating { for _, rel := range stmt.Schema.Relationships.Relations {
if rel.Field.IgnoreMigration {
continue
}
if constraint := rel.ParseConstraint(); constraint != nil { if constraint := rel.ParseConstraint(); constraint != nil {
if constraint.Schema == stmt.Schema { if constraint.Schema == stmt.Schema {
sql, vars := buildConstraint(constraint) sql, vars := buildConstraint(constraint)
@ -818,26 +824,31 @@ func (m Migrator) ReorderModels(values []interface{}, autoAdd bool) (results []i
} }
parsedSchemas[dep.Statement.Schema] = true parsedSchemas[dep.Statement.Schema] = true
for _, rel := range dep.Schema.Relationships.Relations { if !m.DB.IgnoreRelationshipsWhenMigrating {
if c := rel.ParseConstraint(); c != nil && c.Schema == dep.Statement.Schema && c.Schema != c.ReferenceSchema { for _, rel := range dep.Schema.Relationships.Relations {
dep.Depends = append(dep.Depends, c.ReferenceSchema) if rel.Field.IgnoreMigration {
} continue
}
if c := rel.ParseConstraint(); c != nil && c.Schema == dep.Statement.Schema && c.Schema != c.ReferenceSchema {
dep.Depends = append(dep.Depends, c.ReferenceSchema)
}
if rel.Type == schema.HasOne || rel.Type == schema.HasMany { if rel.Type == schema.HasOne || rel.Type == schema.HasMany {
beDependedOn[rel.FieldSchema] = true beDependedOn[rel.FieldSchema] = true
} }
if rel.JoinTable != nil { if rel.JoinTable != nil {
// append join value // append join value
defer func(rel *schema.Relationship, joinValue interface{}) { defer func(rel *schema.Relationship, joinValue interface{}) {
if !beDependedOn[rel.FieldSchema] { if !beDependedOn[rel.FieldSchema] {
dep.Depends = append(dep.Depends, rel.FieldSchema) dep.Depends = append(dep.Depends, rel.FieldSchema)
} else { } else {
fieldValue := reflect.New(rel.FieldSchema.ModelType).Interface() fieldValue := reflect.New(rel.FieldSchema.ModelType).Interface()
parseDependence(fieldValue, autoAdd) parseDependence(fieldValue, autoAdd)
} }
parseDependence(joinValue, autoAdd) parseDependence(joinValue, autoAdd)
}(rel, reflect.New(rel.JoinTable.ModelType).Interface()) }(rel, reflect.New(rel.JoinTable.ModelType).Interface())
}
} }
} }

View File

@ -1203,3 +1203,67 @@ func TestMigrateSameEmbeddedFieldName(t *testing.T) {
_, err = findColumnType(&GameUser{}, "rate_ground_rb_ground_destory_count") _, err = findColumnType(&GameUser{}, "rate_ground_rb_ground_destory_count")
AssertEqual(t, nil, err) AssertEqual(t, nil, err)
} }
func TestMigrateIgnoreRelations(t *testing.T) {
type RelationModel1 struct {
ID uint
}
type RelationModel2 struct {
ID uint
}
type RelationModel3 struct {
ID uint
RelationModel1ID uint
RelationModel1 *RelationModel1
RelationModel2ID uint
RelationModel2 *RelationModel2 `gorm:"-:migration"`
}
var err error
_ = DB.Migrator().DropTable(&RelationModel1{}, &RelationModel2{}, &RelationModel3{})
tx := DB.Session(&gorm.Session{})
tx.IgnoreRelationshipsWhenMigrating = true
err = tx.AutoMigrate(&RelationModel3{})
if err != nil {
t.Errorf("AutoMigrate err:%v", err)
}
// RelationModel3 should be existed
_, err = findColumnType(&RelationModel3{}, "id")
AssertEqual(t, nil, err)
// RelationModel1 should not be existed
_, err = findColumnType(&RelationModel1{}, "id")
if err == nil {
t.Errorf("RelationModel1 should not be migrated")
}
// RelationModel2 should not be existed
_, err = findColumnType(&RelationModel2{}, "id")
if err == nil {
t.Errorf("RelationModel2 should not be migrated")
}
tx.IgnoreRelationshipsWhenMigrating = false
err = tx.AutoMigrate(&RelationModel3{})
if err != nil {
t.Errorf("AutoMigrate err:%v", err)
}
// RelationModel3 should be existed
_, err = findColumnType(&RelationModel3{}, "id")
AssertEqual(t, nil, err)
// RelationModel1 should be existed
_, err = findColumnType(&RelationModel1{}, "id")
AssertEqual(t, nil, err)
// RelationModel2 should not be existed
_, err = findColumnType(&RelationModel2{}, "id")
if err == nil {
t.Errorf("RelationModel2 should not be migrated")
}
}