From 6095dbf939a8de468378084eb4cbbe9d83fe7201 Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Tue, 19 Jan 2021 15:40:04 +0800 Subject: [PATCH] Fix parse embedded relations, close #3964, #3965 --- migrator/migrator.go | 16 +++++++++------- schema/relationship.go | 12 ++++++------ schema/relationship_test.go | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/migrator/migrator.go b/migrator/migrator.go index a475d307..e25d427c 100644 --- a/migrator/migrator.go +++ b/migrator/migrator.go @@ -667,13 +667,15 @@ func (m Migrator) ReorderModels(values []interface{}, autoAdd bool) (results []i } orderedModelNamesMap[name] = true - dep := valuesMap[name] - for _, d := range dep.Depends { - if _, ok := valuesMap[d.Table]; ok { - insertIntoOrderedList(d.Table) - } else if autoAdd { - parseDependence(reflect.New(d.ModelType).Interface(), autoAdd) - insertIntoOrderedList(d.Table) + if autoAdd { + dep := valuesMap[name] + for _, d := range dep.Depends { + if _, ok := valuesMap[d.Table]; ok { + insertIntoOrderedList(d.Table) + } else { + parseDependence(reflect.New(d.ModelType).Interface(), autoAdd) + insertIntoOrderedList(d.Table) + } } } diff --git a/schema/relationship.go b/schema/relationship.go index b2253035..41e0b9bd 100644 --- a/schema/relationship.go +++ b/schema/relationship.go @@ -53,7 +53,7 @@ type Reference struct { OwnPrimaryKey bool } -func (schema *Schema) parseRelation(field *Field) { +func (schema *Schema) parseRelation(field *Field) *Relationship { var ( err error fieldValue = reflect.New(field.IndirectFieldType).Interface() @@ -67,13 +67,10 @@ func (schema *Schema) parseRelation(field *Field) { ) cacheStore := schema.cacheStore - if field.OwnerSchema != nil { - cacheStore = field.OwnerSchema.cacheStore - } if relation.FieldSchema, err = getOrParse(fieldValue, cacheStore, schema.namer); err != nil { schema.err = err - return + return nil } if polymorphic := field.TagSettings["POLYMORPHIC"]; polymorphic != "" { @@ -92,7 +89,8 @@ func (schema *Schema) parseRelation(field *Field) { } 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 } @@ -117,6 +115,8 @@ func (schema *Schema) parseRelation(field *Field) { 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` diff --git a/schema/relationship_test.go b/schema/relationship_test.go index 887e1341..64d0c2a7 100644 --- a/schema/relationship_test.go +++ b/schema/relationship_test.go @@ -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") + } +}