refactor conversion #2001
2
Makefile
2
Makefile
|
@ -6,7 +6,7 @@ GOFMT ?= gofmt -s
|
|||
TAGS ?=
|
||||
SED_INPLACE := sed -i
|
||||
|
||||
GO_DIRS := caches contexts integrations convert core dialects internal log migrate names schemas tags
|
||||
GO_DIRS := caches contexts integrations core dialects internal log migrate names schemas tags
|
||||
GOFILES := $(wildcard *.go)
|
||||
GOFILES += $(shell find $(GO_DIRS) -name "*.go" -type f)
|
||||
INTEGRATION_PACKAGES := xorm.io/xorm/integrations
|
||||
|
|
561
convert.go
561
convert.go
|
@ -15,7 +15,7 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
"xorm.io/xorm/convert"
|
||||
"xorm.io/xorm/internal/convert"
|
||||
)
|
||||
|
||||
var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error
|
||||
|
@ -36,347 +36,6 @@ func cloneBytes(b []byte) []byte {
|
|||
return c
|
||||
}
|
||||
|
||||
func asString(src interface{}) string {
|
||||
switch v := src.(type) {
|
||||
case string:
|
||||
return v
|
||||
case []byte:
|
||||
return string(v)
|
||||
case *sql.NullString:
|
||||
return v.String
|
||||
case *sql.NullInt32:
|
||||
return fmt.Sprintf("%d", v.Int32)
|
||||
case *sql.NullInt64:
|
||||
return fmt.Sprintf("%d", v.Int64)
|
||||
}
|
||||
rv := reflect.ValueOf(src)
|
||||
switch rv.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return strconv.FormatInt(rv.Int(), 10)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return strconv.FormatUint(rv.Uint(), 10)
|
||||
case reflect.Float64:
|
||||
return strconv.FormatFloat(rv.Float(), 'g', -1, 64)
|
||||
case reflect.Float32:
|
||||
return strconv.FormatFloat(rv.Float(), 'g', -1, 32)
|
||||
case reflect.Bool:
|
||||
return strconv.FormatBool(rv.Bool())
|
||||
}
|
||||
return fmt.Sprintf("%v", src)
|
||||
}
|
||||
|
||||
func asInt64(src interface{}) (int64, error) {
|
||||
switch v := src.(type) {
|
||||
case int:
|
||||
return int64(v), nil
|
||||
case int16:
|
||||
return int64(v), nil
|
||||
case int32:
|
||||
return int64(v), nil
|
||||
case int8:
|
||||
return int64(v), nil
|
||||
case int64:
|
||||
return v, nil
|
||||
case uint:
|
||||
return int64(v), nil
|
||||
case uint8:
|
||||
return int64(v), nil
|
||||
case uint16:
|
||||
return int64(v), nil
|
||||
case uint32:
|
||||
return int64(v), nil
|
||||
case uint64:
|
||||
return int64(v), nil
|
||||
case []byte:
|
||||
return strconv.ParseInt(string(v), 10, 64)
|
||||
case string:
|
||||
return strconv.ParseInt(v, 10, 64)
|
||||
case *sql.NullString:
|
||||
return strconv.ParseInt(v.String, 10, 64)
|
||||
case *sql.NullInt32:
|
||||
return int64(v.Int32), nil
|
||||
case *sql.NullInt64:
|
||||
return int64(v.Int64), nil
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(src)
|
||||
switch rv.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return rv.Int(), nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return int64(rv.Uint()), nil
|
||||
case reflect.Float64, reflect.Float32:
|
||||
return int64(rv.Float()), nil
|
||||
case reflect.String:
|
||||
return strconv.ParseInt(rv.String(), 10, 64)
|
||||
}
|
||||
return 0, fmt.Errorf("unsupported value %T as int64", src)
|
||||
}
|
||||
|
||||
func asUint64(src interface{}) (uint64, error) {
|
||||
switch v := src.(type) {
|
||||
case int:
|
||||
return uint64(v), nil
|
||||
case int16:
|
||||
return uint64(v), nil
|
||||
case int32:
|
||||
return uint64(v), nil
|
||||
case int8:
|
||||
return uint64(v), nil
|
||||
case int64:
|
||||
return uint64(v), nil
|
||||
case uint:
|
||||
return uint64(v), nil
|
||||
case uint8:
|
||||
return uint64(v), nil
|
||||
case uint16:
|
||||
return uint64(v), nil
|
||||
case uint32:
|
||||
return uint64(v), nil
|
||||
case uint64:
|
||||
return v, nil
|
||||
case []byte:
|
||||
return strconv.ParseUint(string(v), 10, 64)
|
||||
case string:
|
||||
return strconv.ParseUint(v, 10, 64)
|
||||
case *sql.NullString:
|
||||
return strconv.ParseUint(v.String, 10, 64)
|
||||
case *sql.NullInt32:
|
||||
return uint64(v.Int32), nil
|
||||
case *sql.NullInt64:
|
||||
return uint64(v.Int64), nil
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(src)
|
||||
switch rv.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return uint64(rv.Int()), nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return uint64(rv.Uint()), nil
|
||||
case reflect.Float64, reflect.Float32:
|
||||
return uint64(rv.Float()), nil
|
||||
case reflect.String:
|
||||
return strconv.ParseUint(rv.String(), 10, 64)
|
||||
}
|
||||
return 0, fmt.Errorf("unsupported value %T as uint64", src)
|
||||
}
|
||||
|
||||
func asFloat64(src interface{}) (float64, error) {
|
||||
switch v := src.(type) {
|
||||
case int:
|
||||
return float64(v), nil
|
||||
case int16:
|
||||
return float64(v), nil
|
||||
case int32:
|
||||
return float64(v), nil
|
||||
case int8:
|
||||
return float64(v), nil
|
||||
case int64:
|
||||
return float64(v), nil
|
||||
case uint:
|
||||
return float64(v), nil
|
||||
case uint8:
|
||||
return float64(v), nil
|
||||
case uint16:
|
||||
return float64(v), nil
|
||||
case uint32:
|
||||
return float64(v), nil
|
||||
case uint64:
|
||||
return float64(v), nil
|
||||
case []byte:
|
||||
return strconv.ParseFloat(string(v), 64)
|
||||
case string:
|
||||
return strconv.ParseFloat(v, 64)
|
||||
case *sql.NullString:
|
||||
return strconv.ParseFloat(v.String, 64)
|
||||
case *sql.NullInt32:
|
||||
return float64(v.Int32), nil
|
||||
case *sql.NullInt64:
|
||||
return float64(v.Int64), nil
|
||||
case *sql.NullFloat64:
|
||||
return v.Float64, nil
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(src)
|
||||
switch rv.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return float64(rv.Int()), nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return float64(rv.Uint()), nil
|
||||
case reflect.Float64, reflect.Float32:
|
||||
return float64(rv.Float()), nil
|
||||
case reflect.String:
|
||||
return strconv.ParseFloat(rv.String(), 64)
|
||||
}
|
||||
return 0, fmt.Errorf("unsupported value %T as int64", src)
|
||||
}
|
||||
|
||||
func asBigFloat(src interface{}) (*big.Float, error) {
|
||||
res := big.NewFloat(0)
|
||||
switch v := src.(type) {
|
||||
case int:
|
||||
res.SetInt64(int64(v))
|
||||
return res, nil
|
||||
case int16:
|
||||
res.SetInt64(int64(v))
|
||||
return res, nil
|
||||
case int32:
|
||||
res.SetInt64(int64(v))
|
||||
return res, nil
|
||||
case int8:
|
||||
res.SetInt64(int64(v))
|
||||
return res, nil
|
||||
case int64:
|
||||
res.SetInt64(int64(v))
|
||||
return res, nil
|
||||
case uint:
|
||||
res.SetUint64(uint64(v))
|
||||
return res, nil
|
||||
case uint8:
|
||||
res.SetUint64(uint64(v))
|
||||
return res, nil
|
||||
case uint16:
|
||||
res.SetUint64(uint64(v))
|
||||
return res, nil
|
||||
case uint32:
|
||||
res.SetUint64(uint64(v))
|
||||
return res, nil
|
||||
case uint64:
|
||||
res.SetUint64(uint64(v))
|
||||
return res, nil
|
||||
case []byte:
|
||||
res.SetString(string(v))
|
||||
return res, nil
|
||||
case string:
|
||||
res.SetString(v)
|
||||
return res, nil
|
||||
case *sql.NullString:
|
||||
if v.Valid {
|
||||
res.SetString(v.String)
|
||||
return res, nil
|
||||
}
|
||||
return nil, nil
|
||||
case *sql.NullInt32:
|
||||
if v.Valid {
|
||||
res.SetInt64(int64(v.Int32))
|
||||
return res, nil
|
||||
}
|
||||
return nil, nil
|
||||
case *sql.NullInt64:
|
||||
if v.Valid {
|
||||
res.SetInt64(int64(v.Int64))
|
||||
return res, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(src)
|
||||
switch rv.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
res.SetInt64(rv.Int())
|
||||
return res, nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
res.SetUint64(rv.Uint())
|
||||
return res, nil
|
||||
case reflect.Float64, reflect.Float32:
|
||||
res.SetFloat64(rv.Float())
|
||||
return res, nil
|
||||
case reflect.String:
|
||||
res.SetString(rv.String())
|
||||
return res, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported value %T as big.Float", src)
|
||||
}
|
||||
|
||||
func asBytes(src interface{}) ([]byte, bool) {
|
||||
switch t := src.(type) {
|
||||
case []byte:
|
||||
return t, true
|
||||
case *sql.NullString:
|
||||
if !t.Valid {
|
||||
return nil, true
|
||||
}
|
||||
return []byte(t.String), true
|
||||
case *sql.RawBytes:
|
||||
return *t, true
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(src)
|
||||
|
||||
switch rv.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return strconv.AppendInt(nil, rv.Int(), 10), true
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return strconv.AppendUint(nil, rv.Uint(), 10), true
|
||||
case reflect.Float32:
|
||||
return strconv.AppendFloat(nil, rv.Float(), 'g', -1, 32), true
|
||||
case reflect.Float64:
|
||||
return strconv.AppendFloat(nil, rv.Float(), 'g', -1, 64), true
|
||||
case reflect.Bool:
|
||||
return strconv.AppendBool(nil, rv.Bool()), true
|
||||
case reflect.String:
|
||||
return []byte(rv.String()), true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func asTime(src interface{}, dbLoc *time.Location, uiLoc *time.Location) (*time.Time, error) {
|
||||
switch t := src.(type) {
|
||||
case string:
|
||||
return convert.String2Time(t, dbLoc, uiLoc)
|
||||
case *sql.NullString:
|
||||
if !t.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return convert.String2Time(t.String, dbLoc, uiLoc)
|
||||
case []uint8:
|
||||
if t == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return convert.String2Time(string(t), dbLoc, uiLoc)
|
||||
case *sql.NullTime:
|
||||
if !t.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
z, _ := t.Time.Zone()
|
||||
if len(z) == 0 || t.Time.Year() == 0 || t.Time.Location().String() != dbLoc.String() {
|
||||
tm := time.Date(t.Time.Year(), t.Time.Month(), t.Time.Day(), t.Time.Hour(),
|
||||
t.Time.Minute(), t.Time.Second(), t.Time.Nanosecond(), dbLoc).In(uiLoc)
|
||||
return &tm, nil
|
||||
}
|
||||
tm := t.Time.In(uiLoc)
|
||||
return &tm, nil
|
||||
case *time.Time:
|
||||
z, _ := t.Zone()
|
||||
if len(z) == 0 || t.Year() == 0 || t.Location().String() != dbLoc.String() {
|
||||
tm := time.Date(t.Year(), t.Month(), t.Day(), t.Hour(),
|
||||
t.Minute(), t.Second(), t.Nanosecond(), dbLoc).In(uiLoc)
|
||||
return &tm, nil
|
||||
}
|
||||
tm := t.In(uiLoc)
|
||||
return &tm, nil
|
||||
case time.Time:
|
||||
z, _ := t.Zone()
|
||||
if len(z) == 0 || t.Year() == 0 || t.Location().String() != dbLoc.String() {
|
||||
tm := time.Date(t.Year(), t.Month(), t.Day(), t.Hour(),
|
||||
t.Minute(), t.Second(), t.Nanosecond(), dbLoc).In(uiLoc)
|
||||
return &tm, nil
|
||||
}
|
||||
tm := t.In(uiLoc)
|
||||
return &tm, nil
|
||||
case int:
|
||||
tm := time.Unix(int64(t), 0).In(uiLoc)
|
||||
return &tm, nil
|
||||
case int64:
|
||||
tm := time.Unix(t, 0).In(uiLoc)
|
||||
return &tm, nil
|
||||
case *sql.NullInt64:
|
||||
tm := time.Unix(t.Int64, 0).In(uiLoc)
|
||||
return &tm, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported value %#v as time", src)
|
||||
}
|
||||
|
||||
// convertAssign copies to dest the value in src, converting it if possible.
|
||||
// An error is returned if the copy would result in loss of information.
|
||||
// dest should be a pointer type.
|
||||
|
@ -585,7 +244,7 @@ func convertAssign(dest, src interface{}, originalLocation *time.Location, conve
|
|||
}
|
||||
return nil
|
||||
}
|
||||
case *NullUint32:
|
||||
case *convert.NullUint32:
|
||||
switch d := dest.(type) {
|
||||
case *uint8:
|
||||
if s.Valid {
|
||||
|
@ -603,7 +262,7 @@ func convertAssign(dest, src interface{}, originalLocation *time.Location, conve
|
|||
}
|
||||
return nil
|
||||
}
|
||||
case *NullUint64:
|
||||
case *convert.NullUint64:
|
||||
switch d := dest.(type) {
|
||||
case *uint64:
|
||||
if s.Valid {
|
||||
|
@ -628,11 +287,11 @@ func convertAssign(dest, src interface{}, originalLocation *time.Location, conve
|
|||
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||
reflect.Float32, reflect.Float64:
|
||||
*d = asString(src)
|
||||
*d = convert.AsString(src)
|
||||
return nil
|
||||
}
|
||||
case *[]byte:
|
||||
if b, ok := asBytes(src); ok {
|
||||
if b, ok := convert.AsBytes(src); ok {
|
||||
*d = b
|
||||
return nil
|
||||
}
|
||||
|
@ -666,7 +325,7 @@ func convertAssignV(dv reflect.Value, src interface{}) error {
|
|||
}
|
||||
return convertAssignV(dv.Elem(), src)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
i64, err := asInt64(src)
|
||||
i64, err := convert.AsInt64(src)
|
||||
if err != nil {
|
||||
err = strconvErr(err)
|
||||
return fmt.Errorf("converting driver.Value type %T to a %s: %v", src, dv.Kind(), err)
|
||||
|
@ -674,7 +333,7 @@ func convertAssignV(dv reflect.Value, src interface{}) error {
|
|||
dv.SetInt(i64)
|
||||
return nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
u64, err := asUint64(src)
|
||||
u64, err := convert.AsUint64(src)
|
||||
if err != nil {
|
||||
err = strconvErr(err)
|
||||
return fmt.Errorf("converting driver.Value type %T to a %s: %v", src, dv.Kind(), err)
|
||||
|
@ -682,7 +341,7 @@ func convertAssignV(dv reflect.Value, src interface{}) error {
|
|||
dv.SetUint(u64)
|
||||
return nil
|
||||
case reflect.Float32, reflect.Float64:
|
||||
f64, err := asFloat64(src)
|
||||
f64, err := convert.AsFloat64(src)
|
||||
if err != nil {
|
||||
err = strconvErr(err)
|
||||
return fmt.Errorf("converting driver.Value type %T to a %s: %v", src, dv.Kind(), err)
|
||||
|
@ -690,17 +349,17 @@ func convertAssignV(dv reflect.Value, src interface{}) error {
|
|||
dv.SetFloat(f64)
|
||||
return nil
|
||||
case reflect.String:
|
||||
dv.SetString(asString(src))
|
||||
dv.SetString(convert.AsString(src))
|
||||
return nil
|
||||
case reflect.Bool:
|
||||
b, err := asBool(src)
|
||||
b, err := convert.AsBool(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dv.SetBool(b)
|
||||
return nil
|
||||
case reflect.Slice, reflect.Map, reflect.Struct, reflect.Array:
|
||||
data, ok := asBytes(src)
|
||||
data, ok := convert.AsBytes(src)
|
||||
if !ok {
|
||||
return fmt.Errorf("onvertAssignV: src cannot be as bytes %#v", src)
|
||||
}
|
||||
|
@ -753,201 +412,3 @@ func asKind(vv reflect.Value, tp reflect.Type) (interface{}, error) {
|
|||
}
|
||||
return nil, fmt.Errorf("unsupported primary key type: %v, %v", tp, vv)
|
||||
}
|
||||
|
||||
func asBool(src interface{}) (bool, error) {
|
||||
switch v := src.(type) {
|
||||
case bool:
|
||||
return v, nil
|
||||
case *bool:
|
||||
return *v, nil
|
||||
case *sql.NullBool:
|
||||
return v.Bool, nil
|
||||
case int64:
|
||||
return v > 0, nil
|
||||
case int:
|
||||
return v > 0, nil
|
||||
case int8:
|
||||
return v > 0, nil
|
||||
case int16:
|
||||
return v > 0, nil
|
||||
case int32:
|
||||
return v > 0, nil
|
||||
case []byte:
|
||||
if len(v) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
if v[0] == 0x00 {
|
||||
return false, nil
|
||||
} else if v[0] == 0x01 {
|
||||
return true, nil
|
||||
}
|
||||
return strconv.ParseBool(string(v))
|
||||
case string:
|
||||
return strconv.ParseBool(v)
|
||||
case *sql.NullInt64:
|
||||
return v.Int64 > 0, nil
|
||||
case *sql.NullInt32:
|
||||
return v.Int32 > 0, nil
|
||||
default:
|
||||
return false, fmt.Errorf("unknow type %T as bool", src)
|
||||
}
|
||||
}
|
||||
|
||||
// str2PK convert string value to primary key value according to tp
|
||||
func str2PKValue(s string, tp reflect.Type) (reflect.Value, error) {
|
||||
var err error
|
||||
var result interface{}
|
||||
var defReturn = reflect.Zero(tp)
|
||||
|
||||
switch tp.Kind() {
|
||||
case reflect.Int:
|
||||
result, err = strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return defReturn, fmt.Errorf("convert %s as int: %s", s, err.Error())
|
||||
}
|
||||
case reflect.Int8:
|
||||
x, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return defReturn, fmt.Errorf("convert %s as int8: %s", s, err.Error())
|
||||
}
|
||||
result = int8(x)
|
||||
case reflect.Int16:
|
||||
x, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return defReturn, fmt.Errorf("convert %s as int16: %s", s, err.Error())
|
||||
}
|
||||
result = int16(x)
|
||||
case reflect.Int32:
|
||||
x, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return defReturn, fmt.Errorf("convert %s as int32: %s", s, err.Error())
|
||||
}
|
||||
result = int32(x)
|
||||
case reflect.Int64:
|
||||
result, err = strconv.ParseInt(s, 10, 64)
|
||||
if err != nil {
|
||||
return defReturn, fmt.Errorf("convert %s as int64: %s", s, err.Error())
|
||||
}
|
||||
case reflect.Uint:
|
||||
x, err := strconv.ParseUint(s, 10, 64)
|
||||
if err != nil {
|
||||
return defReturn, fmt.Errorf("convert %s as uint: %s", s, err.Error())
|
||||
}
|
||||
result = uint(x)
|
||||
case reflect.Uint8:
|
||||
x, err := strconv.ParseUint(s, 10, 64)
|
||||
if err != nil {
|
||||
return defReturn, fmt.Errorf("convert %s as uint8: %s", s, err.Error())
|
||||
}
|
||||
result = uint8(x)
|
||||
case reflect.Uint16:
|
||||
x, err := strconv.ParseUint(s, 10, 64)
|
||||
if err != nil {
|
||||
return defReturn, fmt.Errorf("convert %s as uint16: %s", s, err.Error())
|
||||
}
|
||||
result = uint16(x)
|
||||
case reflect.Uint32:
|
||||
x, err := strconv.ParseUint(s, 10, 64)
|
||||
if err != nil {
|
||||
return defReturn, fmt.Errorf("convert %s as uint32: %s", s, err.Error())
|
||||
}
|
||||
result = uint32(x)
|
||||
case reflect.Uint64:
|
||||
result, err = strconv.ParseUint(s, 10, 64)
|
||||
if err != nil {
|
||||
return defReturn, fmt.Errorf("convert %s as uint64: %s", s, err.Error())
|
||||
}
|
||||
case reflect.String:
|
||||
result = s
|
||||
default:
|
||||
return defReturn, errors.New("unsupported convert type")
|
||||
}
|
||||
return reflect.ValueOf(result).Convert(tp), nil
|
||||
}
|
||||
|
||||
func str2PK(s string, tp reflect.Type) (interface{}, error) {
|
||||
v, err := str2PKValue(s, tp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v.Interface(), nil
|
||||
}
|
||||
|
||||
var (
|
||||
_ sql.Scanner = &NullUint64{}
|
||||
)
|
||||
|
||||
// NullUint64 represents an uint64 that may be null.
|
||||
// NullUint64 implements the Scanner interface so
|
||||
// it can be used as a scan destination, similar to NullString.
|
||||
type NullUint64 struct {
|
||||
Uint64 uint64
|
||||
Valid bool
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (n *NullUint64) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
n.Uint64, n.Valid = 0, false
|
||||
return nil
|
||||
}
|
||||
n.Valid = true
|
||||
var err error
|
||||
n.Uint64, err = asUint64(value)
|
||||
return err
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (n NullUint64) Value() (driver.Value, error) {
|
||||
if !n.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return n.Uint64, nil
|
||||
}
|
||||
|
||||
var (
|
||||
_ sql.Scanner = &NullUint32{}
|
||||
)
|
||||
|
||||
// NullUint32 represents an uint32 that may be null.
|
||||
// NullUint32 implements the Scanner interface so
|
||||
// it can be used as a scan destination, similar to NullString.
|
||||
type NullUint32 struct {
|
||||
Uint32 uint32
|
||||
Valid bool // Valid is true if Uint32 is not NULL
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (n *NullUint32) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
n.Uint32, n.Valid = 0, false
|
||||
return nil
|
||||
}
|
||||
n.Valid = true
|
||||
i64, err := asUint64(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n.Uint32 = uint32(i64)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (n NullUint32) Value() (driver.Value, error) {
|
||||
if !n.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return int64(n.Uint32), nil
|
||||
}
|
||||
|
||||
var (
|
||||
_ sql.Scanner = &EmptyScanner{}
|
||||
)
|
||||
|
||||
// EmptyScanner represents an empty scanner which will ignore the scan
|
||||
type EmptyScanner struct{}
|
||||
|
||||
// Scan implements sql.Scanner
|
||||
func (EmptyScanner) Scan(value interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
// 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 (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"xorm.io/xorm/internal/utils"
|
||||
)
|
||||
|
||||
// String2Time converts a string to time with original location
|
||||
func String2Time(s string, originalLocation *time.Location, convertedLocation *time.Location) (*time.Time, error) {
|
||||
if len(s) == 19 {
|
||||
if s == utils.ZeroTime0 || s == utils.ZeroTime1 {
|
||||
return &time.Time{}, nil
|
||||
}
|
||||
dt, err := time.ParseInLocation("2006-01-02 15:04:05", s, originalLocation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dt = dt.In(convertedLocation)
|
||||
return &dt, nil
|
||||
} else if len(s) == 20 && s[10] == 'T' && s[19] == 'Z' {
|
||||
dt, err := time.ParseInLocation("2006-01-02T15:04:05", s[:19], originalLocation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dt = dt.In(convertedLocation)
|
||||
return &dt, nil
|
||||
} else if len(s) == 25 && s[10] == 'T' && s[19] == '+' && s[22] == ':' {
|
||||
dt, err := time.Parse(time.RFC3339, s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dt = dt.In(convertedLocation)
|
||||
return &dt, nil
|
||||
} else {
|
||||
i, err := strconv.ParseInt(s, 10, 64)
|
||||
if err == nil {
|
||||
tm := time.Unix(i, 0).In(convertedLocation)
|
||||
return &tm, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported conversion from %s to time", s)
|
||||
}
|
|
@ -9,68 +9,18 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"xorm.io/xorm"
|
||||
"xorm.io/xorm/contexts"
|
||||
"xorm.io/xorm/internal/convert"
|
||||
"xorm.io/xorm/schemas"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func convertInt(v interface{}) (int64, error) {
|
||||
switch v.(type) {
|
||||
case int:
|
||||
return int64(v.(int)), nil
|
||||
case int8:
|
||||
return int64(v.(int8)), nil
|
||||
case int16:
|
||||
return int64(v.(int16)), nil
|
||||
case int32:
|
||||
return int64(v.(int32)), nil
|
||||
case int64:
|
||||
return v.(int64), nil
|
||||
case []byte:
|
||||
i, err := strconv.ParseInt(string(v.([]byte)), 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return i, nil
|
||||
case string:
|
||||
i, err := strconv.ParseInt(v.(string), 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
return 0, fmt.Errorf("unsupported type: %v", v)
|
||||
}
|
||||
|
||||
func convertFloat(v interface{}) (float64, error) {
|
||||
switch v.(type) {
|
||||
case float32:
|
||||
return float64(v.(float32)), nil
|
||||
case float64:
|
||||
return v.(float64), nil
|
||||
case string:
|
||||
i, err := strconv.ParseFloat(v.(string), 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return i, nil
|
||||
case []byte:
|
||||
i, err := strconv.ParseFloat(string(v.([]byte)), 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
return 0, fmt.Errorf("unsupported type: %v", v)
|
||||
}
|
||||
|
||||
func TestGetVar(t *testing.T) {
|
||||
assert.NoError(t, PrepareEngine())
|
||||
|
||||
|
@ -261,17 +211,17 @@ func TestGetVar(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, has)
|
||||
|
||||
v1, err := convertInt(valuesSliceInter[0])
|
||||
v1, err := convert.AsInt64(valuesSliceInter[0])
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 1, v1)
|
||||
|
||||
assert.Equal(t, "hi", fmt.Sprintf("%s", valuesSliceInter[1]))
|
||||
|
||||
v3, err := convertInt(valuesSliceInter[2])
|
||||
v3, err := convert.AsInt64(valuesSliceInter[2])
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 28, v3)
|
||||
|
||||
v4, err := convertFloat(valuesSliceInter[3])
|
||||
v4, err := convert.AsFloat64(valuesSliceInter[3])
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "1.5", fmt.Sprintf("%v", v4))
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"xorm.io/xorm"
|
||||
"xorm.io/xorm/convert"
|
||||
"xorm.io/xorm/internal/convert"
|
||||
"xorm.io/xorm/internal/json"
|
||||
"xorm.io/xorm/schemas"
|
||||
|
||||
|
|
51
internal/convert/bool.go
Normal file
51
internal/convert/bool.go
Normal file
|
@ -0,0 +1,51 @@
|
|||
// 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"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// AsBool convert interface as bool
|
||||
func AsBool(src interface{}) (bool, error) {
|
||||
switch v := src.(type) {
|
||||
case bool:
|
||||
return v, nil
|
||||
case *bool:
|
||||
return *v, nil
|
||||
case *sql.NullBool:
|
||||
return v.Bool, nil
|
||||
case int64:
|
||||
return v > 0, nil
|
||||
case int:
|
||||
return v > 0, nil
|
||||
case int8:
|
||||
return v > 0, nil
|
||||
case int16:
|
||||
return v > 0, nil
|
||||
case int32:
|
||||
return v > 0, nil
|
||||
case []byte:
|
||||
if len(v) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
if v[0] == 0x00 {
|
||||
return false, nil
|
||||
} else if v[0] == 0x01 {
|
||||
return true, nil
|
||||
}
|
||||
return strconv.ParseBool(string(v))
|
||||
case string:
|
||||
return strconv.ParseBool(v)
|
||||
case *sql.NullInt64:
|
||||
return v.Int64 > 0, nil
|
||||
case *sql.NullInt32:
|
||||
return v.Int32 > 0, nil
|
||||
default:
|
||||
return false, fmt.Errorf("unknow type %T as bool", src)
|
||||
}
|
||||
}
|
142
internal/convert/float.go
Normal file
142
internal/convert/float.go
Normal file
|
@ -0,0 +1,142 @@
|
|||
// 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"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// AsFloat64 convets interface as float64
|
||||
func AsFloat64(src interface{}) (float64, error) {
|
||||
switch v := src.(type) {
|
||||
case int:
|
||||
return float64(v), nil
|
||||
case int16:
|
||||
return float64(v), nil
|
||||
case int32:
|
||||
return float64(v), nil
|
||||
case int8:
|
||||
return float64(v), nil
|
||||
case int64:
|
||||
return float64(v), nil
|
||||
case uint:
|
||||
return float64(v), nil
|
||||
case uint8:
|
||||
return float64(v), nil
|
||||
case uint16:
|
||||
return float64(v), nil
|
||||
case uint32:
|
||||
return float64(v), nil
|
||||
case uint64:
|
||||
return float64(v), nil
|
||||
case []byte:
|
||||
return strconv.ParseFloat(string(v), 64)
|
||||
case string:
|
||||
return strconv.ParseFloat(v, 64)
|
||||
case *sql.NullString:
|
||||
return strconv.ParseFloat(v.String, 64)
|
||||
case *sql.NullInt32:
|
||||
return float64(v.Int32), nil
|
||||
case *sql.NullInt64:
|
||||
return float64(v.Int64), nil
|
||||
case *sql.NullFloat64:
|
||||
return v.Float64, nil
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(src)
|
||||
switch rv.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return float64(rv.Int()), nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return float64(rv.Uint()), nil
|
||||
case reflect.Float64, reflect.Float32:
|
||||
return float64(rv.Float()), nil
|
||||
case reflect.String:
|
||||
return strconv.ParseFloat(rv.String(), 64)
|
||||
}
|
||||
return 0, fmt.Errorf("unsupported value %T as int64", src)
|
||||
}
|
||||
|
||||
// AsBigFloat converts interface as big.Float
|
||||
func AsBigFloat(src interface{}) (*big.Float, error) {
|
||||
res := big.NewFloat(0)
|
||||
switch v := src.(type) {
|
||||
case int:
|
||||
res.SetInt64(int64(v))
|
||||
return res, nil
|
||||
case int16:
|
||||
res.SetInt64(int64(v))
|
||||
return res, nil
|
||||
case int32:
|
||||
res.SetInt64(int64(v))
|
||||
return res, nil
|
||||
case int8:
|
||||
res.SetInt64(int64(v))
|
||||
return res, nil
|
||||
case int64:
|
||||
res.SetInt64(int64(v))
|
||||
return res, nil
|
||||
case uint:
|
||||
res.SetUint64(uint64(v))
|
||||
return res, nil
|
||||
case uint8:
|
||||
res.SetUint64(uint64(v))
|
||||
return res, nil
|
||||
case uint16:
|
||||
res.SetUint64(uint64(v))
|
||||
return res, nil
|
||||
case uint32:
|
||||
res.SetUint64(uint64(v))
|
||||
return res, nil
|
||||
case uint64:
|
||||
res.SetUint64(uint64(v))
|
||||
return res, nil
|
||||
case []byte:
|
||||
res.SetString(string(v))
|
||||
return res, nil
|
||||
case string:
|
||||
res.SetString(v)
|
||||
return res, nil
|
||||
case *sql.NullString:
|
||||
if v.Valid {
|
||||
res.SetString(v.String)
|
||||
return res, nil
|
||||
}
|
||||
return nil, nil
|
||||
case *sql.NullInt32:
|
||||
if v.Valid {
|
||||
res.SetInt64(int64(v.Int32))
|
||||
return res, nil
|
||||
}
|
||||
return nil, nil
|
||||
case *sql.NullInt64:
|
||||
if v.Valid {
|
||||
res.SetInt64(int64(v.Int64))
|
||||
return res, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(src)
|
||||
switch rv.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
res.SetInt64(rv.Int())
|
||||
return res, nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
res.SetUint64(rv.Uint())
|
||||
return res, nil
|
||||
case reflect.Float64, reflect.Float32:
|
||||
res.SetFloat64(rv.Float())
|
||||
return res, nil
|
||||
case reflect.String:
|
||||
res.SetString(rv.String())
|
||||
return res, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported value %T as big.Float", src)
|
||||
}
|
178
internal/convert/int.go
Normal file
178
internal/convert/int.go
Normal file
|
@ -0,0 +1,178 @@
|
|||
// 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"
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// AsInt64 converts interface as int64
|
||||
func AsInt64(src interface{}) (int64, error) {
|
||||
switch v := src.(type) {
|
||||
case int:
|
||||
return int64(v), nil
|
||||
case int16:
|
||||
return int64(v), nil
|
||||
case int32:
|
||||
return int64(v), nil
|
||||
case int8:
|
||||
return int64(v), nil
|
||||
case int64:
|
||||
return v, nil
|
||||
case uint:
|
||||
return int64(v), nil
|
||||
case uint8:
|
||||
return int64(v), nil
|
||||
case uint16:
|
||||
return int64(v), nil
|
||||
case uint32:
|
||||
return int64(v), nil
|
||||
case uint64:
|
||||
return int64(v), nil
|
||||
case []byte:
|
||||
return strconv.ParseInt(string(v), 10, 64)
|
||||
case string:
|
||||
return strconv.ParseInt(v, 10, 64)
|
||||
case *sql.NullString:
|
||||
return strconv.ParseInt(v.String, 10, 64)
|
||||
case *sql.NullInt32:
|
||||
return int64(v.Int32), nil
|
||||
case *sql.NullInt64:
|
||||
return int64(v.Int64), nil
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(src)
|
||||
switch rv.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return rv.Int(), nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return int64(rv.Uint()), nil
|
||||
case reflect.Float64, reflect.Float32:
|
||||
return int64(rv.Float()), nil
|
||||
case reflect.String:
|
||||
return strconv.ParseInt(rv.String(), 10, 64)
|
||||
}
|
||||
return 0, fmt.Errorf("unsupported value %T as int64", src)
|
||||
}
|
||||
|
||||
// AsUint64 converts interface as uint64
|
||||
func AsUint64(src interface{}) (uint64, error) {
|
||||
switch v := src.(type) {
|
||||
case int:
|
||||
return uint64(v), nil
|
||||
case int16:
|
||||
return uint64(v), nil
|
||||
case int32:
|
||||
return uint64(v), nil
|
||||
case int8:
|
||||
return uint64(v), nil
|
||||
case int64:
|
||||
return uint64(v), nil
|
||||
case uint:
|
||||
return uint64(v), nil
|
||||
case uint8:
|
||||
return uint64(v), nil
|
||||
case uint16:
|
||||
return uint64(v), nil
|
||||
case uint32:
|
||||
return uint64(v), nil
|
||||
case uint64:
|
||||
return v, nil
|
||||
case []byte:
|
||||
return strconv.ParseUint(string(v), 10, 64)
|
||||
case string:
|
||||
return strconv.ParseUint(v, 10, 64)
|
||||
case *sql.NullString:
|
||||
return strconv.ParseUint(v.String, 10, 64)
|
||||
case *sql.NullInt32:
|
||||
return uint64(v.Int32), nil
|
||||
case *sql.NullInt64:
|
||||
return uint64(v.Int64), nil
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(src)
|
||||
switch rv.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return uint64(rv.Int()), nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return uint64(rv.Uint()), nil
|
||||
case reflect.Float64, reflect.Float32:
|
||||
return uint64(rv.Float()), nil
|
||||
case reflect.String:
|
||||
return strconv.ParseUint(rv.String(), 10, 64)
|
||||
}
|
||||
return 0, fmt.Errorf("unsupported value %T as uint64", src)
|
||||
}
|
||||
|
||||
var (
|
||||
_ sql.Scanner = &NullUint64{}
|
||||
)
|
||||
|
||||
// NullUint64 represents an uint64 that may be null.
|
||||
// NullUint64 implements the Scanner interface so
|
||||
// it can be used as a scan destination, similar to NullString.
|
||||
type NullUint64 struct {
|
||||
Uint64 uint64
|
||||
Valid bool
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (n *NullUint64) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
n.Uint64, n.Valid = 0, false
|
||||
return nil
|
||||
}
|
||||
n.Valid = true
|
||||
var err error
|
||||
n.Uint64, err = AsUint64(value)
|
||||
return err
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (n NullUint64) Value() (driver.Value, error) {
|
||||
if !n.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return n.Uint64, nil
|
||||
}
|
||||
|
||||
var (
|
||||
_ sql.Scanner = &NullUint32{}
|
||||
)
|
||||
|
||||
// NullUint32 represents an uint32 that may be null.
|
||||
// NullUint32 implements the Scanner interface so
|
||||
// it can be used as a scan destination, similar to NullString.
|
||||
type NullUint32 struct {
|
||||
Uint32 uint32
|
||||
Valid bool // Valid is true if Uint32 is not NULL
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (n *NullUint32) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
n.Uint32, n.Valid = 0, false
|
||||
return nil
|
||||
}
|
||||
n.Valid = true
|
||||
i64, err := AsUint64(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n.Uint32 = uint32(i64)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (n NullUint32) Value() (driver.Value, error) {
|
||||
if !n.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return int64(n.Uint32), nil
|
||||
}
|
19
internal/convert/scanner.go
Normal file
19
internal/convert/scanner.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
// 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"
|
||||
|
||||
var (
|
||||
_ sql.Scanner = &EmptyScanner{}
|
||||
)
|
||||
|
||||
// EmptyScanner represents an empty scanner which will ignore the scan
|
||||
type EmptyScanner struct{}
|
||||
|
||||
// Scan implements sql.Scanner
|
||||
func (EmptyScanner) Scan(value interface{}) error {
|
||||
return nil
|
||||
}
|
75
internal/convert/string.go
Normal file
75
internal/convert/string.go
Normal file
|
@ -0,0 +1,75 @@
|
|||
// 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"
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// AsString converts interface as string
|
||||
func AsString(src interface{}) string {
|
||||
switch v := src.(type) {
|
||||
case string:
|
||||
return v
|
||||
case []byte:
|
||||
return string(v)
|
||||
case *sql.NullString:
|
||||
return v.String
|
||||
case *sql.NullInt32:
|
||||
return fmt.Sprintf("%d", v.Int32)
|
||||
case *sql.NullInt64:
|
||||
return fmt.Sprintf("%d", v.Int64)
|
||||
}
|
||||
rv := reflect.ValueOf(src)
|
||||
switch rv.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return strconv.FormatInt(rv.Int(), 10)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return strconv.FormatUint(rv.Uint(), 10)
|
||||
case reflect.Float64:
|
||||
return strconv.FormatFloat(rv.Float(), 'g', -1, 64)
|
||||
case reflect.Float32:
|
||||
return strconv.FormatFloat(rv.Float(), 'g', -1, 32)
|
||||
case reflect.Bool:
|
||||
return strconv.FormatBool(rv.Bool())
|
||||
}
|
||||
return fmt.Sprintf("%v", src)
|
||||
}
|
||||
|
||||
// AsBytes converts interface as bytes
|
||||
func AsBytes(src interface{}) ([]byte, bool) {
|
||||
switch t := src.(type) {
|
||||
case []byte:
|
||||
return t, true
|
||||
case *sql.NullString:
|
||||
if !t.Valid {
|
||||
return nil, true
|
||||
}
|
||||
return []byte(t.String), true
|
||||
case *sql.RawBytes:
|
||||
return *t, true
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(src)
|
||||
|
||||
switch rv.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return strconv.AppendInt(nil, rv.Int(), 10), true
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return strconv.AppendUint(nil, rv.Uint(), 10), true
|
||||
case reflect.Float32:
|
||||
return strconv.AppendFloat(nil, rv.Float(), 'g', -1, 32), true
|
||||
case reflect.Float64:
|
||||
return strconv.AppendFloat(nil, rv.Float(), 'g', -1, 64), true
|
||||
case reflect.Bool:
|
||||
return strconv.AppendBool(nil, rv.Bool()), true
|
||||
case reflect.String:
|
||||
return []byte(rv.String()), true
|
||||
}
|
||||
return nil, false
|
||||
}
|
108
internal/convert/time.go
Normal file
108
internal/convert/time.go
Normal file
|
@ -0,0 +1,108 @@
|
|||
// 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"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"xorm.io/xorm/internal/utils"
|
||||
)
|
||||
|
||||
// String2Time converts a string to time with original location
|
||||
func String2Time(s string, originalLocation *time.Location, convertedLocation *time.Location) (*time.Time, error) {
|
||||
if len(s) == 19 {
|
||||
if s == utils.ZeroTime0 || s == utils.ZeroTime1 {
|
||||
return &time.Time{}, nil
|
||||
}
|
||||
dt, err := time.ParseInLocation("2006-01-02 15:04:05", s, originalLocation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dt = dt.In(convertedLocation)
|
||||
return &dt, nil
|
||||
} else if len(s) == 20 && s[10] == 'T' && s[19] == 'Z' {
|
||||
dt, err := time.ParseInLocation("2006-01-02T15:04:05", s[:19], originalLocation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dt = dt.In(convertedLocation)
|
||||
return &dt, nil
|
||||
} else if len(s) == 25 && s[10] == 'T' && s[19] == '+' && s[22] == ':' {
|
||||
dt, err := time.Parse(time.RFC3339, s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dt = dt.In(convertedLocation)
|
||||
return &dt, nil
|
||||
} else {
|
||||
i, err := strconv.ParseInt(s, 10, 64)
|
||||
if err == nil {
|
||||
tm := time.Unix(i, 0).In(convertedLocation)
|
||||
return &tm, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported conversion from %s to time", s)
|
||||
}
|
||||
|
||||
// AsTime converts interface as time
|
||||
func AsTime(src interface{}, dbLoc *time.Location, uiLoc *time.Location) (*time.Time, error) {
|
||||
switch t := src.(type) {
|
||||
case string:
|
||||
return String2Time(t, dbLoc, uiLoc)
|
||||
case *sql.NullString:
|
||||
if !t.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return String2Time(t.String, dbLoc, uiLoc)
|
||||
case []uint8:
|
||||
if t == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return String2Time(string(t), dbLoc, uiLoc)
|
||||
case *sql.NullTime:
|
||||
if !t.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
z, _ := t.Time.Zone()
|
||||
if len(z) == 0 || t.Time.Year() == 0 || t.Time.Location().String() != dbLoc.String() {
|
||||
tm := time.Date(t.Time.Year(), t.Time.Month(), t.Time.Day(), t.Time.Hour(),
|
||||
t.Time.Minute(), t.Time.Second(), t.Time.Nanosecond(), dbLoc).In(uiLoc)
|
||||
return &tm, nil
|
||||
}
|
||||
tm := t.Time.In(uiLoc)
|
||||
return &tm, nil
|
||||
case *time.Time:
|
||||
z, _ := t.Zone()
|
||||
if len(z) == 0 || t.Year() == 0 || t.Location().String() != dbLoc.String() {
|
||||
tm := time.Date(t.Year(), t.Month(), t.Day(), t.Hour(),
|
||||
t.Minute(), t.Second(), t.Nanosecond(), dbLoc).In(uiLoc)
|
||||
return &tm, nil
|
||||
}
|
||||
tm := t.In(uiLoc)
|
||||
return &tm, nil
|
||||
case time.Time:
|
||||
z, _ := t.Zone()
|
||||
if len(z) == 0 || t.Year() == 0 || t.Location().String() != dbLoc.String() {
|
||||
tm := time.Date(t.Year(), t.Month(), t.Day(), t.Hour(),
|
||||
t.Minute(), t.Second(), t.Nanosecond(), dbLoc).In(uiLoc)
|
||||
return &tm, nil
|
||||
}
|
||||
tm := t.In(uiLoc)
|
||||
return &tm, nil
|
||||
case int:
|
||||
tm := time.Unix(int64(t), 0).In(uiLoc)
|
||||
return &tm, nil
|
||||
case int64:
|
||||
tm := time.Unix(t, 0).In(uiLoc)
|
||||
return &tm, nil
|
||||
case *sql.NullInt64:
|
||||
tm := time.Unix(t.Int64, 0).In(uiLoc)
|
||||
return &tm, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported value %#v as time", src)
|
||||
}
|
|
@ -15,8 +15,8 @@ import (
|
|||
|
||||
"xorm.io/builder"
|
||||
"xorm.io/xorm/contexts"
|
||||
"xorm.io/xorm/convert"
|
||||
"xorm.io/xorm/dialects"
|
||||
"xorm.io/xorm/internal/convert"
|
||||
"xorm.io/xorm/internal/json"
|
||||
"xorm.io/xorm/internal/utils"
|
||||
"xorm.io/xorm/schemas"
|
||||
|
|
|
@ -11,8 +11,8 @@ import (
|
|||
"reflect"
|
||||
"time"
|
||||
|
||||
"xorm.io/xorm/convert"
|
||||
"xorm.io/xorm/dialects"
|
||||
"xorm.io/xorm/internal/convert"
|
||||
"xorm.io/xorm/internal/json"
|
||||
"xorm.io/xorm/internal/utils"
|
||||
"xorm.io/xorm/schemas"
|
||||
|
|
|
@ -12,8 +12,8 @@ import (
|
|||
"reflect"
|
||||
"time"
|
||||
|
||||
"xorm.io/xorm/convert"
|
||||
"xorm.io/xorm/dialects"
|
||||
"xorm.io/xorm/internal/convert"
|
||||
"xorm.io/xorm/internal/json"
|
||||
"xorm.io/xorm/schemas"
|
||||
)
|
||||
|
|
10
scan.go
10
scan.go
|
@ -11,9 +11,9 @@ import (
|
|||
"reflect"
|
||||
"time"
|
||||
|
||||
"xorm.io/xorm/convert"
|
||||
"xorm.io/xorm/core"
|
||||
"xorm.io/xorm/dialects"
|
||||
"xorm.io/xorm/internal/convert"
|
||||
"xorm.io/xorm/schemas"
|
||||
)
|
||||
|
||||
|
@ -35,9 +35,9 @@ func genScanResultsByBeanNullable(bean interface{}) (interface{}, bool, error) {
|
|||
case *int64:
|
||||
return &sql.NullInt64{}, true, nil
|
||||
case *uint, *uint8, *uint16, *uint32:
|
||||
return &NullUint32{}, true, nil
|
||||
return &convert.NullUint32{}, true, nil
|
||||
case *uint64:
|
||||
return &NullUint64{}, true, nil
|
||||
return &convert.NullUint64{}, true, nil
|
||||
case *float32, *float64:
|
||||
return &sql.NullFloat64{}, true, nil
|
||||
case *bool:
|
||||
|
@ -63,9 +63,9 @@ func genScanResultsByBeanNullable(bean interface{}) (interface{}, bool, error) {
|
|||
case reflect.Int32, reflect.Int, reflect.Int16, reflect.Int8:
|
||||
return &sql.NullInt32{}, true, nil
|
||||
case reflect.Uint64:
|
||||
return &NullUint64{}, true, nil
|
||||
return &convert.NullUint64{}, true, nil
|
||||
case reflect.Uint32, reflect.Uint, reflect.Uint16, reflect.Uint8:
|
||||
return &NullUint32{}, true, nil
|
||||
return &convert.NullUint32{}, true, nil
|
||||
default:
|
||||
return nil, false, fmt.Errorf("unsupported type: %#v", bean)
|
||||
}
|
||||
|
|
14
session.go
14
session.go
|
@ -18,8 +18,8 @@ import (
|
|||
"strings"
|
||||
|
||||
"xorm.io/xorm/contexts"
|
||||
"xorm.io/xorm/convert"
|
||||
"xorm.io/xorm/core"
|
||||
"xorm.io/xorm/internal/convert"
|
||||
"xorm.io/xorm/internal/json"
|
||||
"xorm.io/xorm/internal/statements"
|
||||
"xorm.io/xorm/log"
|
||||
|
@ -435,7 +435,7 @@ func (session *Session) row2Slice(rows *core.Rows, fields []string, types []*sql
|
|||
}
|
||||
|
||||
func (session *Session) setJSON(fieldValue *reflect.Value, fieldType reflect.Type, scanResult interface{}) error {
|
||||
bs, ok := asBytes(scanResult)
|
||||
bs, ok := convert.AsBytes(scanResult)
|
||||
if !ok {
|
||||
return fmt.Errorf("unsupported database data type: %#v", scanResult)
|
||||
}
|
||||
|
@ -476,7 +476,7 @@ func (session *Session) convertBeanField(col *schemas.Column, fieldValue *reflec
|
|||
|
||||
if fieldValue.CanAddr() {
|
||||
if structConvert, ok := fieldValue.Addr().Interface().(convert.Conversion); ok {
|
||||
data, ok := asBytes(scanResult)
|
||||
data, ok := convert.AsBytes(scanResult)
|
||||
if !ok {
|
||||
return fmt.Errorf("cannot convert %#v as bytes", scanResult)
|
||||
}
|
||||
|
@ -485,7 +485,7 @@ func (session *Session) convertBeanField(col *schemas.Column, fieldValue *reflec
|
|||
}
|
||||
|
||||
if structConvert, ok := fieldValue.Interface().(convert.Conversion); ok {
|
||||
data, ok := asBytes(scanResult)
|
||||
data, ok := convert.AsBytes(scanResult)
|
||||
if !ok {
|
||||
return fmt.Errorf("cannot convert %#v as bytes", scanResult)
|
||||
}
|
||||
|
@ -525,7 +525,7 @@ func (session *Session) convertBeanField(col *schemas.Column, fieldValue *reflec
|
|||
case reflect.Complex64, reflect.Complex128:
|
||||
return session.setJSON(fieldValue, fieldType, scanResult)
|
||||
case reflect.Slice, reflect.Array:
|
||||
bs, ok := asBytes(scanResult)
|
||||
bs, ok := convert.AsBytes(scanResult)
|
||||
if ok && fieldType.Elem().Kind() == reflect.Uint8 {
|
||||
if col.SQLType.IsText() {
|
||||
x := reflect.New(fieldType)
|
||||
|
@ -551,7 +551,7 @@ func (session *Session) convertBeanField(col *schemas.Column, fieldValue *reflec
|
|||
}
|
||||
case reflect.Struct:
|
||||
if fieldType.ConvertibleTo(schemas.BigFloatType) {
|
||||
v, err := asBigFloat(scanResult)
|
||||
v, err := convert.AsBigFloat(scanResult)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -565,7 +565,7 @@ func (session *Session) convertBeanField(col *schemas.Column, fieldValue *reflec
|
|||
dbTZ = col.TimeZone
|
||||
}
|
||||
|
||||
t, err := asTime(scanResult, dbTZ, session.engine.TZLocation)
|
||||
t, err := convert.AsTime(scanResult, dbTZ, session.engine.TZLocation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ package xorm
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"xorm.io/builder"
|
||||
|
@ -476,12 +475,13 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in
|
|||
} else if sliceValue.Kind() == reflect.Map {
|
||||
var key = ids[j]
|
||||
keyType := sliceValue.Type().Key()
|
||||
keyValue := reflect.New(keyType)
|
||||
var ikey interface{}
|
||||
if len(key) == 1 {
|
||||
ikey, err = str2PK(fmt.Sprintf("%v", key[0]), keyType)
|
||||
if err != nil {
|
||||
if err := convertAssignV(keyValue, key[0]); err != nil {
|
||||
return err
|
||||
}
|
||||
ikey = keyValue.Elem().Interface()
|
||||
} else {
|
||||
if keyType.Kind() != reflect.Slice {
|
||||
return errors.New("table have multiple primary keys, key is not schemas.PK or slice")
|
||||
|
|
|
@ -15,8 +15,8 @@ import (
|
|||
"time"
|
||||
|
||||
"xorm.io/xorm/caches"
|
||||
"xorm.io/xorm/convert"
|
||||
"xorm.io/xorm/core"
|
||||
"xorm.io/xorm/internal/convert"
|
||||
"xorm.io/xorm/internal/utils"
|
||||
"xorm.io/xorm/schemas"
|
||||
)
|
||||
|
|
|
@ -14,8 +14,8 @@ import (
|
|||
"unicode"
|
||||
|
||||
"xorm.io/xorm/caches"
|
||||
"xorm.io/xorm/convert"
|
||||
"xorm.io/xorm/dialects"
|
||||
"xorm.io/xorm/internal/convert"
|
||||
"xorm.io/xorm/names"
|
||||
"xorm.io/xorm/schemas"
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue
Block a user