improve result data type converting for package gdb

This commit is contained in:
john
2020-07-28 20:31:50 +08:00
parent 939ae37baf
commit 6d406498db
3 changed files with 24 additions and 29 deletions

View File

@ -155,7 +155,7 @@ type DB interface {
// ===========================================================================
filterFields(schema, table string, data map[string]interface{}) map[string]interface{}
convertValue(fieldValue []byte, fieldType string) interface{}
convertValue(fieldValue interface{}, fieldType string) interface{}
rowsToResult(rows *sql.Rows) (Result, error)
}

View File

@ -737,7 +737,7 @@ func (c *Core) rowsToResult(rows *sql.Rows) (Result, error) {
columnNames[k] = v.Name()
}
var (
values = make([]sql.RawBytes, len(columnNames))
values = make([]interface{}, len(columnNames))
records = make(Result, 0)
scanArgs = make([]interface{}, len(values))
)
@ -748,19 +748,12 @@ func (c *Core) rowsToResult(rows *sql.Rows) (Result, error) {
if err := rows.Scan(scanArgs...); err != nil {
return records, err
}
// Creates a new row object.
row := make(Record)
// Note that the internal looping variable <value> is type of []byte,
// which points to the same memory address. So it should do a copy.
for i, value := range values {
if value == nil {
row[columnNames[i]] = gvar.New(nil)
} else {
// As sql.RawBytes is type of slice,
// it should do a copy of it.
v := make([]byte, len(value))
copy(v, value)
row[columnNames[i]] = gvar.New(c.DB.convertValue(v, columnTypes[i]))
row[columnNames[i]] = gvar.New(c.DB.convertValue(value, columnTypes[i]))
}
}
records = append(records, row)

View File

@ -21,7 +21,9 @@ import (
// convertValue automatically checks and converts field value from database type
// to golang variable type.
func (c *Core) convertValue(fieldValue []byte, fieldType string) interface{} {
func (c *Core) convertValue(fieldValue interface{}, fieldType string) interface{} {
// If there's no type retrieved, it returns the <fieldValue> directly
// to use its original data type, as <fieldValue> is type of interface{}.
if fieldType == "" {
return fieldValue
}
@ -35,7 +37,7 @@ func (c *Core) convertValue(fieldValue []byte, fieldType string) interface{} {
"tinyblob",
"mediumblob",
"longblob":
return fieldValue
return gconv.Bytes(fieldValue)
case
"int",
@ -46,21 +48,21 @@ func (c *Core) convertValue(fieldValue []byte, fieldType string) interface{} {
"mediumint",
"serial":
if gstr.ContainsI(fieldType, "unsigned") {
gconv.Uint(string(fieldValue))
gconv.Uint(gconv.String(fieldValue))
}
return gconv.Int(string(fieldValue))
return gconv.Int(gconv.String(fieldValue))
case
"big_int",
"bigint",
"bigserial":
if gstr.ContainsI(fieldType, "unsigned") {
gconv.Uint64(string(fieldValue))
gconv.Uint64(gconv.String(fieldValue))
}
return gconv.Int64(string(fieldValue))
return gconv.Int64(gconv.String(fieldValue))
case "real":
return gconv.Float32(string(fieldValue))
return gconv.Float32(gconv.String(fieldValue))
case
"float",
@ -69,10 +71,10 @@ func (c *Core) convertValue(fieldValue []byte, fieldType string) interface{} {
"money",
"numeric",
"smallmoney":
return gconv.Float64(string(fieldValue))
return gconv.Float64(gconv.String(fieldValue))
case "bit":
s := string(fieldValue)
s := gconv.String(fieldValue)
// mssql is true|false string.
if strings.EqualFold(s, "true") {
return 1
@ -80,41 +82,41 @@ func (c *Core) convertValue(fieldValue []byte, fieldType string) interface{} {
if strings.EqualFold(s, "false") {
return 0
}
return gbinary.BeDecodeToInt64(fieldValue)
return gbinary.BeDecodeToInt64(gconv.Bytes(fieldValue))
case "bool":
return gconv.Bool(fieldValue)
case "date":
t, _ := gtime.StrToTime(string(fieldValue))
t, _ := gtime.StrToTime(gconv.String(fieldValue))
return t.Format("Y-m-d")
case
"datetime",
"timestamp":
t, _ := gtime.StrToTime(string(fieldValue))
t, _ := gtime.StrToTime(gconv.String(fieldValue))
return t.String()
default:
// Auto detect field type, using key match.
switch {
case strings.Contains(t, "text") || strings.Contains(t, "char") || strings.Contains(t, "character"):
return string(fieldValue)
return gconv.String(fieldValue)
case strings.Contains(t, "float") || strings.Contains(t, "double") || strings.Contains(t, "numeric"):
return gconv.Float64(string(fieldValue))
return gconv.Float64(gconv.String(fieldValue))
case strings.Contains(t, "bool"):
return gconv.Bool(string(fieldValue))
return gconv.Bool(gconv.String(fieldValue))
case strings.Contains(t, "binary") || strings.Contains(t, "blob"):
return fieldValue
case strings.Contains(t, "int"):
return gconv.Int(string(fieldValue))
return gconv.Int(gconv.String(fieldValue))
case strings.Contains(t, "time"):
s := string(fieldValue)
s := gconv.String(fieldValue)
t, err := gtime.StrToTime(s)
if err != nil {
return s
@ -122,7 +124,7 @@ func (c *Core) convertValue(fieldValue []byte, fieldType string) interface{} {
return t.String()
case strings.Contains(t, "date"):
s := string(fieldValue)
s := gconv.String(fieldValue)
t, err := gtime.StrToTime(s)
if err != nil {
return s
@ -130,7 +132,7 @@ func (c *Core) convertValue(fieldValue []byte, fieldType string) interface{} {
return t.Format("Y-m-d")
default:
return fieldValue
return gconv.String(fieldValue)
}
}
}