From d9d5c4dce0dcf322202f3336f5951c844475cc51 Mon Sep 17 00:00:00 2001 From: Mayank Govilla <31316460+mgovilla@users.noreply.github.com> Date: Sun, 7 Nov 2021 20:47:29 -0500 Subject: [PATCH] Fix self-referential belongs to constraint (#4801) * create tests for self-ref has one migration * add relation equality check to avoid skipping self-referential schemas * remove drop table error check --- schema/relationship.go | 2 +- schema/relationship_test.go | 15 +++++++++++++++ tests/migrate_test.go | 19 +++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/schema/relationship.go b/schema/relationship.go index 5699ec5f..c5d3dcad 100644 --- a/schema/relationship.go +++ b/schema/relationship.go @@ -519,7 +519,7 @@ func (rel *Relationship) ParseConstraint() *Constraint { if rel.Type == BelongsTo { for _, r := range rel.FieldSchema.Relationships.Relations { - if r.FieldSchema == rel.Schema && len(rel.References) == len(r.References) { + if r != rel && r.FieldSchema == rel.Schema && len(rel.References) == len(r.References) { matched := true for idx, ref := range r.References { if !(rel.References[idx].PrimaryKey == ref.PrimaryKey && rel.References[idx].ForeignKey == ref.ForeignKey && diff --git a/schema/relationship_test.go b/schema/relationship_test.go index cb616fc0..afa103b3 100644 --- a/schema/relationship_test.go +++ b/schema/relationship_test.go @@ -93,6 +93,21 @@ func TestBelongsToWithOnlyReferences2(t *testing.T) { }) } +func TestSelfReferentialBelongsTo(t *testing.T) { + type User struct { + ID int32 `gorm:"primaryKey"` + Name string + CreatorID *int32 + Creator *User + } + + checkStructRelation(t, &User{}, Relation{ + Name: "Creator", Type: schema.BelongsTo, Schema: "User", FieldSchema: "User", + References: []Reference{{"ID", "User", "CreatorID", "User", "", false}}, + }) + +} + func TestSelfReferentialBelongsToOverrideReferences(t *testing.T) { type User struct { ID int32 `gorm:"primaryKey"` diff --git a/tests/migrate_test.go b/tests/migrate_test.go index 0354e84e..f0467c5b 100644 --- a/tests/migrate_test.go +++ b/tests/migrate_test.go @@ -54,6 +54,25 @@ func TestMigrate(t *testing.T) { } } +func TestAutoMigrateSelfReferential(t *testing.T) { + type MigratePerson struct { + ID uint + Name string + ManagerID *uint + Manager *MigratePerson + } + + DB.Migrator().DropTable(&MigratePerson{}) + + if err := DB.AutoMigrate(&MigratePerson{}); err != nil { + t.Fatalf("Failed to auto migrate, but got error %v", err) + } + + if !DB.Migrator().HasConstraint("migrate_people", "fk_migrate_people_manager") { + t.Fatalf("Failed to find has one constraint between people and managers") + } +} + func TestSmartMigrateColumn(t *testing.T) { fullSupported := map[string]bool{"mysql": true, "postgres": true}[DB.Dialector.Name()]