mirror of https://github.com/go-gorm/gorm.git
Fix preload duplicates has many related objects
This commit is contained in:
parent
24501a3c1a
commit
ca46038cb4
|
@ -186,13 +186,6 @@ func (scope *Scope) handleHasManyPreload(field *Field, conditions []interface{})
|
||||||
for j := 0; j < indirectScopeValue.Len(); j++ {
|
for j := 0; j < indirectScopeValue.Len(); j++ {
|
||||||
object := indirect(indirectScopeValue.Index(j))
|
object := indirect(indirectScopeValue.Index(j))
|
||||||
objectRealValue := getValueFromFields(object, relation.AssociationForeignFieldNames)
|
objectRealValue := getValueFromFields(object, relation.AssociationForeignFieldNames)
|
||||||
if j > 0 {
|
|
||||||
prevObject := indirect(indirectScopeValue.Index(j - 1))
|
|
||||||
prevObjectRealValue := getValueFromFields(prevObject, relation.AssociationForeignFieldNames)
|
|
||||||
if toString(prevObjectRealValue) == toString(objectRealValue) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if results, ok := preloadMap[toString(objectRealValue)]; ok {
|
if results, ok := preloadMap[toString(objectRealValue)]; ok {
|
||||||
f := object.FieldByName(field.Name)
|
f := object.FieldByName(field.Name)
|
||||||
f.Set(reflect.Append(f, results...))
|
f.Set(reflect.Append(f, results...))
|
||||||
|
|
|
@ -1513,19 +1513,23 @@ func TestPrefixedPreloadDuplication(t *testing.T) {
|
||||||
type (
|
type (
|
||||||
Level4 struct {
|
Level4 struct {
|
||||||
ID uint
|
ID uint
|
||||||
|
Name string
|
||||||
Level3ID uint
|
Level3ID uint
|
||||||
}
|
}
|
||||||
Level3 struct {
|
Level3 struct {
|
||||||
ID uint
|
ID uint
|
||||||
|
Name string
|
||||||
Level4s []*Level4
|
Level4s []*Level4
|
||||||
}
|
}
|
||||||
Level2 struct {
|
Level2 struct {
|
||||||
ID uint
|
ID uint
|
||||||
|
Name string
|
||||||
Level3ID sql.NullInt64 `sql:"index"`
|
Level3ID sql.NullInt64 `sql:"index"`
|
||||||
Level3 *Level3
|
Level3 *Level3
|
||||||
}
|
}
|
||||||
Level1 struct {
|
Level1 struct {
|
||||||
ID uint
|
ID uint
|
||||||
|
Name string
|
||||||
Level2ID sql.NullInt64 `sql:"index"`
|
Level2ID sql.NullInt64 `sql:"index"`
|
||||||
Level2 *Level2
|
Level2 *Level2
|
||||||
}
|
}
|
||||||
|
@ -1540,7 +1544,7 @@ func TestPrefixedPreloadDuplication(t *testing.T) {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
lvl := new(Level3)
|
lvl := &Level3{}
|
||||||
if err := DB.Save(lvl).Error; err != nil {
|
if err := DB.Save(lvl).Error; err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
7
scope.go
7
scope.go
|
@ -1237,6 +1237,7 @@ func (scope *Scope) getColumnAsScope(column string) *Scope {
|
||||||
fieldType = fieldType.Elem()
|
fieldType = fieldType.Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resultsMap := map[interface{}]bool{}
|
||||||
results := reflect.New(reflect.SliceOf(reflect.PtrTo(fieldType))).Elem()
|
results := reflect.New(reflect.SliceOf(reflect.PtrTo(fieldType))).Elem()
|
||||||
|
|
||||||
for i := 0; i < indirectScopeValue.Len(); i++ {
|
for i := 0; i < indirectScopeValue.Len(); i++ {
|
||||||
|
@ -1244,11 +1245,13 @@ func (scope *Scope) getColumnAsScope(column string) *Scope {
|
||||||
|
|
||||||
if result.Kind() == reflect.Slice {
|
if result.Kind() == reflect.Slice {
|
||||||
for j := 0; j < result.Len(); j++ {
|
for j := 0; j < result.Len(); j++ {
|
||||||
if elem := result.Index(j); elem.CanAddr() {
|
if elem := result.Index(j); elem.CanAddr() && resultsMap[elem.Addr()] != true {
|
||||||
|
resultsMap[elem.Addr()] = true
|
||||||
results = reflect.Append(results, elem.Addr())
|
results = reflect.Append(results, elem.Addr())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if result.CanAddr() {
|
} else if result.CanAddr() && resultsMap[result.Addr()] != true {
|
||||||
|
resultsMap[result.Addr()] = true
|
||||||
results = reflect.Append(results, result.Addr())
|
results = reflect.Append(results, result.Addr())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue