Fix parse embedded relations, close #3964, #3965

This commit is contained in:
Jinzhu 2021-01-19 15:40:04 +08:00
parent 3d87575e7e
commit 6095dbf939
3 changed files with 51 additions and 13 deletions

View File

@ -667,15 +667,17 @@ func (m Migrator) ReorderModels(values []interface{}, autoAdd bool) (results []i
} }
orderedModelNamesMap[name] = true orderedModelNamesMap[name] = true
if autoAdd {
dep := valuesMap[name] dep := valuesMap[name]
for _, d := range dep.Depends { for _, d := range dep.Depends {
if _, ok := valuesMap[d.Table]; ok { if _, ok := valuesMap[d.Table]; ok {
insertIntoOrderedList(d.Table) insertIntoOrderedList(d.Table)
} else if autoAdd { } else {
parseDependence(reflect.New(d.ModelType).Interface(), autoAdd) parseDependence(reflect.New(d.ModelType).Interface(), autoAdd)
insertIntoOrderedList(d.Table) insertIntoOrderedList(d.Table)
} }
} }
}
orderedModelNames = append(orderedModelNames, name) orderedModelNames = append(orderedModelNames, name)
} }

View File

@ -53,7 +53,7 @@ type Reference struct {
OwnPrimaryKey bool OwnPrimaryKey bool
} }
func (schema *Schema) parseRelation(field *Field) { func (schema *Schema) parseRelation(field *Field) *Relationship {
var ( var (
err error err error
fieldValue = reflect.New(field.IndirectFieldType).Interface() fieldValue = reflect.New(field.IndirectFieldType).Interface()
@ -67,13 +67,10 @@ func (schema *Schema) parseRelation(field *Field) {
) )
cacheStore := schema.cacheStore cacheStore := schema.cacheStore
if field.OwnerSchema != nil {
cacheStore = field.OwnerSchema.cacheStore
}
if relation.FieldSchema, err = getOrParse(fieldValue, cacheStore, schema.namer); err != nil { if relation.FieldSchema, err = getOrParse(fieldValue, cacheStore, schema.namer); err != nil {
schema.err = err schema.err = err
return return nil
} }
if polymorphic := field.TagSettings["POLYMORPHIC"]; polymorphic != "" { if polymorphic := field.TagSettings["POLYMORPHIC"]; polymorphic != "" {
@ -92,7 +89,8 @@ func (schema *Schema) parseRelation(field *Field) {
} }
if relation.Type == "has" { if relation.Type == "has" {
if relation.FieldSchema != relation.Schema && relation.Polymorphic == nil { // don't add relations to embeded schema, which might be shared
if relation.FieldSchema != relation.Schema && relation.Polymorphic == nil && field.OwnerSchema == nil {
relation.FieldSchema.Relationships.Relations["_"+relation.Schema.Name+"_"+relation.Name] = relation relation.FieldSchema.Relationships.Relations["_"+relation.Schema.Name+"_"+relation.Name] = relation
} }
@ -117,6 +115,8 @@ func (schema *Schema) parseRelation(field *Field) {
schema.Relationships.Many2Many = append(schema.Relationships.Many2Many, relation) schema.Relationships.Many2Many = append(schema.Relationships.Many2Many, relation)
} }
} }
return relation
} }
// User has many Toys, its `Polymorphic` is `Owner`, Pet has one Toy, its `Polymorphic` is `Owner` // User has many Toys, its `Polymorphic` is `Owner`, Pet has one Toy, its `Polymorphic` is `Owner`

View File

@ -397,3 +397,39 @@ func TestMultipleMany2Many(t *testing.T) {
}, },
) )
} }
type CreatedByModel struct {
CreatedByID uint
CreatedBy *CreatedUser
}
type CreatedUser struct {
gorm.Model
CreatedByModel
}
func TestEmbeddedRelation(t *testing.T) {
checkStructRelation(t, &CreatedUser{}, Relation{
Name: "CreatedBy", Type: schema.BelongsTo, Schema: "CreatedUser", FieldSchema: "CreatedUser",
References: []Reference{
{"ID", "CreatedUser", "CreatedByID", "CreatedUser", "", false},
},
})
userSchema, err := schema.Parse(&CreatedUser{}, &sync.Map{}, schema.NamingStrategy{})
if err != nil {
t.Fatalf("failed to parse schema, got error %v", err)
}
if len(userSchema.Relationships.Relations) != 1 {
t.Fatalf("expects 1 relations, but got %v", len(userSchema.Relationships.Relations))
}
if createdByRel, ok := userSchema.Relationships.Relations["CreatedBy"]; ok {
if createdByRel.FieldSchema != userSchema {
t.Fatalf("expects same field schema, but got new %p, old %p", createdByRel.FieldSchema, userSchema)
}
} else {
t.Fatalf("expects created by relations, but not found")
}
}