gorm
gorm copied to clipboard
Joins and Preload Regression with gorm version 1.25.7
GORM Playground Link
https://github.com/go-gorm/playground/pull/688
Description
suppose we have the following data structures
type Repo struct {
ID uint `gorm:"primarykey"`
URL string `json:"RepoURL"`
Status string `json:"RepoStatus"`
}
type DispatchRecord struct {
ID uint `gorm:"primarykey"`
PlaybookURL string
PlaybookDispatcherID string
}
type UpdateTransaction struct {
ID uint `gorm:"primarykey"`
RepoID *uint
Repo *Repo
DispatchRecords []DispatchRecord `gorm:"many2many:updatetransaction_dispatchrecords"`
}
type DeviceUpdate struct {
ID uint `gorm:"primarykey"`
Name string
UpdateID *uint
Update *UpdateTransaction
}
Panic Occurs when Mixing Joins and Preload with the same field eg query like
DB.Joins("Update.Repo").Joins("Update").Preload("Update.DispatchRecords").Find(&deviceUpdates)
will panic with
panic: reflect: call of reflect.Value.Field on slice Value [recovered]
panic: reflect: call of reflect.Value.Field on slice Value
goroutine 15 [running]:
testing.tRunner.func1.2({0xc50dc0, 0xc000013e78})
/home/djlezzou/bin/go/src/testing/testing.go:1526 +0x24e
testing.tRunner.func1()
/home/djlezzou/bin/go/src/testing/testing.go:1529 +0x39f
panic({0xc50dc0, 0xc000013e78})
/home/djlezzou/bin/go/src/runtime/panic.go:884 +0x213
reflect.Value.Field({0xc1db00?, 0xc000012798?, 0xc0004e81a8?}, 0xc00001f970?)
/home/djlezzou/bin/go/src/reflect/value.go:1268 +0xe5
gorm.io/gorm/schema.(*Field).setupValuerAndSetter.func4({0xd3e90f?, 0x6?}, {0xc1db00?, 0xc000012798?, 0x10?})
/home/djlezzou/projects/gorm/playground/gorm/schema/field.go:503 +0x65
gorm.io/gorm/callbacks.preloadEntryPoint(0xc0001845d0, {0xc00001f970, 0x1, 0x1}, 0xc0004b7748, 0xc000012798?, {0x0, 0x0, 0x0})
/home/djlezzou/projects/gorm/playground/gorm/callbacks/preload.go:124 +0x429
gorm.io/gorm/callbacks.Preload(0xc000023b90)
/home/djlezzou/projects/gorm/playground/gorm/callbacks/query.go:283 +0x2e5
gorm.io/gorm.(*processor).Execute(0xc0002508c0, 0xc00025c360?)
/home/djlezzou/projects/gorm/playground/gorm/callbacks.go:130 +0x3ce
gorm.io/gorm.(*DB).Find(0x1221520?, {0xc04c60?, 0xc000012798}, {0x0, 0x0, 0x0})
/home/djlezzou/projects/gorm/playground/gorm/finisher_api.go:170 +0x137
gorm.io/playground.TestGORM1(0x0?)
/home/djlezzou/projects/gorm/playground/main_test.go:72 +0x4ad
testing.tRunner(0xc000583380, 0xd97258)
/home/djlezzou/bin/go/src/testing/testing.go:1576 +0x10b
created by testing.(*T).Run
/home/djlezzou/bin/go/src/testing/testing.go:1629 +0x3ea
with version v1.25.6 all the tests passed
this has been discovered with dependency PR in our project https://github.com/RedHatInsights/edge-api/pull/2406
I think I found the problem
Used the same test used in unit tests in PR https://github.com/go-gorm/gorm/pull/6771 The unit tests are only using First with var find1 Value
But when using Find with type var find1 []Value it will panic eg :
type (
Preload struct {
ID uint
Value string
NestedID uint
}
Join struct {
ID uint
Value string
NestedID uint
}
Nested struct {
ID uint
Preloads []*Preload
Join Join
ValueID uint
}
Value struct {
ID uint
Name string
Nested Nested
}
)
func TestJoinsPreloads(t *testing.T) {
_ = DB.AutoMigrate(&Preload{}, &Join{}, &Nested{}, &Value{})
value := Value{
Name: "value",
Nested: Nested{
Preloads: []*Preload{
{Value: "p1"}, {Value: "p2"},
},
Join: Join{Value: "j1"},
},
}
if err := DB.Create(&value).Error; err != nil {
t.Errorf("failed to create value, got err: %v", err)
}
var err error
// this will succeed
var find Value
err = DB.Joins("Nested").Joins("Nested.Join").Preload("Nested.Preloads").First(&find).Error
if err != nil {
t.Errorf("Failed, got error: %v", err)
}
// this will panic
var values []Value
err = DB.Joins("Nested").Joins("Nested.Join").Preload("Nested.Preloads").Find(&values).Error
if err != nil {
t.Errorf("Failed, got error: %v", err)
}
}
the second query will panic
var values []Value
err = DB.Joins("Nested").Joins("Nested.Join").Preload("Nested.Preloads").Find(&values).Error
if err != nil {
t.Errorf("Failed, got error: %v", err)
}
The unit tests in that PR was not using Find with slice , but only First with pointer to a struct
Experiencing the same issue. Debugging revealed that the db.Statement.ReflectValue
here appears to be of Kind
reflect.Slice
despite my relationship being a simple struct pointer.
I have this exact same issue. Upgrading to 1.25.7 completely breaks my entire application consisting of a dozen+ microservices all using gorm.
I haven't investigated it, but it seems from the description that it may have something to do with https://github.com/go-gorm/gorm/pull/6771. Do you have time to take a look? @black-06
I haven't investigated it, but it seems from the description that it may have something to do with #6771. Do you have time to take a look? @black-06
Okay...
Hello @go-gorm maintainers 👋 do you know when this fix will be released?
I cannot test this with https://github.com/go-gorm/postgres/releases/tag/v1.5.7 because m.GuessConstraintInterfaceAndTable undefined
in <= v1.25.6
@DAcodedBEAT looks like it was released in 1.25.8