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
This commit is contained in:
Mayank Govilla 2021-11-07 20:47:29 -05:00 committed by GitHub
parent 4c8810a848
commit d9d5c4dce0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 1 deletions

View File

@ -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 &&

View File

@ -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"`

View File

@ -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()]