diff --git a/gorm.go b/gorm.go index 65c9e2280e..37595ddd78 100644 --- a/gorm.go +++ b/gorm.go @@ -37,6 +37,8 @@ type Config struct { DisableAutomaticPing bool // DisableForeignKeyConstraintWhenMigrating DisableForeignKeyConstraintWhenMigrating bool + // IgnoreRelationshipsWhenMigrating + IgnoreRelationshipsWhenMigrating bool // DisableNestedTransaction disable nested transaction DisableNestedTransaction bool // AllowGlobalUpdate allow global update diff --git a/migrator/migrator.go b/migrator/migrator.go index eafe7bb298..2b0803b48d 100644 --- a/migrator/migrator.go +++ b/migrator/migrator.go @@ -143,8 +143,11 @@ func (m Migrator) AutoMigrate(values ...interface{}) error { } } - for _, rel := range stmt.Schema.Relationships.Relations { - if !m.DB.Config.DisableForeignKeyConstraintWhenMigrating { + if !m.DB.DisableForeignKeyConstraintWhenMigrating && !m.DB.IgnoreRelationshipsWhenMigrating { + for _, rel := range stmt.Schema.Relationships.Relations { + if rel.Field.IgnoreMigration { + continue + } if constraint := rel.ParseConstraint(); constraint != nil && constraint.Schema == stmt.Schema && !queryTx.Migrator().HasConstraint(value, constraint.Name) { 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 { + if !m.DB.DisableForeignKeyConstraintWhenMigrating && !m.DB.IgnoreRelationshipsWhenMigrating { + for _, rel := range stmt.Schema.Relationships.Relations { + if rel.Field.IgnoreMigration { + continue + } if constraint := rel.ParseConstraint(); constraint != nil { if constraint.Schema == stmt.Schema { sql, vars := buildConstraint(constraint) @@ -819,15 +825,18 @@ func (m Migrator) ReorderModels(values []interface{}, autoAdd bool) (results []i parsedSchemas[dep.Statement.Schema] = true for _, rel := range dep.Schema.Relationships.Relations { - if c := rel.ParseConstraint(); c != nil && c.Schema == dep.Statement.Schema && c.Schema != c.ReferenceSchema { - dep.Depends = append(dep.Depends, c.ReferenceSchema) + ignoreRel := rel.Field.IgnoreMigration || m.DB.IgnoreRelationshipsWhenMigrating + if !ignoreRel { + 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 { beDependedOn[rel.FieldSchema] = true } - if rel.JoinTable != nil { + if !ignoreRel && rel.JoinTable != nil { // append join value defer func(rel *schema.Relationship, joinValue interface{}) { if !beDependedOn[rel.FieldSchema] { diff --git a/tests/migrate_test.go b/tests/migrate_test.go index 9df626fd27..d5d129a8e6 100644 --- a/tests/migrate_test.go +++ b/tests/migrate_test.go @@ -1203,3 +1203,67 @@ func TestMigrateSameEmbeddedFieldName(t *testing.T) { _, err = findColumnType(&GameUser{}, "rate_ground_rb_ground_destory_count") 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") + } +}