Fixed a bug with invalid zero value in preload

When using pointers in model structs, there is an edge case.

When using preload to eagerly preload a many to many relationship and
the main row is not found by a primary key, use of reflect.Indirect in
preload.go results in a zero value and the subsequent call to
FieldByName panics the program.
This commit is contained in:
Richard Knop 2015-12-16 00:18:36 +08:00
parent ba694926d0
commit e69ffaa9c4
1 changed files with 15 additions and 2 deletions

View File

@ -10,8 +10,15 @@ import (
func getRealValue(value reflect.Value, columns []string) (results []interface{}) { func getRealValue(value reflect.Value, columns []string) (results []interface{}) {
for _, column := range columns { for _, column := range columns {
if reflect.Indirect(value).FieldByName(column).IsValid() { pointedValue := reflect.Indirect(value)
result := reflect.Indirect(value).FieldByName(column).Interface() // If v is a nil pointer, Indirect returns a zero Value!
// Therefor we need to check for a zero value,
// as FieldByName could panic
if !pointedValue.IsValid() {
continue
}
if pointedValue.FieldByName(column).IsValid() {
result := pointedValue.FieldByName(column).Interface()
if r, ok := result.(driver.Valuer); ok { if r, ok := result.(driver.Valuer); ok {
result, _ = r.Value() result, _ = r.Value()
} }
@ -290,6 +297,12 @@ func (scope *Scope) handleManyToManyPreload(field *Field, conditions []interface
} }
} }
} else { } else {
// If v is a nil pointer, Indirect returns a zero Value!
// Therefor we need to check for a zero value,
// as FieldByName could panic
if !scope.IndirectValue().IsValid() {
return
}
object := scope.IndirectValue() object := scope.IndirectValue()
source := getRealValue(object, associationForeignStructFieldNames) source := getRealValue(object, associationForeignStructFieldNames)
field := object.FieldByName(field.Name) field := object.FieldByName(field.Name)