From 5d91ddac8c01aeff48e2402efeb11fcb697b37a0 Mon Sep 17 00:00:00 2001 From: Paras Waykole Date: Fri, 8 Oct 2021 08:29:55 +0530 Subject: [PATCH] fixed belongs_to & has_one reversed if field same (proper fix) (#4694) * fixed belongs_to & has_one reversed if field same * hasmany same foreign key bug fixed and test added * belongsToSameForeignKey fixed and reverted old fix --- schema/relationship.go | 12 ++++----- schema/relationship_test.go | 54 +++++++++++++++++++++++++++++++++---- utils/utils.go | 12 --------- 3 files changed, 54 insertions(+), 24 deletions(-) diff --git a/schema/relationship.go b/schema/relationship.go index 84556bae..5699ec5f 100644 --- a/schema/relationship.go +++ b/schema/relationship.go @@ -7,7 +7,6 @@ import ( "github.com/jinzhu/inflection" "gorm.io/gorm/clause" - "gorm.io/gorm/utils" ) // RelationshipType relationship type @@ -78,6 +77,8 @@ func (schema *Schema) parseRelation(field *Field) *Relationship { schema.buildPolymorphicRelation(relation, field, polymorphic) } else if many2many := field.TagSettings["MANY2MANY"]; many2many != "" { schema.buildMany2ManyRelation(relation, field, many2many) + } else if belongsTo := field.TagSettings["BELONGSTO"]; belongsTo != "" { + schema.guessRelation(relation, field, guessBelongs) } else { switch field.IndirectFieldType.Kind() { case reflect.Struct: @@ -405,14 +406,11 @@ func (schema *Schema) guessRelation(relation *Relationship, field *Field, cgl gu if len(relation.foreignKeys) > 0 { for _, foreignKey := range relation.foreignKeys { - ff := foreignSchema.LookUpField(foreignKey) - pf := primarySchema.LookUpField(foreignKey) - isKeySame := utils.ExistsIn(foreignKey, &relation.primaryKeys) - if ff == nil || (pf != nil && ff != nil && schema == primarySchema && primarySchema != foreignSchema && !isKeySame && field.IndirectFieldType.Kind() == reflect.Struct) { + if f := foreignSchema.LookUpField(foreignKey); f != nil { + foreignFields = append(foreignFields, f) + } else { reguessOrErr() return - } else { - foreignFields = append(foreignFields, ff) } } } else { diff --git a/schema/relationship_test.go b/schema/relationship_test.go index d0ffc28a..cb616fc0 100644 --- a/schema/relationship_test.go +++ b/schema/relationship_test.go @@ -144,6 +144,25 @@ func TestHasOneOverrideReferences(t *testing.T) { }) } +func TestHasOneOverrideReferences2(t *testing.T) { + + type Profile struct { + gorm.Model + Name string + } + + type User struct { + gorm.Model + ProfileID uint `gorm:"column:profile_id"` + Profile *Profile `gorm:"foreignKey:ID;references:ProfileID"` + } + + checkStructRelation(t, &User{}, Relation{ + Name: "Profile", Type: schema.HasOne, Schema: "User", FieldSchema: "Profile", + References: []Reference{{"ProfileID", "User", "ID", "Profile", "", true}}, + }) +} + func TestHasOneWithOnlyReferences(t *testing.T) { type Profile struct { gorm.Model @@ -483,22 +502,47 @@ func TestSameForeignKey(t *testing.T) { ) } -func TestBelongsToWithSameForeignKey(t *testing.T) { +func TestBelongsToSameForeignKey(t *testing.T) { + + type User struct { + gorm.Model + Name string + UUID string + } + + type UserAux struct { + gorm.Model + Aux string + UUID string + User User `gorm:"ForeignKey:UUID;references:UUID;belongsTo"` + } + + checkStructRelation(t, &UserAux{}, + Relation{ + Name: "User", Type: schema.BelongsTo, Schema: "UserAux", FieldSchema: "User", + References: []Reference{ + {"UUID", "User", "UUID", "UserAux", "", false}, + }, + }, + ) +} + +func TestHasOneWithSameForeignKey(t *testing.T) { type Profile struct { gorm.Model Name string - ProfileRefer int + ProfileRefer int // not used in relationship } type User struct { gorm.Model - Profile Profile `gorm:"ForeignKey:ProfileRefer"` + Profile Profile `gorm:"ForeignKey:ID;references:ProfileRefer"` ProfileRefer int } checkStructRelation(t, &User{}, Relation{ - Name: "Profile", Type: schema.BelongsTo, Schema: "User", FieldSchema: "Profile", - References: []Reference{{"ID", "Profile", "ProfileRefer", "User", "", false}}, + Name: "Profile", Type: schema.HasOne, Schema: "User", FieldSchema: "Profile", + References: []Reference{{"ProfileRefer", "User", "ID", "Profile", "", true}}, }) } diff --git a/utils/utils.go b/utils/utils.go index 1110c7a7..9c238ac5 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -114,15 +114,3 @@ func ToString(value interface{}) string { } return "" } - -func ExistsIn(a string, list *[]string) bool { - if list == nil { - return false - } - for _, b := range *list { - if b == a { - return true - } - } - return false -}