forked from mirror/gorm
increase performance m2m preload
This commit is contained in:
parent
e2689d335b
commit
07571d1adf
60
preload.go
60
preload.go
|
@ -202,20 +202,13 @@ func (scope *Scope) handleHasManyToManyPreload(field *Field, conditions []interf
|
||||||
destType = destType.Elem()
|
destType = destType.Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
var destKeys []string
|
|
||||||
var sourceKeys []string
|
var sourceKeys []string
|
||||||
var linkHash = make(map[string][]string)
|
var linkHash = make(map[string][]interface{})
|
||||||
|
|
||||||
for _, key := range joinTableHandler.DestinationForeignKeys() {
|
|
||||||
destKeys = append(destKeys, key.DBName)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, key := range joinTableHandler.SourceForeignKeys() {
|
for _, key := range joinTableHandler.SourceForeignKeys() {
|
||||||
sourceKeys = append(sourceKeys, key.DBName)
|
sourceKeys = append(sourceKeys, key.DBName)
|
||||||
}
|
}
|
||||||
|
|
||||||
results := reflect.New(field.Struct.Type).Elem()
|
|
||||||
|
|
||||||
db := scope.NewDB().Table(scope.New(reflect.New(destType).Interface()).TableName())
|
db := scope.NewDB().Table(scope.New(reflect.New(destType).Interface()).TableName())
|
||||||
preloadJoinDB := joinTableHandler.PreloadWithJoin(joinTableHandler, db, scope.Value)
|
preloadJoinDB := joinTableHandler.PreloadWithJoin(joinTableHandler, db, scope.Value)
|
||||||
if len(conditions) > 0 {
|
if len(conditions) > 0 {
|
||||||
|
@ -250,7 +243,6 @@ func (scope *Scope) handleHasManyToManyPreload(field *Field, conditions []interf
|
||||||
|
|
||||||
scope.Err(rows.Scan(values...))
|
scope.Err(rows.Scan(values...))
|
||||||
|
|
||||||
var destKey []interface{}
|
|
||||||
var sourceKey []interface{}
|
var sourceKey []interface{}
|
||||||
|
|
||||||
for index, column := range columns {
|
for index, column := range columns {
|
||||||
|
@ -261,59 +253,45 @@ func (scope *Scope) handleHasManyToManyPreload(field *Field, conditions []interf
|
||||||
} else if v := reflect.ValueOf(value).Elem().Elem(); v.IsValid() {
|
} else if v := reflect.ValueOf(value).Elem().Elem(); v.IsValid() {
|
||||||
field.Field.Set(v)
|
field.Field.Set(v)
|
||||||
}
|
}
|
||||||
} else if strInSlice(column, destKeys) {
|
|
||||||
destKey = append(destKey, *(value.(*interface{})))
|
|
||||||
} else if strInSlice(column, sourceKeys) {
|
} else if strInSlice(column, sourceKeys) {
|
||||||
sourceKey = append(sourceKey, *(value.(*interface{})))
|
sourceKey = append(sourceKey, *(value.(*interface{})))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(destKey) != 0 && len(sourceKey) != 0 {
|
if len(sourceKey) != 0 {
|
||||||
linkHash[toString(sourceKey)] = append(linkHash[toString(sourceKey)], toString(destKey))
|
if isPtr {
|
||||||
}
|
linkHash[toString(sourceKey)] = append(linkHash[toString(sourceKey)], elem.Addr())
|
||||||
|
} else {
|
||||||
if isPtr {
|
linkHash[toString(sourceKey)] = append(linkHash[toString(sourceKey)], elem)
|
||||||
results = reflect.Append(results, elem.Addr())
|
}
|
||||||
} else {
|
|
||||||
results = reflect.Append(results, elem)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if scope.IndirectValue().Kind() == reflect.Slice {
|
if scope.IndirectValue().Kind() == reflect.Slice {
|
||||||
objects := scope.IndirectValue()
|
objects := scope.IndirectValue()
|
||||||
for j := 0; j < objects.Len(); j++ {
|
for j := 0; j < objects.Len(); j++ {
|
||||||
var checked []string
|
|
||||||
|
|
||||||
object := reflect.Indirect(objects.Index(j))
|
object := reflect.Indirect(objects.Index(j))
|
||||||
source := getRealValue(object, relation.AssociationForeignStructFieldNames)
|
source := getRealValue(object, relation.AssociationForeignStructFieldNames)
|
||||||
|
links := linkHash[toString(source)]
|
||||||
|
|
||||||
for i := 0; i < results.Len(); i++ {
|
for i := 0; i < len(links); i++ {
|
||||||
result := results.Index(i)
|
f := object.FieldByName(field.Name)
|
||||||
value := getRealValue(result, relation.ForeignStructFieldNames)
|
a := links[i].(reflect.Value)
|
||||||
|
f.Set(reflect.Append(f, a))
|
||||||
if strInSlice(toString(value), linkHash[toString(source)]) && !strInSlice(toString(value), checked) {
|
continue
|
||||||
f := object.FieldByName(field.Name)
|
|
||||||
f.Set(reflect.Append(f, result))
|
|
||||||
checked = append(checked, toString(value))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
object := scope.IndirectValue()
|
object := scope.IndirectValue()
|
||||||
var checked []string
|
|
||||||
source := getRealValue(object, relation.AssociationForeignStructFieldNames)
|
source := getRealValue(object, relation.AssociationForeignStructFieldNames)
|
||||||
|
|
||||||
for i := 0; i < results.Len(); i++ {
|
links := linkHash[toString(source)]
|
||||||
result := results.Index(i)
|
|
||||||
value := getRealValue(result, relation.ForeignStructFieldNames)
|
|
||||||
|
|
||||||
if strInSlice(toString(value), linkHash[toString(source)]) && !strInSlice(toString(value), checked) {
|
for i := 0; i < len(links); i++ {
|
||||||
f := object.FieldByName(field.Name)
|
f := object.FieldByName(field.Name)
|
||||||
f.Set(reflect.Append(f, result))
|
a := links[i].(reflect.Value)
|
||||||
checked = append(checked, toString(value))
|
f.Set(reflect.Append(f, a))
|
||||||
continue
|
continue
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue