diff --git a/convert/interface.go b/convert/interface.go new file mode 100644 index 00000000..2b055253 --- /dev/null +++ b/convert/interface.go @@ -0,0 +1,48 @@ +// Copyright 2021 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 convert + +import ( + "database/sql" + "fmt" + "time" +) + +func Interface2Interface(userLocation *time.Location, v interface{}) (interface{}, error) { + if v == nil { + return nil, nil + } + switch vv := v.(type) { + case *int64: + return *vv, nil + case *int8: + return *vv, nil + case *sql.NullString: + return vv.String, nil + case *sql.RawBytes: + if len([]byte(*vv)) > 0 { + return []byte(*vv), nil + } + return nil, nil + case *sql.NullInt32: + return vv.Int32, nil + case *sql.NullInt64: + return vv.Int64, nil + case *sql.NullFloat64: + return vv.Float64, nil + case *sql.NullBool: + if vv.Valid { + return vv.Bool, nil + } + return nil, nil + case *sql.NullTime: + if vv.Valid { + return vv.Time.In(userLocation).Format("2006-01-02 15:04:05"), nil + } + return "", nil + default: + return "", fmt.Errorf("convert assign string unsupported type: %#v", vv) + } +} diff --git a/dialects/postgres.go b/dialects/postgres.go index 9a5beddb..e4641509 100644 --- a/dialects/postgres.go +++ b/dialects/postgres.go @@ -1384,18 +1384,21 @@ func (p *pqDriver) GenScanResult(colType string) (interface{}, error) { case "BIGINT": var s sql.NullInt64 return &s, nil - case "TINYINT", "INT": + case "TINYINT", "INT", "INT8", "INT4": var s sql.NullInt32 return &s, nil - case "FLOAT": + case "FLOAT", "FLOAT4": var s sql.NullFloat64 return &s, nil - case "DATETIME": + case "DATETIME", "TIMESTAMP": var s sql.NullTime return &s, nil case "BIT": var s sql.RawBytes return &s, nil + case "BOOL": + var s sql.NullBool + return &s, nil default: fmt.Printf("unknow postgres database type: %v\n", colType) var r sql.RawBytes diff --git a/scan.go b/scan.go index d5b5698d..7104a2f1 100644 --- a/scan.go +++ b/scan.go @@ -6,8 +6,8 @@ package xorm import ( "database/sql" - "fmt" + "xorm.io/xorm/convert" "xorm.io/xorm/core" "xorm.io/xorm/dialects" ) @@ -86,30 +86,11 @@ func (engine *Engine) row2mapInterface(rows *core.Rows, types []*sql.ColumnType, } for ii, key := range fields { - switch t := scanResultContainers[ii].(type) { - case *sql.NullInt32: - resultsMap[key] = t.Int32 - case *sql.NullInt64: - resultsMap[key] = t.Int64 - case *sql.NullFloat64: - resultsMap[key] = t.Float64 - case *sql.NullString: - resultsMap[key] = t.String - case *sql.NullTime: - if t.Valid { - resultsMap[key] = t.Time.In(engine.TZLocation).Format("2006-01-02 15:04:05") - } else { - resultsMap[key] = nil - } - case *sql.RawBytes: - if t == nil { - resultsMap[key] = nil - } else { - resultsMap[key] = []byte(*t) - } - default: - return nil, fmt.Errorf("unknow type: %v", t) + res, err := convert.Interface2Interface(engine.TZLocation, scanResultContainers[ii]) + if err != nil { + return nil, err } + resultsMap[key] = res } return resultsMap, nil }