Expose ScanString / ScanInterface and etc #2039
288
scan.go
288
scan.go
@ -129,60 +129,6 @@ func genScanResultsByBean(bean interface{}) (interface{}, bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (engine *Engine) row2mapStr(rows *core.Rows, types []*sql.ColumnType, fields []string) (map[string]string, error) {
|
||||
var scanResults = make([]interface{}, len(fields))
|
||||
for i := 0; i < len(fields); i++ {
|
||||
var s sql.NullString
|
||||
scanResults[i] = &s
|
||||
}
|
||||
|
||||
if err := engine.driver.Scan(&dialects.ScanContext{
|
||||
DBLocation: engine.DatabaseTZ,
|
||||
UserLocation: engine.TZLocation,
|
||||
}, rows, types, scanResults...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[string]string, len(fields))
|
||||
for i, key := range fields {
|
||||
s := scanResults[i].(*sql.NullString)
|
||||
if s.String == "" {
|
||||
result[key] = ""
|
||||
continue
|
||||
}
|
||||
|
||||
if schemas.TIME_TYPE == engine.dialect.ColumnTypeKind(types[i].DatabaseTypeName()) {
|
||||
t, err := convert.String2Time(s.String, engine.DatabaseTZ, engine.TZLocation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[key] = t.Format("2006-01-02 15:04:05")
|
||||
} else {
|
||||
result[key] = s.String
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func row2mapBytes(rows *core.Rows, types []*sql.ColumnType, fields []string) (map[string][]byte, error) {
|
||||
var scanResults = make([]interface{}, len(fields))
|
||||
for i := 0; i < len(fields); i++ {
|
||||
var s sql.NullString
|
||||
scanResults[i] = &s
|
||||
}
|
||||
|
||||
if err := rows.Scan(scanResults...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[string][]byte, len(fields))
|
||||
for ii, key := range fields {
|
||||
s := scanResults[ii].(*sql.NullString)
|
||||
result[key] = []byte(s.String)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (engine *Engine) scanStringInterface(rows *core.Rows, fields []string, types []*sql.ColumnType) ([]interface{}, error) {
|
||||
var scanResults = make([]interface{}, len(types))
|
||||
for i := 0; i < len(types); i++ {
|
||||
@ -262,41 +208,8 @@ func (engine *Engine) scanInterfaces(rows *core.Rows, fields []string, types []*
|
||||
return scanResultContainers, nil
|
||||
}
|
||||
|
||||
func (engine *Engine) row2sliceStr(rows *core.Rows, types []*sql.ColumnType, fields []string) ([]string, error) {
|
||||
scanResults, err := engine.scanStringInterface(rows, fields, types)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var results = make([]string, 0, len(fields))
|
||||
for i := 0; i < len(fields); i++ {
|
||||
results = append(results, scanResults[i].(*sql.NullString).String)
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func rows2maps(rows *core.Rows) (resultsSlice []map[string][]byte, err error) {
|
||||
fields, err := rows.Columns()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
types, err := rows.ColumnTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
result, err := row2mapBytes(rows, types, fields)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resultsSlice = append(resultsSlice, result)
|
||||
}
|
||||
if rows.Err() != nil {
|
||||
return nil, rows.Err()
|
||||
}
|
||||
|
||||
return resultsSlice, nil
|
||||
}
|
||||
////////////////////
|
||||
// row -> map[string]interface{}
|
||||
|
||||
func (engine *Engine) row2mapInterface(rows *core.Rows, types []*sql.ColumnType, fields []string) (map[string]interface{}, error) {
|
||||
var resultsMap = make(map[string]interface{}, len(fields))
|
||||
@ -321,3 +234,200 @@ func (engine *Engine) row2mapInterface(rows *core.Rows, types []*sql.ColumnType,
|
||||
}
|
||||
return resultsMap, nil
|
||||
}
|
||||
|
||||
func (engine *Engine) ScanInterfaceMap(rows *core.Rows) (map[string]interface{}, error) {
|
||||
fields, err := rows.Columns()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
types, err := rows.ColumnTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return engine.row2mapInterface(rows, types, fields)
|
||||
}
|
||||
|
||||
func (engine *Engine) ScanInterfaceMaps(rows *core.Rows) (resultsSlice []map[string]interface{}, err error) {
|
||||
fields, err := rows.Columns()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
types, err := rows.ColumnTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
result, err := engine.row2mapInterface(rows, types, fields)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resultsSlice = append(resultsSlice, result)
|
||||
}
|
||||
if rows.Err() != nil {
|
||||
return nil, rows.Err()
|
||||
}
|
||||
|
||||
return resultsSlice, nil
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// row -> map[string]string
|
||||
|
||||
func (engine *Engine) row2mapStr(rows *core.Rows, types []*sql.ColumnType, fields []string) (map[string]string, error) {
|
||||
var scanResults = make([]interface{}, len(fields))
|
||||
for i := 0; i < len(fields); i++ {
|
||||
var s sql.NullString
|
||||
scanResults[i] = &s
|
||||
}
|
||||
|
||||
if err := engine.driver.Scan(&dialects.ScanContext{
|
||||
DBLocation: engine.DatabaseTZ,
|
||||
UserLocation: engine.TZLocation,
|
||||
}, rows, types, scanResults...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[string]string, len(fields))
|
||||
for i, key := range fields {
|
||||
s := scanResults[i].(*sql.NullString)
|
||||
if s.String == "" {
|
||||
result[key] = ""
|
||||
continue
|
||||
}
|
||||
|
||||
if schemas.TIME_TYPE == engine.dialect.ColumnTypeKind(types[i].DatabaseTypeName()) {
|
||||
t, err := convert.String2Time(s.String, engine.DatabaseTZ, engine.TZLocation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[key] = t.Format("2006-01-02 15:04:05")
|
||||
} else {
|
||||
result[key] = s.String
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (engine *Engine) ScanStringMap(rows *core.Rows) (map[string]string, error) {
|
||||
fields, err := rows.Columns()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
types, err := rows.ColumnTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return engine.row2mapStr(rows, types, fields)
|
||||
}
|
||||
|
||||
func (engine *Engine) ScanStringMaps(rows *core.Rows) (resultsSlice []map[string]string, err error) {
|
||||
fields, err := rows.Columns()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
types, err := rows.ColumnTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for rows.Next() {
|
||||
result, err := engine.row2mapStr(rows, types, fields)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resultsSlice = append(resultsSlice, result)
|
||||
}
|
||||
if rows.Err() != nil {
|
||||
return nil, rows.Err()
|
||||
}
|
||||
|
||||
return resultsSlice, nil
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// row -> map[string][]byte
|
||||
|
||||
func convertMapStr2Bytes(m map[string]string) map[string][]byte {
|
||||
var r = make(map[string][]byte, len(m))
|
||||
for k, v := range m {
|
||||
r[k] = []byte(v)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (engine *Engine) scanByteMaps(rows *core.Rows) (resultsSlice []map[string][]byte, err error) {
|
||||
fields, err := rows.Columns()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
types, err := rows.ColumnTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
result, err := engine.row2mapStr(rows, types, fields)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resultsSlice = append(resultsSlice, convertMapStr2Bytes(result))
|
||||
}
|
||||
if rows.Err() != nil {
|
||||
return nil, rows.Err()
|
||||
}
|
||||
|
||||
return resultsSlice, nil
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// row -> []string
|
||||
|
||||
func (engine *Engine) row2sliceStr(rows *core.Rows, types []*sql.ColumnType, fields []string) ([]string, error) {
|
||||
scanResults, err := engine.scanStringInterface(rows, fields, types)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var results = make([]string, 0, len(fields))
|
||||
for i := 0; i < len(fields); i++ {
|
||||
results = append(results, scanResults[i].(*sql.NullString).String)
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (engine *Engine) ScanStringSlice(rows *core.Rows) ([]string, error) {
|
||||
fields, err := rows.Columns()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
types, err := rows.ColumnTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return engine.row2sliceStr(rows, types, fields)
|
||||
}
|
||||
|
||||
func (engine *Engine) ScanStringSlices(rows *core.Rows) (resultsSlice [][]string, err error) {
|
||||
fields, err := rows.Columns()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
types, err := rows.ColumnTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for rows.Next() {
|
||||
record, err := engine.row2sliceStr(rows, types, fields)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resultsSlice = append(resultsSlice, record)
|
||||
}
|
||||
if rows.Err() != nil {
|
||||
return nil, rows.Err()
|
||||
}
|
||||
|
||||
return resultsSlice, nil
|
||||
}
|
||||
|
17
session.go
17
session.go
@ -123,9 +123,9 @@ func newSession(engine *Engine) *Session {
|
||||
autoResetStatement: true,
|
||||
prepareStmt: false,
|
||||
|
||||
afterInsertBeans: make(map[interface{}]*[]func(interface{}), 0),
|
||||
afterUpdateBeans: make(map[interface{}]*[]func(interface{}), 0),
|
||||
afterDeleteBeans: make(map[interface{}]*[]func(interface{}), 0),
|
||||
afterInsertBeans: make(map[interface{}]*[]func(interface{})),
|
||||
afterUpdateBeans: make(map[interface{}]*[]func(interface{})),
|
||||
afterDeleteBeans: make(map[interface{}]*[]func(interface{})),
|
||||
beforeClosures: make([]func(interface{}), 0),
|
||||
afterClosures: make([]func(interface{}), 0),
|
||||
afterProcessors: make([]executedProcessor, 0),
|
||||
@ -684,13 +684,12 @@ func (session *Session) slice2Bean(scanResults []interface{}, fields []string, b
|
||||
tempMap[lKey] = idx
|
||||
|
||||
col, fieldValue, err := session.getField(dataStruct, table, colName, idx)
|
||||
if err != nil {
|
||||
if _, ok := err.(ErrFieldIsNotExist); ok {
|
||||
continue
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := err.(ErrFieldIsNotExist); ok {
|
||||
continue
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if fieldValue == nil {
|
||||
continue
|
||||
}
|
||||
|
@ -40,7 +40,13 @@ func (session *Session) cacheDelete(table *schemas.Table, tableName, sqlStr stri
|
||||
pkColumns := table.PKColumns()
|
||||
ids, err := caches.GetCacheSql(cacher, tableName, newsql, args)
|
||||
if err != nil {
|
||||
resultsSlice, err := session.queryBytes(newsql, args...)
|
||||
rows, err := session.queryRows(newsql, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
resultsSlice, err := session.engine.ScanStringMaps(rows)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -53,9 +59,9 @@ func (session *Session) cacheDelete(table *schemas.Table, tableName, sqlStr stri
|
||||
if v, ok := data[col.Name]; !ok {
|
||||
return errors.New("no id")
|
||||
} else if col.SQLType.IsText() {
|
||||
pk = append(pk, string(v))
|
||||
pk = append(pk, v)
|
||||
} else if col.SQLType.IsNumeric() {
|
||||
id, err = strconv.ParseInt(string(v), 10, 64)
|
||||
id, err = strconv.ParseInt(v, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
154
session_query.go
154
session_query.go
@ -1,154 +0,0 @@
|
||||
// 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 (
|
||||
"xorm.io/xorm/core"
|
||||
)
|
||||
|
||||
// Query runs a raw sql and return records as []map[string][]byte
|
||||
func (session *Session) Query(sqlOrArgs ...interface{}) ([]map[string][]byte, error) {
|
||||
if session.isAutoClose {
|
||||
defer session.Close()
|
||||
}
|
||||
|
||||
sqlStr, args, err := session.statement.GenQuerySQL(sqlOrArgs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return session.queryBytes(sqlStr, args...)
|
||||
}
|
||||
|
||||
func (session *Session) rows2Strings(rows *core.Rows) (resultsSlice []map[string]string, err error) {
|
||||
fields, err := rows.Columns()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
types, err := rows.ColumnTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for rows.Next() {
|
||||
result, err := session.engine.row2mapStr(rows, types, fields)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resultsSlice = append(resultsSlice, result)
|
||||
}
|
||||
if rows.Err() != nil {
|
||||
return nil, rows.Err()
|
||||
}
|
||||
|
||||
return resultsSlice, nil
|
||||
}
|
||||
|
||||
func (session *Session) rows2SliceString(rows *core.Rows) (resultsSlice [][]string, err error) {
|
||||
fields, err := rows.Columns()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
types, err := rows.ColumnTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for rows.Next() {
|
||||
record, err := session.engine.row2sliceStr(rows, types, fields)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resultsSlice = append(resultsSlice, record)
|
||||
}
|
||||
if rows.Err() != nil {
|
||||
return nil, rows.Err()
|
||||
}
|
||||
|
||||
return resultsSlice, nil
|
||||
}
|
||||
|
||||
// QueryString runs a raw sql and return records as []map[string]string
|
||||
func (session *Session) QueryString(sqlOrArgs ...interface{}) ([]map[string]string, error) {
|
||||
if session.isAutoClose {
|
||||
defer session.Close()
|
||||
}
|
||||
|
||||
sqlStr, args, err := session.statement.GenQuerySQL(sqlOrArgs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := session.queryRows(sqlStr, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
return session.rows2Strings(rows)
|
||||
}
|
||||
|
||||
// QuerySliceString runs a raw sql and return records as [][]string
|
||||
func (session *Session) QuerySliceString(sqlOrArgs ...interface{}) ([][]string, error) {
|
||||
if session.isAutoClose {
|
||||
defer session.Close()
|
||||
}
|
||||
|
||||
sqlStr, args, err := session.statement.GenQuerySQL(sqlOrArgs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := session.queryRows(sqlStr, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
return session.rows2SliceString(rows)
|
||||
}
|
||||
|
||||
func (session *Session) rows2Interfaces(rows *core.Rows) (resultsSlice []map[string]interface{}, err error) {
|
||||
fields, err := rows.Columns()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
types, err := rows.ColumnTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for rows.Next() {
|
||||
result, err := session.engine.row2mapInterface(rows, types, fields)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resultsSlice = append(resultsSlice, result)
|
||||
}
|
||||
if rows.Err() != nil {
|
||||
return nil, rows.Err()
|
||||
}
|
||||
|
||||
return resultsSlice, nil
|
||||
}
|
||||
|
||||
// QueryInterface runs a raw sql and return records as []map[string]interface{}
|
||||
func (session *Session) QueryInterface(sqlOrArgs ...interface{}) ([]map[string]interface{}, error) {
|
||||
if session.isAutoClose {
|
||||
defer session.Close()
|
||||
}
|
||||
|
||||
sqlStr, args, err := session.statement.GenQuerySQL(sqlOrArgs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := session.queryRows(sqlStr, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
return session.rows2Interfaces(rows)
|
||||
}
|
@ -71,14 +71,84 @@ func (session *Session) queryRow(sqlStr string, args ...interface{}) *core.Row {
|
||||
return core.NewRow(session.queryRows(sqlStr, args...))
|
||||
}
|
||||
|
||||
func (session *Session) queryBytes(sqlStr string, args ...interface{}) ([]map[string][]byte, error) {
|
||||
// Query runs a raw sql and return records as []map[string][]byte
|
||||
func (session *Session) Query(sqlOrArgs ...interface{}) ([]map[string][]byte, error) {
|
||||
if session.isAutoClose {
|
||||
defer session.Close()
|
||||
}
|
||||
|
||||
sqlStr, args, err := session.statement.GenQuerySQL(sqlOrArgs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := session.queryRows(sqlStr, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
return rows2maps(rows)
|
||||
return session.engine.scanByteMaps(rows)
|
||||
}
|
||||
|
||||
// QueryString runs a raw sql and return records as []map[string]string
|
||||
func (session *Session) QueryString(sqlOrArgs ...interface{}) ([]map[string]string, error) {
|
||||
if session.isAutoClose {
|
||||
defer session.Close()
|
||||
}
|
||||
|
||||
sqlStr, args, err := session.statement.GenQuerySQL(sqlOrArgs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := session.queryRows(sqlStr, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
return session.engine.ScanStringMaps(rows)
|
||||
}
|
||||
|
||||
// QuerySliceString runs a raw sql and return records as [][]string
|
||||
func (session *Session) QuerySliceString(sqlOrArgs ...interface{}) ([][]string, error) {
|
||||
if session.isAutoClose {
|
||||
defer session.Close()
|
||||
}
|
||||
|
||||
sqlStr, args, err := session.statement.GenQuerySQL(sqlOrArgs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := session.queryRows(sqlStr, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
return session.engine.ScanStringSlices(rows)
|
||||
}
|
||||
|
||||
// QueryInterface runs a raw sql and return records as []map[string]interface{}
|
||||
func (session *Session) QueryInterface(sqlOrArgs ...interface{}) ([]map[string]interface{}, error) {
|
||||
if session.isAutoClose {
|
||||
defer session.Close()
|
||||
}
|
||||
|
||||
sqlStr, args, err := session.statement.GenQuerySQL(sqlOrArgs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := session.queryRows(sqlStr, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
return session.engine.ScanInterfaceMaps(rows)
|
||||
}
|
||||
|
||||
func (session *Session) exec(sqlStr string, args ...interface{}) (sql.Result, error) {
|
||||
|
@ -70,12 +70,12 @@ func (session *Session) SumInt(bean interface{}, columnName string) (res int64,
|
||||
|
||||
// Sums call sum some columns. bean's non-empty fields are conditions.
|
||||
func (session *Session) Sums(bean interface{}, columnNames ...string) ([]float64, error) {
|
||||
var res = make([]float64, len(columnNames), len(columnNames))
|
||||
var res = make([]float64, len(columnNames))
|
||||
return res, session.sum(&res, bean, columnNames...)
|
||||
}
|
||||
|
||||
// SumsInt sum specify columns and return as []int64 instead of []float64
|
||||
func (session *Session) SumsInt(bean interface{}, columnNames ...string) ([]int64, error) {
|
||||
var res = make([]int64, len(columnNames), len(columnNames))
|
||||
var res = make([]int64, len(columnNames))
|
||||
return res, session.sum(&res, bean, columnNames...)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user