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:
|
||||
if rv.Len() > 0 {
|
||||
reflectValue := rel.FieldSchema.MakeSlice().Elem()
|
||||
reflectValue.SetLen(rv.Len())
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
frv := rel.Field.ReflectValueOf(db.Statement.Context, rv.Index(i))
|
||||
if frv.Kind() != reflect.Ptr {
|
||||
reflectValue.Index(i).Set(frv.Addr())
|
||||
reflectValue = reflect.Append(reflectValue, frv.Addr())
|
||||
} 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 {
|
||||
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.Elem().Set(slice)
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package tests_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gorm.io/gorm"
|
||||
. "gorm.io/gorm/utils/tests"
|
||||
)
|
||||
|
@ -402,3 +404,75 @@ func TestNestedJoins(t *testing.T) {
|
|||
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