mirror of https://github.com/go-gorm/gorm.git
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
This commit is contained in:
parent
57d927d046
commit
5d91ddac8c
|
@ -7,7 +7,6 @@ import (
|
||||||
|
|
||||||
"github.com/jinzhu/inflection"
|
"github.com/jinzhu/inflection"
|
||||||
"gorm.io/gorm/clause"
|
"gorm.io/gorm/clause"
|
||||||
"gorm.io/gorm/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// RelationshipType relationship type
|
// RelationshipType relationship type
|
||||||
|
@ -78,6 +77,8 @@ func (schema *Schema) parseRelation(field *Field) *Relationship {
|
||||||
schema.buildPolymorphicRelation(relation, field, polymorphic)
|
schema.buildPolymorphicRelation(relation, field, polymorphic)
|
||||||
} else if many2many := field.TagSettings["MANY2MANY"]; many2many != "" {
|
} else if many2many := field.TagSettings["MANY2MANY"]; many2many != "" {
|
||||||
schema.buildMany2ManyRelation(relation, field, many2many)
|
schema.buildMany2ManyRelation(relation, field, many2many)
|
||||||
|
} else if belongsTo := field.TagSettings["BELONGSTO"]; belongsTo != "" {
|
||||||
|
schema.guessRelation(relation, field, guessBelongs)
|
||||||
} else {
|
} else {
|
||||||
switch field.IndirectFieldType.Kind() {
|
switch field.IndirectFieldType.Kind() {
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
|
@ -405,14 +406,11 @@ func (schema *Schema) guessRelation(relation *Relationship, field *Field, cgl gu
|
||||||
|
|
||||||
if len(relation.foreignKeys) > 0 {
|
if len(relation.foreignKeys) > 0 {
|
||||||
for _, foreignKey := range relation.foreignKeys {
|
for _, foreignKey := range relation.foreignKeys {
|
||||||
ff := foreignSchema.LookUpField(foreignKey)
|
if f := foreignSchema.LookUpField(foreignKey); f != nil {
|
||||||
pf := primarySchema.LookUpField(foreignKey)
|
foreignFields = append(foreignFields, f)
|
||||||
isKeySame := utils.ExistsIn(foreignKey, &relation.primaryKeys)
|
} else {
|
||||||
if ff == nil || (pf != nil && ff != nil && schema == primarySchema && primarySchema != foreignSchema && !isKeySame && field.IndirectFieldType.Kind() == reflect.Struct) {
|
|
||||||
reguessOrErr()
|
reguessOrErr()
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
foreignFields = append(foreignFields, ff)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -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) {
|
func TestHasOneWithOnlyReferences(t *testing.T) {
|
||||||
type Profile struct {
|
type Profile struct {
|
||||||
gorm.Model
|
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 {
|
type Profile struct {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
Name string
|
Name string
|
||||||
ProfileRefer int
|
ProfileRefer int // not used in relationship
|
||||||
}
|
}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
Profile Profile `gorm:"ForeignKey:ProfileRefer"`
|
Profile Profile `gorm:"ForeignKey:ID;references:ProfileRefer"`
|
||||||
ProfileRefer int
|
ProfileRefer int
|
||||||
}
|
}
|
||||||
|
|
||||||
checkStructRelation(t, &User{}, Relation{
|
checkStructRelation(t, &User{}, Relation{
|
||||||
Name: "Profile", Type: schema.BelongsTo, Schema: "User", FieldSchema: "Profile",
|
Name: "Profile", Type: schema.HasOne, Schema: "User", FieldSchema: "Profile",
|
||||||
References: []Reference{{"ID", "Profile", "ProfileRefer", "User", "", false}},
|
References: []Reference{{"ProfileRefer", "User", "ID", "Profile", "", true}},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,15 +114,3 @@ func ToString(value interface{}) string {
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExistsIn(a string, list *[]string) bool {
|
|
||||||
if list == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for _, b := range *list {
|
|
||||||
if b == a {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue