Expose ScanString / ScanInterface and etc #2039

Merged
lunny merged 3 commits from lunny/refactor_scan into master 2021-08-27 09:10:17 +00:00
3 changed files with 178 additions and 135 deletions
Showing only changes of commit e90cc79dac - Show all commits

214
scan.go
View File

@ -129,41 +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++ {
@ -262,19 +227,6 @@ 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 {
@ -298,6 +250,9 @@ func rows2maps(rows *core.Rows) (resultsSlice []map[string][]byte, err error) {
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))
var scanResultContainers = make([]interface{}, len(fields))
@ -321,3 +276,166 @@ 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 -> []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
}

View File

@ -4,9 +4,15 @@
package xorm
import (
"xorm.io/xorm/core"
)
func (session *Session) queryBytes(sqlStr string, args ...interface{}) ([]map[string][]byte, error) {
rows, err := session.queryRows(sqlStr, args...)
if err != nil {
return nil, err
}
defer rows.Close()
return rows2maps(rows)
}
// Query runs a raw sql and return records as []map[string][]byte
func (session *Session) Query(sqlOrArgs ...interface{}) ([]map[string][]byte, error) {
@ -22,54 +28,6 @@ func (session *Session) Query(sqlOrArgs ...interface{}) ([]map[string][]byte, er
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 {
@ -87,7 +45,7 @@ func (session *Session) QueryString(sqlOrArgs ...interface{}) ([]map[string]stri
}
defer rows.Close()
return session.rows2Strings(rows)
return session.engine.ScanStringMaps(rows)
}
// QuerySliceString runs a raw sql and return records as [][]string
@ -107,30 +65,7 @@ func (session *Session) QuerySliceString(sqlOrArgs ...interface{}) ([][]string,
}
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
return session.engine.ScanStringSlices(rows)
}
// QueryInterface runs a raw sql and return records as []map[string]interface{}
@ -150,5 +85,5 @@ func (session *Session) QueryInterface(sqlOrArgs ...interface{}) ([]map[string]i
}
defer rows.Close()
return session.rows2Interfaces(rows)
return session.engine.ScanInterfaceMaps(rows)
}

View File

@ -71,16 +71,6 @@ 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) {
rows, err := session.queryRows(sqlStr, args...)
if err != nil {
return nil, err
}
defer rows.Close()
return rows2maps(rows)
}
func (session *Session) exec(sqlStr string, args ...interface{}) (sql.Result, error) {
defer session.resetStatement()