Merge pull request #1038 from RichardKnop/bugfix/preload-panic

Fixed an occurrence of a panic while preloading non existent fields.
This commit is contained in:
Jinzhu 2016-06-01 23:10:28 +08:00
commit dca5e54f8b
2 changed files with 65 additions and 7 deletions

View File

@ -28,6 +28,10 @@ func preloadCallback(scope *Scope) {
for idx, preloadField := range preloadFields {
var currentPreloadConditions []interface{}
if currentScope == nil {
continue
}
// if not preloaded
if preloadKey := strings.Join(preloadFields[:idx+1], "."); !preloadedMap[preloadKey] {
@ -67,11 +71,13 @@ func preloadCallback(scope *Scope) {
// preload next level
if idx < len(preloadFields)-1 {
currentScope = currentScope.getColumnAsScope(preloadField)
if currentScope != nil {
currentFields = currentScope.Fields()
}
}
}
}
}
func (scope *Scope) generatePreloadDBWithConditions(conditions []interface{}) (*DB, []interface{}) {
var (

View File

@ -1288,17 +1288,23 @@ func TestNilPointerSlice(t *testing.T) {
t.Error(err)
}
want := Level1{Value: "Bob", Level2: &Level2{
want := Level1{
Value: "Bob",
Level2: &Level2{
Value: "en",
Level3: &Level3{
Value: "native",
},
}}
},
}
if err := DB.Save(&want).Error; err != nil {
t.Error(err)
}
want2 := Level1{Value: "Tom", Level2: nil}
want2 := Level1{
Value: "Tom",
Level2: nil,
}
if err := DB.Save(&want2).Error; err != nil {
t.Error(err)
}
@ -1321,6 +1327,52 @@ func TestNilPointerSlice(t *testing.T) {
}
}
func TestNilPointerSlice2(t *testing.T) {
type (
Level4 struct {
ID uint
}
Level3 struct {
ID uint
Level4ID sql.NullInt64 `sql:"index"`
Level4 *Level4
}
Level2 struct {
ID uint
Level3s []*Level3 `gorm:"many2many:level2_level3s"`
}
Level1 struct {
ID uint
Level2ID sql.NullInt64 `sql:"index"`
Level2 *Level2
}
)
DB.DropTableIfExists(new(Level4))
DB.DropTableIfExists(new(Level3))
DB.DropTableIfExists(new(Level2))
DB.DropTableIfExists(new(Level1))
if err := DB.AutoMigrate(new(Level4), new(Level3), new(Level2), new(Level1)).Error; err != nil {
t.Error(err)
}
want := new(Level1)
if err := DB.Save(want).Error; err != nil {
t.Error(err)
}
got := new(Level1)
err := DB.Preload("Level2.Level3s.Level4").Last(&got).Error
if err != nil {
t.Error(err)
}
if !reflect.DeepEqual(got, want) {
t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
}
}
func toJSONString(v interface{}) []byte {
r, _ := json.MarshalIndent(v, "", " ")
return r