2021-06-07 01:13:45 +00:00
|
|
|
// Copyright 2017 The Xorm Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package xorm
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
2021-07-22 07:17:38 +00:00
|
|
|
"fmt"
|
2021-06-07 01:13:45 +00:00
|
|
|
"reflect"
|
|
|
|
|
2021-07-22 03:25:37 +00:00
|
|
|
"xorm.io/xorm/internal/utils"
|
|
|
|
"xorm.io/xorm/schemas"
|
2021-06-07 01:13:45 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Load loads associated fields from database
|
|
|
|
func (session *Session) Load(beanOrSlices interface{}, cols ...string) error {
|
|
|
|
v := reflect.ValueOf(beanOrSlices)
|
|
|
|
if v.Kind() == reflect.Ptr {
|
|
|
|
v = v.Elem()
|
|
|
|
}
|
|
|
|
if v.Kind() == reflect.Slice {
|
2021-07-22 05:22:35 +00:00
|
|
|
return session.loadFindSlice(v, cols...)
|
|
|
|
} else if v.Kind() == reflect.Map {
|
|
|
|
return session.loadFindMap(v, cols...)
|
2021-06-07 01:13:45 +00:00
|
|
|
} else if v.Kind() == reflect.Struct {
|
2021-07-22 05:22:35 +00:00
|
|
|
return session.loadGet(v, cols...)
|
2021-06-07 01:13:45 +00:00
|
|
|
}
|
2021-07-22 05:22:35 +00:00
|
|
|
return errors.New("unsupported load type, must struct, slice or map")
|
2021-06-07 01:13:45 +00:00
|
|
|
}
|
|
|
|
|
2021-07-22 03:25:37 +00:00
|
|
|
func isStringInSlice(s string, slice []string) bool {
|
|
|
|
for _, e := range slice {
|
|
|
|
if s == e {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2021-06-07 01:13:45 +00:00
|
|
|
// loadFind load 's belongs to tag field immedicatlly
|
2021-07-22 05:22:35 +00:00
|
|
|
func (session *Session) loadFindSlice(v reflect.Value, cols ...string) error {
|
2021-06-07 01:13:45 +00:00
|
|
|
if v.Kind() != reflect.Slice {
|
|
|
|
return errors.New("only slice is supported")
|
|
|
|
}
|
|
|
|
|
|
|
|
if v.Len() <= 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
vv := v.Index(0)
|
|
|
|
if vv.Kind() == reflect.Ptr {
|
|
|
|
vv = vv.Elem()
|
|
|
|
}
|
2021-07-22 03:25:37 +00:00
|
|
|
tb, err := session.engine.tagParser.ParseWithCache(vv)
|
2021-06-07 01:13:45 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:17:38 +00:00
|
|
|
type Va struct {
|
|
|
|
v reflect.Value
|
|
|
|
pk []interface{}
|
|
|
|
col *schemas.Column
|
|
|
|
}
|
|
|
|
|
|
|
|
var pks = make(map[*schemas.Column]*Va)
|
2021-06-07 01:13:45 +00:00
|
|
|
for i := 0; i < v.Len(); i++ {
|
|
|
|
ev := v.Index(i)
|
|
|
|
|
2021-07-22 07:17:38 +00:00
|
|
|
fmt.Println("1====", ev.Interface(), tb.Name, len(tb.Columns()))
|
|
|
|
|
2021-06-07 01:13:45 +00:00
|
|
|
for _, col := range tb.Columns() {
|
2021-07-22 07:17:38 +00:00
|
|
|
fmt.Println("====", cols, col.Name)
|
2021-06-07 01:13:45 +00:00
|
|
|
if len(cols) > 0 && !isStringInSlice(col.Name, cols) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:17:38 +00:00
|
|
|
fmt.Println("3------", col.Name, col.AssociateTable)
|
|
|
|
|
|
|
|
if col.AssociateTable == nil || col.AssociateType != schemas.AssociateBelongsTo {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
colV, err := col.ValueOfV(&ev)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
pkCols := col.AssociateTable.PKColumns()
|
|
|
|
pkV, err := pkCols[0].ValueOfV(colV)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
vv := pkV.Interface()
|
2021-06-07 01:13:45 +00:00
|
|
|
|
2021-07-22 07:17:38 +00:00
|
|
|
fmt.Println("2====", vv)
|
2021-06-07 01:13:45 +00:00
|
|
|
|
2021-07-22 07:17:38 +00:00
|
|
|
if !utils.IsZero(vv) {
|
|
|
|
va, ok := pks[col]
|
|
|
|
if !ok {
|
|
|
|
va = &Va{
|
|
|
|
v: ev,
|
|
|
|
col: pkCols[0],
|
2021-06-07 01:13:45 +00:00
|
|
|
}
|
2021-07-22 07:17:38 +00:00
|
|
|
pks[col] = va
|
2021-06-07 01:13:45 +00:00
|
|
|
}
|
2021-07-22 07:17:38 +00:00
|
|
|
va.pk = append(va.pk, vv)
|
2021-06-07 01:13:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-22 07:17:38 +00:00
|
|
|
for col, va := range pks {
|
2021-08-10 12:31:37 +00:00
|
|
|
//slice := reflect.New(reflect.SliceOf(col.FieldType))
|
|
|
|
pkCols := col.AssociateTable.PKColumns()
|
|
|
|
if len(pkCols) != 1 {
|
|
|
|
return fmt.Errorf("unsupported primary key number")
|
|
|
|
}
|
|
|
|
mp := reflect.MakeMap(reflect.MapOf(pkCols[0].FieldType, col.FieldType))
|
|
|
|
//slice := reflect.MakeSlice(, 0, len(va.pk))
|
|
|
|
err = session.In(va.col.Name, va.pk...).find(mp.Addr().Interface())
|
2021-06-07 01:13:45 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-07-22 07:17:38 +00:00
|
|
|
|
|
|
|
/*vv, err := col.ValueOfV(&va.v)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
vv.Set()
|
|
|
|
|
|
|
|
for i := 0; i < slice.Len(); i++ {
|
|
|
|
|
|
|
|
|
|
|
|
va.col.ValueOfV(slice.Index(i))
|
|
|
|
}*/
|
2021-06-07 01:13:45 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-07-22 05:22:35 +00:00
|
|
|
// loadFindMap load 's belongs to tag field immedicatlly
|
|
|
|
func (session *Session) loadFindMap(v reflect.Value, cols ...string) error {
|
|
|
|
if v.Kind() != reflect.Map {
|
|
|
|
return errors.New("only map is supported")
|
|
|
|
}
|
|
|
|
|
|
|
|
if v.Len() <= 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
vv := v.Index(0)
|
|
|
|
if vv.Kind() == reflect.Ptr {
|
|
|
|
vv = vv.Elem()
|
|
|
|
}
|
|
|
|
tb, err := session.engine.tagParser.ParseWithCache(vv)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var pks = make(map[*schemas.Column][]interface{})
|
|
|
|
for i := 0; i < v.Len(); i++ {
|
|
|
|
ev := v.Index(i)
|
|
|
|
|
|
|
|
for _, col := range tb.Columns() {
|
|
|
|
if len(cols) > 0 && !isStringInSlice(col.Name, cols) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if col.AssociateTable != nil {
|
|
|
|
if col.AssociateType == schemas.AssociateBelongsTo {
|
|
|
|
colV, err := col.ValueOfV(&ev)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
vv := colV.Interface()
|
|
|
|
/*var colPtr reflect.Value
|
|
|
|
if colV.Kind() == reflect.Ptr {
|
|
|
|
colPtr = *colV
|
|
|
|
} else {
|
|
|
|
colPtr = colV.Addr()
|
|
|
|
}*/
|
|
|
|
|
|
|
|
if !utils.IsZero(vv) {
|
|
|
|
pks[col] = append(pks[col], vv)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for col, pk := range pks {
|
|
|
|
slice := reflect.MakeSlice(col.FieldType, 0, len(pk))
|
|
|
|
err = session.In(col.Name, pk...).find(slice.Addr().Interface())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-06-07 01:13:45 +00:00
|
|
|
// loadGet load bean's belongs to tag field immedicatlly
|
2021-07-22 05:22:35 +00:00
|
|
|
func (session *Session) loadGet(v reflect.Value, cols ...string) error {
|
2021-06-07 01:13:45 +00:00
|
|
|
if session.isAutoClose {
|
|
|
|
defer session.Close()
|
|
|
|
}
|
|
|
|
|
2021-07-22 03:25:37 +00:00
|
|
|
tb, err := session.engine.tagParser.ParseWithCache(v)
|
2021-06-07 01:13:45 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, col := range tb.Columns() {
|
|
|
|
if len(cols) > 0 && !isStringInSlice(col.Name, cols) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-07-22 05:22:35 +00:00
|
|
|
if col.AssociateTable == nil || col.AssociateType != schemas.AssociateBelongsTo {
|
|
|
|
continue
|
|
|
|
}
|
2021-06-07 01:13:45 +00:00
|
|
|
|
2021-07-22 05:22:35 +00:00
|
|
|
colV, err := col.ValueOfV(&v)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-06-07 01:13:45 +00:00
|
|
|
|
2021-07-22 05:22:35 +00:00
|
|
|
var colPtr reflect.Value
|
|
|
|
if colV.Kind() == reflect.Ptr {
|
|
|
|
colPtr = *colV
|
|
|
|
} else {
|
|
|
|
colPtr = colV.Addr()
|
|
|
|
}
|
|
|
|
|
|
|
|
pks := col.AssociateTable.PKColumns()
|
|
|
|
pkV, err := pks[0].ValueOfV(colV)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
vv := pkV.Interface()
|
|
|
|
|
|
|
|
if !utils.IsZero(vv) && session.cascadeLevel > 0 {
|
|
|
|
has, err := session.ID(vv).NoAutoCondition().get(colPtr.Interface())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if !has {
|
|
|
|
return errors.New("load bean does not exist")
|
2021-06-07 01:13:45 +00:00
|
|
|
}
|
2021-07-22 05:22:35 +00:00
|
|
|
session.cascadeLevel--
|
2021-06-07 01:13:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|