Skip to content

Commit

Permalink
add mapper
Browse files Browse the repository at this point in the history
  • Loading branch information
it512 committed Feb 1, 2019
1 parent 0263da3 commit c148eda
Show file tree
Hide file tree
Showing 10 changed files with 897 additions and 2 deletions.
7 changes: 7 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module github.com/twiglab/sqlt

require (
github.com/jmoiron/sqlx v1.2.0
github.com/lib/pq v1.0.0
google.golang.org/appengine v1.4.0 // indirect
)
13 changes: 13 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
54 changes: 54 additions & 0 deletions internal/mapper/base.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package mapper

import (
"errors"
"reflect"
)

type ColScanner interface {
Columns() ([]string, error)
Scan(dest ...interface{}) error
Err() error
}

func MapScan(r ColScanner, dest map[string]interface{}) error {
columns, err := r.Columns()
if err != nil {
return err
}

values := make([]interface{}, len(columns))
for i := range values {
values[i] = new(interface{})
}

err = r.Scan(values...)
if err != nil {
return err
}

for i, column := range columns {
dest[column] = *(values[i].(*interface{}))
}

return r.Err()
}

func StructScan(rows ColScanner, dest interface{}) (err error) {
destValue := reflect.ValueOf(dest)
elemType := destValue.Type()

if elemType.Kind() != reflect.Ptr {
return errors.New("slice elem must ptr ")
}

rowMap := make(map[string]interface{})
if err = MapScan(rows, rowMap); err != nil {
return
}
if err = MapperMap(rowMap, dest); err != nil {
return
}

return
}
233 changes: 233 additions & 0 deletions internal/mapper/convert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
package mapper

import (
"fmt"
"math/big"
"reflect"
"strconv"
"time"
)

// Convert is the target string
type Convert string

// Set string
func (f *Convert) Set(v string) {
if v != "" {
*f = Convert(v)
} else {
f.Clear()
}
}

// Clear string
func (f *Convert) Clear() {
*f = Convert(0x1E)
}

// Exist check string exist
func (f Convert) Exist() bool {
return string(f) != string(0x1E)
}

// Bool string to bool
func (f Convert) Bool() (bool, error) {
return strconv.ParseBool(f.String())
}

// Float32 string to float32
func (f Convert) Float32() (float32, error) {
v, err := strconv.ParseFloat(f.String(), 32)
return float32(v), err
}

// Float64 string to float64
func (f Convert) Float64() (float64, error) {
return strconv.ParseFloat(f.String(), 64)
}

// Int string to int
func (f Convert) Int() (int, error) {
v, err := strconv.ParseInt(f.String(), 10, 32)
return int(v), err
}

// Int8 string to int8
func (f Convert) Int8() (int8, error) {
v, err := strconv.ParseInt(f.String(), 10, 8)
return int8(v), err
}

// Int16 string to int16
func (f Convert) Int16() (int16, error) {
v, err := strconv.ParseInt(f.String(), 10, 16)
return int16(v), err
}

// Int32 string to int32
func (f Convert) Int32() (int32, error) {
v, err := strconv.ParseInt(f.String(), 10, 32)
return int32(v), err
}

// Int64 string to int64
func (f Convert) Int64() (int64, error) {
v, err := strconv.ParseInt(f.String(), 10, 64)
if err != nil {
i := new(big.Int)
ni, ok := i.SetString(f.String(), 10) // octal
if !ok {
return v, err
}
return ni.Int64(), nil
}
return v, err
}

// Uint string to uint
func (f Convert) Uint() (uint, error) {
v, err := strconv.ParseUint(f.String(), 10, 32)
return uint(v), err
}

// Uint8 string to uint8
func (f Convert) Uint8() (uint8, error) {
v, err := strconv.ParseUint(f.String(), 10, 8)
return uint8(v), err
}

// Uint16 string to uint16
func (f Convert) Uint16() (uint16, error) {
v, err := strconv.ParseUint(f.String(), 10, 16)
return uint16(v), err
}

// Uint32 string to uint32
func (f Convert) Uint32() (uint32, error) {
v, err := strconv.ParseUint(f.String(), 10, 32)
return uint32(v), err
}

// Uint64 string to uint64
func (f Convert) Uint64() (uint64, error) {
v, err := strconv.ParseUint(f.String(), 10, 64)
if err != nil {
i := new(big.Int)
ni, ok := i.SetString(f.String(), 10)
if !ok {
return v, err
}
return ni.Uint64(), nil
}
return v, err
}

// String string to string
func (f Convert) String() string {
if f.Exist() {
return string(f)
}
return ""
}

// ToString interface to string
func ToString(value interface{}, args ...int) (s string) {
switch v := value.(type) {
case bool:
s = strconv.FormatBool(v)
case float32:
s = strconv.FormatFloat(float64(v), 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 32))
case float64:
s = strconv.FormatFloat(v, 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 64))
case int:
s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
case int8:
s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
case int16:
s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
case int32:
s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
case int64:
s = strconv.FormatInt(v, argInt(args).Get(0, 10))
case uint:
s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
case uint8:
s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
case uint16:
s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
case uint32:
s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
case uint64:
s = strconv.FormatUint(v, argInt(args).Get(0, 10))
case string:
s = v
case []byte:
s = string(v)
default:
s = fmt.Sprintf("%v", v)
}
return s
}

// ToInt64 interface to int64
func ToInt64(value interface{}) (d int64) {
val := reflect.ValueOf(value)
switch value.(type) {
case int, int8, int16, int32, int64:
d = val.Int()
case uint, uint8, uint16, uint32, uint64:
d = int64(val.Uint())
default:
panic(fmt.Errorf("ToInt64 need numeric not `%T`", value))
}
return
}

type argInt []int

// get int by index from int slice
func (a argInt) Get(i int, args ...int) (r int) {
if i >= 0 && i < len(a) {
r = a[i]
}
if len(args) > 0 {
r = args[0]
}
return
}

// TimeToUnix transform time to Unix time, the number of seconds elapsed
func TimeToUnix(t time.Time) int64 {
return t.Unix()
}

// UnixToTime transform Unix time to local Time
func UnixToTime(tt int64) time.Time {
return time.Unix(tt, 0)
}

// TimeToUnixLocation transform time to Unix time with time location
// location like "Asia/Shanghai"
func TimeToUnixLocation(t time.Time, location string) (int64, error) {
timeStr := t.Format("2006-01-02 15:04:05")
loc, err := time.LoadLocation(location)
if err != nil {
return 0, err
}
tt, err := time.ParseInLocation("2006-01-02 15:04:05", timeStr, loc)
if err != nil {
return 0, err
}
return tt.Unix(), err
}

// UnixToTimeLocation transform Unix time to local Time with time location
// location like "Asia/Shanghai"
func UnixToTimeLocation(tt int64, location string) (time.Time, error) {
loc, err := time.LoadLocation(location)
if err != nil {
return time.Now(), err
}
time.Local = loc
return time.Unix(tt, 0), nil
}
35 changes: 35 additions & 0 deletions internal/mapper/jsontime.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package mapper

import "time"

type JSONTime time.Time

var (
timeJSONFormat = "2006-01-02 15:04:05"
)

func SetTimeJSONFormat(format string) {
timeJSONFormat = format
}

func GetTimeJSONFormat() string {
return timeJSONFormat
}

func (t *JSONTime) UnmarshalJSON(data []byte) (err error) {
now, err := time.ParseInLocation(`"`+timeJSONFormat+`"`, string(data), time.Local)
*t = JSONTime(now)
return
}

func (t JSONTime) MarshalJSON() ([]byte, error) {
b := make([]byte, 0, len(timeJSONFormat)+2)
b = append(b, '"')
b = time.Time(t).AppendFormat(b, timeJSONFormat)
b = append(b, '"')
return b, nil
}

func (t JSONTime) String() string {
return time.Time(t).Format(timeJSONFormat)
}
Loading

0 comments on commit c148eda

Please sign in to comment.