Fix test
This commit is contained in:
parent
dca8a72b64
commit
b882579026
54
session.go
54
session.go
|
@ -10,7 +10,6 @@ import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash/crc32"
|
"hash/crc32"
|
||||||
"io"
|
"io"
|
||||||
|
@ -631,9 +630,7 @@ func (session *Session) convertBeanField(col *schemas.Column, fieldValue *reflec
|
||||||
}
|
}
|
||||||
fieldValue.Set(reflect.ValueOf(v).Elem().Convert(fieldType))
|
fieldValue.Set(reflect.ValueOf(v).Elem().Convert(fieldType))
|
||||||
return nil
|
return nil
|
||||||
}
|
} else if fieldType.ConvertibleTo(schemas.TimeType) {
|
||||||
|
|
||||||
if fieldType.ConvertibleTo(schemas.TimeType) {
|
|
||||||
dbTZ := session.engine.DatabaseTZ
|
dbTZ := session.engine.DatabaseTZ
|
||||||
if col.TimeZone != nil {
|
if col.TimeZone != nil {
|
||||||
dbTZ = col.TimeZone
|
dbTZ = col.TimeZone
|
||||||
|
@ -647,42 +644,35 @@ func (session *Session) convertBeanField(col *schemas.Column, fieldValue *reflec
|
||||||
fieldValue.Set(reflect.ValueOf(*t).Convert(fieldType))
|
fieldValue.Set(reflect.ValueOf(*t).Convert(fieldType))
|
||||||
return nil
|
return nil
|
||||||
} else if nulVal, ok := fieldValue.Addr().Interface().(sql.Scanner); ok {
|
} else if nulVal, ok := fieldValue.Addr().Interface().(sql.Scanner); ok {
|
||||||
err := nulVal.Scan(scanResult)
|
return nulVal.Scan(scanResult)
|
||||||
if err == nil {
|
} else if session.cascadeLevel > 0 && ((col.AssociateType == schemas.AssociateNone &&
|
||||||
return nil
|
session.cascadeMode == cascadeCompitable) ||
|
||||||
}
|
(col.AssociateType == schemas.AssociateBelongsTo &&
|
||||||
session.engine.logger.Errorf("sql.Sanner error: %v", err)
|
session.cascadeMode == cascadeEager)) {
|
||||||
} else if session.statement.UseCascade {
|
var pk = make(schemas.PK, len(col.AssociateTable.PrimaryKeys))
|
||||||
table, err := session.engine.tagParser.ParseWithCache(*fieldValue)
|
var err error
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(table.PrimaryKeys) != 1 {
|
|
||||||
return errors.New("unsupported non or composited primary key cascade")
|
|
||||||
}
|
|
||||||
var pk = make(schemas.PK, len(table.PrimaryKeys))
|
|
||||||
pk[0], err = asKind(vv, reflect.TypeOf(scanResult))
|
pk[0], err = asKind(vv, reflect.TypeOf(scanResult))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !pk.IsZero() {
|
session.afterProcessors = append(session.afterProcessors, executedProcessor{
|
||||||
// !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
|
fun: func(session *Session, bean interface{}) error {
|
||||||
// however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
|
fieldValue := bean.(*reflect.Value)
|
||||||
// property to be fetched lazily
|
return session.getStructByPK(pk, fieldValue)
|
||||||
structInter := reflect.New(fieldValue.Type())
|
},
|
||||||
has, err := session.ID(pk).NoCascade().get(structInter.Interface())
|
session: session,
|
||||||
|
bean: fieldValue,
|
||||||
|
})
|
||||||
|
session.cascadeLevel--
|
||||||
|
return nil
|
||||||
|
} else if col.AssociateType == schemas.AssociateBelongsTo {
|
||||||
|
pkCols := col.AssociateTable.PKColumns()
|
||||||
|
colV, err := pkCols[0].ValueOfV(fieldValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if has {
|
return convertAssignV(*colV, scanResult)
|
||||||
fieldValue.Set(structInter.Elem())
|
|
||||||
} else {
|
|
||||||
return errors.New("cascade obj is not exist")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
} // switch fieldType.Kind()
|
} // switch fieldType.Kind()
|
||||||
|
|
||||||
|
|
|
@ -19,11 +19,13 @@ func (session *Session) Load(beanOrSlices interface{}, cols ...string) error {
|
||||||
v = v.Elem()
|
v = v.Elem()
|
||||||
}
|
}
|
||||||
if v.Kind() == reflect.Slice {
|
if v.Kind() == reflect.Slice {
|
||||||
return session.loadFind(beanOrSlices, cols...)
|
return session.loadFindSlice(v, cols...)
|
||||||
|
} else if v.Kind() == reflect.Map {
|
||||||
|
return session.loadFindMap(v, cols...)
|
||||||
} else if v.Kind() == reflect.Struct {
|
} else if v.Kind() == reflect.Struct {
|
||||||
return session.loadGet(beanOrSlices, cols...)
|
return session.loadGet(v, cols...)
|
||||||
}
|
}
|
||||||
return errors.New("unsupported load type, must struct or slice")
|
return errors.New("unsupported load type, must struct, slice or map")
|
||||||
}
|
}
|
||||||
|
|
||||||
func isStringInSlice(s string, slice []string) bool {
|
func isStringInSlice(s string, slice []string) bool {
|
||||||
|
@ -36,11 +38,7 @@ func isStringInSlice(s string, slice []string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadFind load 's belongs to tag field immedicatlly
|
// loadFind load 's belongs to tag field immedicatlly
|
||||||
func (session *Session) loadFind(slices interface{}, cols ...string) error {
|
func (session *Session) loadFindSlice(v reflect.Value, cols ...string) error {
|
||||||
v := reflect.ValueOf(slices)
|
|
||||||
if v.Kind() == reflect.Ptr {
|
|
||||||
v = v.Elem()
|
|
||||||
}
|
|
||||||
if v.Kind() != reflect.Slice {
|
if v.Kind() != reflect.Slice {
|
||||||
return errors.New("only slice is supported")
|
return errors.New("only slice is supported")
|
||||||
}
|
}
|
||||||
|
@ -100,13 +98,73 @@ func (session *Session) loadFind(slices interface{}, cols ...string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
// loadGet load bean's belongs to tag field immedicatlly
|
// loadGet load bean's belongs to tag field immedicatlly
|
||||||
func (session *Session) loadGet(bean interface{}, cols ...string) error {
|
func (session *Session) loadGet(v reflect.Value, cols ...string) error {
|
||||||
if session.isAutoClose {
|
if session.isAutoClose {
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
v := reflect.Indirect(reflect.ValueOf(bean))
|
|
||||||
tb, err := session.engine.tagParser.ParseWithCache(v)
|
tb, err := session.engine.tagParser.ParseWithCache(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -117,14 +175,15 @@ func (session *Session) loadGet(bean interface{}, cols ...string) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if col.AssociateTable != nil {
|
if col.AssociateTable == nil || col.AssociateType != schemas.AssociateBelongsTo {
|
||||||
if col.AssociateType == schemas.AssociateBelongsTo {
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
colV, err := col.ValueOfV(&v)
|
colV, err := col.ValueOfV(&v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
vv := colV.Interface()
|
|
||||||
var colPtr reflect.Value
|
var colPtr reflect.Value
|
||||||
if colV.Kind() == reflect.Ptr {
|
if colV.Kind() == reflect.Ptr {
|
||||||
colPtr = *colV
|
colPtr = *colV
|
||||||
|
@ -132,6 +191,13 @@ func (session *Session) loadGet(bean interface{}, cols ...string) error {
|
||||||
colPtr = colV.Addr()
|
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 {
|
if !utils.IsZero(vv) && session.cascadeLevel > 0 {
|
||||||
has, err := session.ID(vv).NoAutoCondition().get(colPtr.Interface())
|
has, err := session.ID(vv).NoAutoCondition().get(colPtr.Interface())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -143,7 +209,5 @@ func (session *Session) loadGet(bean interface{}, cols ...string) error {
|
||||||
session.cascadeLevel--
|
session.cascadeLevel--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,6 +280,42 @@ func (session *Session) getMap(rows *core.Rows, types []*sql.ColumnType, fields
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (session *Session) getStructByPK(pk schemas.PK, fieldValue *reflect.Value) error {
|
||||||
|
if pk.IsZero() {
|
||||||
|
return errors.New("getStructByPK: primary key is zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
var structInter reflect.Value
|
||||||
|
if fieldValue.Kind() == reflect.Ptr {
|
||||||
|
if fieldValue.IsNil() {
|
||||||
|
structInter = reflect.New(fieldValue.Type().Elem())
|
||||||
|
} else {
|
||||||
|
structInter = *fieldValue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
structInter = fieldValue.Addr()
|
||||||
|
}
|
||||||
|
|
||||||
|
has, err := session.ID(pk).NoAutoCondition().get(structInter.Interface())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !has {
|
||||||
|
return errors.New("cascade obj is not exist")
|
||||||
|
}
|
||||||
|
if fieldValue.Kind() == reflect.Ptr && fieldValue.IsNil() {
|
||||||
|
fieldValue.Set(structInter)
|
||||||
|
fmt.Println("getByPK value ptr:", fieldValue.Interface())
|
||||||
|
return nil
|
||||||
|
} else if fieldValue.Kind() == reflect.Struct {
|
||||||
|
fieldValue.Set(structInter.Elem())
|
||||||
|
fmt.Println("getByPK value:", fieldValue.Interface())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New("set value failed")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (session *Session) cacheGet(bean interface{}, sqlStr string, args ...interface{}) (has bool, err error) {
|
func (session *Session) cacheGet(bean interface{}, sqlStr string, args ...interface{}) (has bool, err error) {
|
||||||
// if has no reftable, then don't use cache currently
|
// if has no reftable, then don't use cache currently
|
||||||
if !session.canCache() {
|
if !session.canCache() {
|
||||||
|
|
Loading…
Reference in New Issue