update xorm for fixing bug on processor BeforeSet and AfterSet when Find a map (#987)

This commit is contained in:
Lunny Xiao 2017-02-20 19:33:10 +08:00 committed by GitHub
parent 04fdeb9d8d
commit c5f8b96dda
7 changed files with 363 additions and 153 deletions

View file

@ -43,14 +43,12 @@ func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{})
pv := reflect.New(sliceElementType.Elem())
session.Statement.setRefValue(pv.Elem())
} else {
//return errors.New("slice type")
tp = tpNonStruct
}
} else if sliceElementType.Kind() == reflect.Struct {
pv := reflect.New(sliceElementType)
session.Statement.setRefValue(pv.Elem())
} else {
//return errors.New("slice type")
tp = tpNonStruct
}
}
@ -148,62 +146,10 @@ func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{})
}
}
if sliceValue.Kind() != reflect.Map {
return session.noCacheFind(sliceValue, sqlStr, args...)
}
resultsSlice, err := session.query(sqlStr, args...)
if err != nil {
return err
}
keyType := sliceValue.Type().Key()
for _, results := range resultsSlice {
var newValue reflect.Value
if sliceElementType.Kind() == reflect.Ptr {
newValue = reflect.New(sliceElementType.Elem())
} else {
newValue = reflect.New(sliceElementType)
}
err := session.scanMapIntoStruct(newValue.Interface(), results)
if err != nil {
return err
}
var key interface{}
// if there is only one pk, we can put the id as map key.
if len(table.PrimaryKeys) == 1 {
key, err = str2PK(string(results[table.PrimaryKeys[0]]), keyType)
if err != nil {
return err
}
} else {
if keyType.Kind() != reflect.Slice {
panic("don't support multiple primary key's map has non-slice key type")
} else {
var keys core.PK = make([]interface{}, 0, len(table.PrimaryKeys))
for _, pk := range table.PrimaryKeys {
skey, err := str2PK(string(results[pk]), keyType)
if err != nil {
return err
}
keys = append(keys, skey)
}
key = keys
}
}
if sliceElementType.Kind() == reflect.Ptr {
sliceValue.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(newValue.Interface()))
} else {
sliceValue.SetMapIndex(reflect.ValueOf(key), reflect.Indirect(reflect.ValueOf(newValue.Interface())))
}
}
return nil
return session.noCacheFind(table, sliceValue, sqlStr, args...)
}
func (session *Session) noCacheFind(sliceValue reflect.Value, sqlStr string, args ...interface{}) error {
func (session *Session) noCacheFind(table *core.Table, containerValue reflect.Value, sqlStr string, args ...interface{}) error {
var rawRows *core.Rows
var err error
@ -224,27 +170,59 @@ func (session *Session) noCacheFind(sliceValue reflect.Value, sqlStr string, arg
}
var newElemFunc func() reflect.Value
sliceElementType := sliceValue.Type().Elem()
if sliceElementType.Kind() == reflect.Ptr {
elemType := containerValue.Type().Elem()
if elemType.Kind() == reflect.Ptr {
newElemFunc = func() reflect.Value {
return reflect.New(sliceElementType.Elem())
return reflect.New(elemType.Elem())
}
} else {
newElemFunc = func() reflect.Value {
return reflect.New(sliceElementType)
return reflect.New(elemType)
}
}
var sliceValueSetFunc func(*reflect.Value)
var containerValueSetFunc func(*reflect.Value, core.PK) error
if sliceValue.Kind() == reflect.Slice {
if sliceElementType.Kind() == reflect.Ptr {
sliceValueSetFunc = func(newValue *reflect.Value) {
sliceValue.Set(reflect.Append(sliceValue, reflect.ValueOf(newValue.Interface())))
if containerValue.Kind() == reflect.Slice {
if elemType.Kind() == reflect.Ptr {
containerValueSetFunc = func(newValue *reflect.Value, pk core.PK) error {
containerValue.Set(reflect.Append(containerValue, reflect.ValueOf(newValue.Interface())))
return nil
}
} else {
sliceValueSetFunc = func(newValue *reflect.Value) {
sliceValue.Set(reflect.Append(sliceValue, reflect.Indirect(reflect.ValueOf(newValue.Interface()))))
containerValueSetFunc = func(newValue *reflect.Value, pk core.PK) error {
containerValue.Set(reflect.Append(containerValue, reflect.Indirect(reflect.ValueOf(newValue.Interface()))))
return nil
}
}
} else {
keyType := containerValue.Type().Key()
if len(table.PrimaryKeys) == 0 {
return errors.New("don't support multiple primary key's map has non-slice key type")
}
if len(table.PrimaryKeys) > 1 && keyType.Kind() != reflect.Slice {
return errors.New("don't support multiple primary key's map has non-slice key type")
}
if elemType.Kind() == reflect.Ptr {
containerValueSetFunc = func(newValue *reflect.Value, pk core.PK) error {
keyValue := reflect.New(keyType)
err := convertPKToValue(table, keyValue.Interface(), pk)
if err != nil {
return err
}
containerValue.SetMapIndex(keyValue.Elem(), reflect.ValueOf(newValue.Interface()))
return nil
}
} else {
containerValueSetFunc = func(newValue *reflect.Value, pk core.PK) error {
keyValue := reflect.New(keyType)
err := convertPKToValue(table, keyValue.Interface(), pk)
if err != nil {
return err
}
containerValue.SetMapIndex(keyValue.Elem(), reflect.Indirect(reflect.ValueOf(newValue.Interface())))
return nil
}
}
}
@ -252,7 +230,7 @@ func (session *Session) noCacheFind(sliceValue reflect.Value, sqlStr string, arg
var newValue = newElemFunc()
dataStruct := rValue(newValue.Interface())
if dataStruct.Kind() == reflect.Struct {
return session.rows2Beans(rawRows, fields, len(fields), session.Engine.autoMapType(dataStruct), newElemFunc, sliceValueSetFunc)
return session.rows2Beans(rawRows, fields, len(fields), session.Engine.autoMapType(dataStruct), newElemFunc, containerValueSetFunc)
}
for rawRows.Next() {
@ -263,11 +241,23 @@ func (session *Session) noCacheFind(sliceValue reflect.Value, sqlStr string, arg
return err
}
sliceValueSetFunc(&newValue)
if err := containerValueSetFunc(&newValue, nil); err != nil {
return err
}
}
return nil
}
func convertPKToValue(table *core.Table, dst interface{}, pk core.PK) error {
cols := table.PKColumns()
if len(cols) == 1 {
return convertAssign(dst, pk[0])
}
dst = pk
return nil
}
func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr interface{}, args ...interface{}) (err error) {
if !session.canCache() ||
indexNoCase(sqlStr, "having") != -1 ||