From b9ee143cc2098dde184f2cd533121b2fd58449b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B4=AA=E5=9D=A4=E5=AE=89?= Date: Mon, 3 Apr 2023 02:28:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96func=20(session=20*Session)?= =?UTF-8?q?=20slice2Bean=E6=96=B9=E6=B3=95=E4=B8=AD=E7=9A=84strings.ToLowe?= =?UTF-8?q?r=EF=BC=88=E5=AF=B9=E5=BA=94issue:https://gitea.com/xorm/xorm/i?= =?UTF-8?q?ssues/2243=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rows.go | 4 +++- session.go | 21 +++++++++------------ session_find.go | 36 +++++++++++++++++++++++++++++++++++- session_get.go | 10 ++++++---- 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/rows.go b/rows.go index 4801c300..e464b101 100644 --- a/rows.go +++ b/rows.go @@ -129,7 +129,9 @@ func (rows *Rows) Scan(beans ...interface{}) error { return err } - if err := rows.session.scan(rows.rows, rows.session.statement.RefTable, beanKind, beans, types, fields); err != nil { + allColumn := ParseQueryRows(fields, types) + + if err := rows.session.scan(rows.rows, rows.session.statement.RefTable, beanKind, beans, allColumn, types, fields); err != nil { return err } diff --git a/session.go b/session.go index cf8cbeb1..d232d30d 100644 --- a/session.go +++ b/session.go @@ -16,8 +16,6 @@ import ( "io" "reflect" "strconv" - "strings" - "xorm.io/xorm/contexts" "xorm.io/xorm/convert" "xorm.io/xorm/core" @@ -418,7 +416,7 @@ func getField(dataStruct *reflect.Value, table *schemas.Table, colName string, i // Cell cell is a result of one column field type Cell *interface{} -func (session *Session) rows2Beans(rows *core.Rows, fields []string, types []*sql.ColumnType, +func (session *Session) rows2Beans(rows *core.Rows, allColumn *AllColumn, fields []string, types []*sql.ColumnType, table *schemas.Table, newElemFunc func([]string) reflect.Value, sliceValueSetFunc func(*reflect.Value, schemas.PK) error, ) error { @@ -428,11 +426,11 @@ func (session *Session) rows2Beans(rows *core.Rows, fields []string, types []*sq dataStruct := newValue.Elem() // handle beforeClosures - scanResults, err := session.row2Slice(rows, fields, types, bean) + scanResults, err := session.row2Slice(rows, allColumn, fields, types, bean) if err != nil { return err } - pk, err := session.slice2Bean(scanResults, fields, bean, &dataStruct, table) + pk, err := session.slice2Bean(scanResults, allColumn, fields, bean, &dataStruct, table) if err != nil { return err } @@ -447,7 +445,7 @@ func (session *Session) rows2Beans(rows *core.Rows, fields []string, types []*sq return rows.Err() } -func (session *Session) row2Slice(rows *core.Rows, fields []string, types []*sql.ColumnType, bean interface{}) ([]interface{}, error) { +func (session *Session) row2Slice(rows *core.Rows, allColumn *AllColumn, fields []string, types []*sql.ColumnType, bean interface{}) ([]interface{}, error) { for _, closure := range session.beforeClosures { closure(bean) } @@ -705,7 +703,7 @@ func (session *Session) convertBeanField(col *schemas.Column, fieldValue *reflec return convert.AssignValue(fieldValue.Addr(), scanResult) } -func (session *Session) slice2Bean(scanResults []interface{}, fields []string, bean interface{}, dataStruct *reflect.Value, table *schemas.Table) (schemas.PK, error) { +func (session *Session) slice2Bean(scanResults []interface{}, allColum *AllColumn, fields []string, bean interface{}, dataStruct *reflect.Value, table *schemas.Table) (schemas.PK, error) { defer func() { executeAfterSet(bean, fields, scanResults) }() @@ -714,19 +712,18 @@ func (session *Session) slice2Bean(scanResults []interface{}, fields []string, b tempMap := make(map[string]int) var pk schemas.PK - for i, colName := range fields { + for i, field := range allColum.Fields { var idx int - lKey := strings.ToLower(colName) var ok bool - if idx, ok = tempMap[lKey]; !ok { + if idx, ok = tempMap[field.LowerFieldName]; !ok { idx = 0 } else { idx++ } - tempMap[lKey] = idx + tempMap[field.LowerFieldName] = idx - col, fieldValue, err := getField(dataStruct, table, colName, idx) + col, fieldValue, err := getField(dataStruct, table, field.FieldName, idx) if _, ok := err.(ErrFieldIsNotExist); ok { continue } else if err != nil { diff --git a/session_find.go b/session_find.go index 2270454b..483b4d71 100644 --- a/session_find.go +++ b/session_find.go @@ -5,8 +5,10 @@ package xorm import ( + "database/sql" "errors" "reflect" + "strings" "xorm.io/builder" "xorm.io/xorm/caches" @@ -161,6 +163,36 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{}) return session.noCacheFind(table, sliceValue, sqlStr, args...) } +type QueryedField struct { + FieldName string + LowerFieldName string + ColumnType *sql.ColumnType +} + +type AllColumn struct { + Fields []*QueryedField + FieldNames []string + Types []*sql.ColumnType +} + +func ParseQueryRows(fieldNames []string, types []*sql.ColumnType) *AllColumn { + var allColumn AllColumn + + fields := make([]*QueryedField, 0, len(fieldNames)) + + for i, fieldName := range fieldNames { + field := &QueryedField{ + FieldName: fieldName, + LowerFieldName: strings.ToLower(fieldName), + ColumnType: types[i], + } + fields = append(fields, field) + } + + allColumn.Fields = fields + return &allColumn +} + func (session *Session) noCacheFind(table *schemas.Table, containerValue reflect.Value, sqlStr string, args ...interface{}) error { elemType := containerValue.Type().Elem() var isPointer bool @@ -188,6 +220,8 @@ func (session *Session) noCacheFind(table *schemas.Table, containerValue reflect return err } + allColumn := ParseQueryRows(fields, types) + newElemFunc := func(fields []string) reflect.Value { return utils.New(elemType, len(fields), len(fields)) } @@ -238,7 +272,7 @@ func (session *Session) noCacheFind(table *schemas.Table, containerValue reflect if err != nil { return err } - err = session.rows2Beans(rows, fields, types, tb, newElemFunc, containerValueSetFunc) + err = session.rows2Beans(rows, allColumn, fields, types, tb, newElemFunc, containerValueSetFunc) rows.Close() if err != nil { return err diff --git a/session_get.go b/session_get.go index 9bb92a8b..cea6ce5b 100644 --- a/session_get.go +++ b/session_get.go @@ -164,7 +164,9 @@ func (session *Session) nocacheGet(beanKind reflect.Kind, table *schemas.Table, return true, err } - if err := session.scan(rows, table, beanKind, beans, types, fields); err != nil { + allColumn := ParseQueryRows(fields, types) + + if err := session.scan(rows, table, beanKind, beans, allColumn, types, fields); err != nil { return true, err } rows.Close() @@ -172,7 +174,7 @@ func (session *Session) nocacheGet(beanKind reflect.Kind, table *schemas.Table, return true, session.executeProcessors() } -func (session *Session) scan(rows *core.Rows, table *schemas.Table, firstBeanKind reflect.Kind, beans []interface{}, types []*sql.ColumnType, fields []string) error { +func (session *Session) scan(rows *core.Rows, table *schemas.Table, firstBeanKind reflect.Kind, beans []interface{}, allColumn *AllColumn, types []*sql.ColumnType, fields []string) error { if len(beans) == 1 { bean := beans[0] switch firstBeanKind { @@ -180,13 +182,13 @@ func (session *Session) scan(rows *core.Rows, table *schemas.Table, firstBeanKin if !isScannableStruct(bean, len(types)) { break } - scanResults, err := session.row2Slice(rows, fields, types, bean) + scanResults, err := session.row2Slice(rows, allColumn, fields, types, bean) if err != nil { return err } dataStruct := utils.ReflectValue(bean) - _, err = session.slice2Bean(scanResults, fields, bean, &dataStruct, table) + _, err = session.slice2Bean(scanResults, allColumn, fields, bean, &dataStruct, table) return err case reflect.Slice: return session.getSlice(rows, types, fields, bean)