Fix stack overflow for embedded self-referred associations, close #3269

This commit is contained in:
Jinzhu 2020-08-17 12:02:41 +08:00
parent 2faff25dfb
commit 6834c25cec
4 changed files with 42 additions and 11 deletions

View File

@ -317,7 +317,13 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field {
field.Creatable = false field.Creatable = false
field.Updatable = false field.Updatable = false
field.Readable = false field.Readable = false
if field.EmbeddedSchema, err = Parse(fieldValue.Interface(), &sync.Map{}, schema.namer); err != nil {
cacheStore := schema.cacheStore
if _, embedded := schema.cacheStore.Load("embedded_cache_store"); !embedded {
cacheStore = &sync.Map{}
cacheStore.Store("embedded_cache_store", true)
}
if field.EmbeddedSchema, err = Parse(fieldValue.Interface(), cacheStore, schema.namer); err != nil {
schema.err = err schema.err = err
} }
for _, ef := range field.EmbeddedSchema.Fields { for _, ef := range field.EmbeddedSchema.Fields {

View File

@ -39,3 +39,25 @@ type AdvancedDataTypeUser struct {
Active mybool Active mybool
Admin *mybool Admin *mybool
} }
type BaseModel struct {
ID uint `gorm:"primarykey"`
CreatedAt time.Time
CreatedBy *int
Created *VersionUser `gorm:"foreignKey:CreatedBy"`
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
type VersionModel struct {
BaseModel
Version int
CompanyID int
}
type VersionUser struct {
VersionModel
Name string
Age uint
Birthday *time.Time
}

View File

@ -5,7 +5,6 @@ import (
"reflect" "reflect"
"regexp" "regexp"
"strings" "strings"
"sync"
"github.com/jinzhu/inflection" "github.com/jinzhu/inflection"
"gorm.io/gorm/clause" "gorm.io/gorm/clause"
@ -67,16 +66,14 @@ func (schema *Schema) parseRelation(field *Field) {
} }
) )
cacheStore := schema.cacheStore
if field.OwnerSchema != nil { if field.OwnerSchema != nil {
if relation.FieldSchema, err = Parse(fieldValue, &sync.Map{}, schema.namer); err != nil { cacheStore = field.OwnerSchema.cacheStore
schema.err = err }
return
} if relation.FieldSchema, err = Parse(fieldValue, cacheStore, schema.namer); err != nil {
} else { schema.err = err
if relation.FieldSchema, err = Parse(fieldValue, schema.cacheStore, schema.namer); err != nil { return
schema.err = err
return
}
} }
if polymorphic := field.TagSettings["POLYMORPHIC"]; polymorphic != "" { if polymorphic := field.TagSettings["POLYMORPHIC"]; polymorphic != "" {

View File

@ -160,3 +160,9 @@ func TestCustomizeTableName(t *testing.T) {
t.Errorf("Failed to customize table with TableName method") t.Errorf("Failed to customize table with TableName method")
} }
} }
func TestNestedModel(t *testing.T) {
if _, err := schema.Parse(&VersionUser{}, &sync.Map{}, schema.NamingStrategy{}); err != nil {
t.Fatalf("failed to parse nested user, got error %v", err)
}
}