mirror of https://github.com/go-gorm/gorm.git
Merge pull request #669 from nkovacs/addr-fix
Fix panic: reflect.Value.Addr of unaddressable value
This commit is contained in:
commit
e6ef3818bf
13
preload.go
13
preload.go
|
@ -337,15 +337,24 @@ func (scope *Scope) getColumnsAsScope(column string) *Scope {
|
||||||
}
|
}
|
||||||
if column.Kind() == reflect.Slice {
|
if column.Kind() == reflect.Slice {
|
||||||
for i := 0; i < column.Len(); i++ {
|
for i := 0; i < column.Len(); i++ {
|
||||||
columns = reflect.Append(columns, column.Index(i).Addr())
|
elem := column.Index(i)
|
||||||
|
if elem.CanAddr() {
|
||||||
|
columns = reflect.Append(columns, elem.Addr())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if column.CanAddr() {
|
||||||
columns = reflect.Append(columns, column.Addr())
|
columns = reflect.Append(columns, column.Addr())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return scope.New(columns.Interface())
|
return scope.New(columns.Interface())
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
return scope.New(values.FieldByName(column).Addr().Interface())
|
field := values.FieldByName(column)
|
||||||
|
if !field.CanAddr() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return scope.New(field.Addr().Interface())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -772,6 +772,67 @@ func TestManyToManyPreloadForPointer(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNilPointerSlice(t *testing.T) {
|
||||||
|
type (
|
||||||
|
Level3 struct {
|
||||||
|
ID uint `gorm:"primary_key;"`
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
Level2 struct {
|
||||||
|
ID uint `gorm:"primary_key;"`
|
||||||
|
Value string
|
||||||
|
Level3ID uint
|
||||||
|
Level3 *Level3
|
||||||
|
}
|
||||||
|
Level1 struct {
|
||||||
|
ID uint `gorm:"primary_key;"`
|
||||||
|
Value string
|
||||||
|
Level2ID uint
|
||||||
|
Level2 *Level2
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
DB.DropTableIfExists(&Level3{})
|
||||||
|
DB.DropTableIfExists(&Level2{})
|
||||||
|
DB.DropTableIfExists(&Level1{})
|
||||||
|
|
||||||
|
if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
want := Level1{Value: "Bob", Level2: &Level2{
|
||||||
|
Value: "en",
|
||||||
|
Level3: &Level3{
|
||||||
|
Value: "native",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
if err := DB.Save(&want).Error; err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
want2 := Level1{Value: "Tom", Level2: nil}
|
||||||
|
if err := DB.Save(&want2).Error; err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var got []Level1
|
||||||
|
if err := DB.Debug().Preload("Level2").Preload("Level2.Level3").Find(&got).Error; err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(got) != 2 {
|
||||||
|
t.Fatalf("got %v items, expected 2", len(got))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(got[0], want) && !reflect.DeepEqual(got[1], want) {
|
||||||
|
t.Errorf("got %s; want array containing %s", toJSONString(got), toJSONString(want))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(got[0], want2) && !reflect.DeepEqual(got[1], want2) {
|
||||||
|
t.Errorf("got %s; want array containing %s", toJSONString(got), toJSONString(want2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func toJSONString(v interface{}) []byte {
|
func toJSONString(v interface{}) []byte {
|
||||||
r, _ := json.MarshalIndent(v, "", " ")
|
r, _ := json.MarshalIndent(v, "", " ")
|
||||||
return r
|
return r
|
||||||
|
|
Loading…
Reference in New Issue