mirror of https://github.com/go-gorm/gorm.git
fix: use reflect.Append when preloading nested associations (#7014)
Co-authored-by: Emilien Kofman <emilien.kofman@miimosa.com>
This commit is contained in:
parent
78c6dfd712
commit
05167fd591
|
@ -125,13 +125,15 @@ func preloadEntryPoint(db *gorm.DB, joins []string, relationships *schema.Relati
|
||||||
case reflect.Slice, reflect.Array:
|
case reflect.Slice, reflect.Array:
|
||||||
if rv.Len() > 0 {
|
if rv.Len() > 0 {
|
||||||
reflectValue := rel.FieldSchema.MakeSlice().Elem()
|
reflectValue := rel.FieldSchema.MakeSlice().Elem()
|
||||||
reflectValue.SetLen(rv.Len())
|
|
||||||
for i := 0; i < rv.Len(); i++ {
|
for i := 0; i < rv.Len(); i++ {
|
||||||
frv := rel.Field.ReflectValueOf(db.Statement.Context, rv.Index(i))
|
frv := rel.Field.ReflectValueOf(db.Statement.Context, rv.Index(i))
|
||||||
if frv.Kind() != reflect.Ptr {
|
if frv.Kind() != reflect.Ptr {
|
||||||
reflectValue.Index(i).Set(frv.Addr())
|
reflectValue = reflect.Append(reflectValue, frv.Addr())
|
||||||
} else {
|
} else {
|
||||||
reflectValue.Index(i).Set(frv)
|
if frv.IsNil() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
reflectValue = reflect.Append(reflectValue, frv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,9 +67,10 @@ func (schema Schema) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (schema Schema) MakeSlice() reflect.Value {
|
func (schema Schema) MakeSlice() reflect.Value {
|
||||||
slice := reflect.MakeSlice(reflect.SliceOf(reflect.PtrTo(schema.ModelType)), 0, 20)
|
slice := reflect.MakeSlice(reflect.SliceOf(reflect.PointerTo(schema.ModelType)), 0, 20)
|
||||||
results := reflect.New(slice.Type())
|
results := reflect.New(slice.Type())
|
||||||
results.Elem().Set(slice)
|
results.Elem().Set(slice)
|
||||||
|
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package tests_test
|
package tests_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
. "gorm.io/gorm/utils/tests"
|
. "gorm.io/gorm/utils/tests"
|
||||||
)
|
)
|
||||||
|
@ -402,3 +404,75 @@ func TestNestedJoins(t *testing.T) {
|
||||||
CheckPet(t, *user.Manager.NamedPet, *users2[idx].Manager.NamedPet)
|
CheckPet(t, *user.Manager.NamedPet, *users2[idx].Manager.NamedPet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestJoinsPreload_Issue7013(t *testing.T) {
|
||||||
|
manager := &User{Name: "Manager"}
|
||||||
|
DB.Create(manager)
|
||||||
|
|
||||||
|
var userIDs []uint
|
||||||
|
for i := 0; i < 21; i++ {
|
||||||
|
user := &User{Name: fmt.Sprintf("User%d", i), ManagerID: &manager.ID}
|
||||||
|
DB.Create(user)
|
||||||
|
userIDs = append(userIDs, user.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
var entries []User
|
||||||
|
assert.NotPanics(t, func() {
|
||||||
|
assert.NoError(t,
|
||||||
|
DB.Debug().Preload("Manager.Team").
|
||||||
|
Joins("Manager.Company").
|
||||||
|
Find(&entries).Error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJoinsPreload_Issue7013_RelationEmpty(t *testing.T) {
|
||||||
|
type (
|
||||||
|
Furniture struct {
|
||||||
|
gorm.Model
|
||||||
|
OwnerID *uint
|
||||||
|
}
|
||||||
|
|
||||||
|
Owner struct {
|
||||||
|
gorm.Model
|
||||||
|
Furnitures []Furniture
|
||||||
|
CompanyID *uint
|
||||||
|
Company Company
|
||||||
|
}
|
||||||
|
|
||||||
|
Building struct {
|
||||||
|
gorm.Model
|
||||||
|
Name string
|
||||||
|
OwnerID *uint
|
||||||
|
Owner Owner
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
DB.Migrator().DropTable(&Building{}, &Owner{}, &Furniture{})
|
||||||
|
DB.Migrator().AutoMigrate(&Building{}, &Owner{}, &Furniture{})
|
||||||
|
|
||||||
|
home := &Building{Name: "relation_empty"}
|
||||||
|
DB.Create(home)
|
||||||
|
|
||||||
|
var entries []Building
|
||||||
|
assert.NotPanics(t, func() {
|
||||||
|
assert.NoError(t,
|
||||||
|
DB.Debug().Preload("Owner.Furnitures").
|
||||||
|
Joins("Owner.Company").
|
||||||
|
Find(&entries).Error)
|
||||||
|
})
|
||||||
|
|
||||||
|
AssertEqual(t, entries, []Building{{Model: home.Model, Name: "relation_empty", Owner: Owner{Company: Company{}}}})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJoinsPreload_Issue7013_NoEntries(t *testing.T) {
|
||||||
|
var entries []User
|
||||||
|
assert.NotPanics(t, func() {
|
||||||
|
assert.NoError(t,
|
||||||
|
DB.Debug().Preload("Manager.Team").
|
||||||
|
Joins("Manager.Company").
|
||||||
|
Where("false").
|
||||||
|
Find(&entries).Error)
|
||||||
|
})
|
||||||
|
|
||||||
|
AssertEqual(t, len(entries), 0)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue