TODO: sql to time.Time Type

This commit is contained in:
eson 2020-09-07 15:13:50 +08:00
parent 83dcdf86c9
commit d3689a0c8b
3 changed files with 170 additions and 56 deletions

View File

@ -3,11 +3,14 @@ package intimate
import ( import (
"database/sql" "database/sql"
"encoding/binary" "encoding/binary"
"encoding/json"
"fmt" "fmt"
"log" "log"
"reflect" "reflect"
"strconv" "strconv"
"testing" "testing"
"github.com/davecgh/go-spew/spew"
) )
type Store struct { type Store struct {
@ -120,14 +123,9 @@ func (queue *Queue) Pop() (result interface{}, err error) {
for i := 0; i < obj.NumField(); i++ { for i := 0; i < obj.NumField(); i++ {
field := obj.Field(i) field := obj.Field(i)
convert(*fields[i].(*interface{}), field, columntypes[i]) convert(*fields[i].(*interface{}), field, columntypes[i])
// if field.Type().Kind() == reflect.Ptr {
// field.Elem().Set(reflect.ValueOf(*fields[i].(*interface{})))
// continue
// }
// field.Set(reflect.ValueOf(*fields[i].(*interface{})))
} }
return obj.Interface(), err return obj.Addr().Interface(), err
} }
func TestAutoStore(t *testing.T) { func TestAutoStore(t *testing.T) {
@ -135,90 +133,204 @@ func TestAutoStore(t *testing.T) {
store := NewStore(uri) store := NewStore(uri)
queue := store.Table("streamer").Queue(TSreamer{}, "operator = 0") queue := store.Table("streamer").Queue(TSreamer{}, "operator = 0")
t.Error(queue.Pop()) re, _ := queue.Pop()
pstreamer := re.(*TSreamer)
m := make(map[string]interface{})
json.Unmarshal(pstreamer.Iface.([]byte), &m)
spew.Println(re.(*TSreamer), m)
streamer := &TSreamer{} streamer := &TSreamer{}
streamer.Uid = 2 streamer.Uid = 2
streamer.UserID = &sql.NullString{String: "xixi", Valid: true} streamer.UserID = &sql.NullString{String: "hehe", Valid: true}
streamer.Name = "streamer" streamer.Name = "streamer"
streamer.Operator = 0 streamer.Operator = 0
streamer.Bit = 0b11
streamer.Ext = &sql.NullString{String: "ext", Valid: true} streamer.Ext = &sql.NullString{String: "ext", Valid: true}
err := store.Table("streamer").Insert(streamer)
tag := make(map[string]interface{})
tag["json"] = true
tag["name"] = "test"
btag, err := json.Marshal(tag)
if err != nil {
t.Error(err)
}
streamer.Iface = btag
err = store.Table("streamer").Insert(streamer)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
} }
func assign(field reflect.Value, dest interface{}) (bool, error) {
func convert(dest interface{}, field reflect.Value, columntype *sql.ColumnType) error { switch field.Kind() {
log.Println("type:", field.Type(), ",kind:", field.Kind(), ",field:", field)
if field.Kind() == reflect.Ptr {
fn := field.Type().Elem().Name() // New 一个 field.Type().Elem() . 然后判断 columntype 转化 成 NullString Time
field = field.Elem() //
log.Println("type:", fn, ",kind:", field.Kind(), ",field:", field)
}
if field.Kind() == reflect.Interface {
}
// log.Println(field.Kind(), field, reflect.TypeOf(field).Elem().Name(), columntype.ScanType().Kind())
switch fv := field.Kind(); fv {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if dest == nil {
return fmt.Errorf("converting NULL to %s is unsupported", field.Kind())
}
log.Println(binary.Varint(dest.([]byte)))
s := asString(dest) s := asString(dest)
i64, err := strconv.ParseInt(s, 10, field.Type().Bits()) i64, err := strconv.ParseInt(s, 10, field.Type().Bits())
if err != nil { if err != nil {
err = strconvErr(err) err = strconvErr(err)
return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", dest, s, field.Kind(), err) return false, fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", dest, s, field.Kind(), err)
} }
field.SetInt(i64) field.SetInt(i64)
return nil return false, nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
if dest == nil {
return fmt.Errorf("converting NULL to %s is unsupported", field.Kind())
}
s := asString(dest) s := asString(dest)
u64, err := strconv.ParseUint(s, 10, field.Type().Bits()) u64, err := strconv.ParseUint(s, 10, field.Type().Bits())
if err != nil { if err != nil {
err = strconvErr(err) err = strconvErr(err)
return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", dest, s, field.Kind(), err) return false, fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", dest, s, field.Kind(), err)
} }
field.SetUint(u64) field.SetUint(u64)
return nil return false, nil
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
if dest == nil {
return fmt.Errorf("converting NULL to %s is unsupported", field.Kind())
}
s := asString(dest) s := asString(dest)
f64, err := strconv.ParseFloat(s, field.Type().Bits()) f64, err := strconv.ParseFloat(s, field.Type().Bits())
if err != nil { if err != nil {
err = strconvErr(err) err = strconvErr(err)
return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", dest, s, field.Kind(), err) return false, fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", dest, s, field.Kind(), err)
} }
field.SetFloat(f64) field.SetFloat(f64)
return nil return false, nil
case reflect.String: case reflect.String:
if dest == nil { field.SetString(string(dest.([]byte)))
return fmt.Errorf("converting NULL to %s is unsupported", field.Kind()) return false, nil
} case reflect.Interface:
switch v := dest.(type) { return true, nil
case string: }
field.SetString(v)
return nil
case []byte:
field.SetString(string(v))
return nil
}
default:
// log.Println(fv, columntype.ScanType().Kind()) return false, fmt.Errorf("")
}
func convert(dest interface{}, field reflect.Value, columntype *sql.ColumnType) error {
log.Println("type:", field.Type(), ",kind:", field.Kind(), ",field:", field, "scanType:", columntype.ScanType(), "databaseType:", columntype.DatabaseTypeName())
if field.Kind() == reflect.Ptr {
fn := field.Type().Elem() // New 一个 field.Type().Elem() . 然后判断 columntype 转化 成 NullString Time
field.Set(reflect.New(fn))
field = field.Elem()
log.Println("type:", fn.Name(), ",kind:", field.Kind(), ",fieldtype:", field.Type())
}
// log.Println(field.Kind(), field, reflect.TypeOf(field).Elem().Name(), columntype.ScanType().Kind())
if dest == nil {
return fmt.Errorf("converting NULL to %s is unsupported", field.Kind())
}
switch columntype.DatabaseTypeName() {
case "TINYINT":
fallthrough
case "SMALLINT":
fallthrough
case "MEDIUMINT":
fallthrough
case "INT":
fallthrough
case "BIGINT":
isdefault, err := assign(field, dest)
if err != nil {
return err
}
if isdefault {
s := asString(dest)
i64, err := strconv.ParseInt(s, 10, 64)
if err != nil {
err = strconvErr(err)
return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", dest, s, field.Kind(), err)
}
// reflect.New(reflect.TypeOf(i64))
field.Set(reflect.ValueOf(i64))
}
return nil
case "FLOAT":
fallthrough
case "DOUBLE":
fallthrough
case "DECIMAL":
isdefault, err := assign(field, dest)
if err != nil {
return err
}
if isdefault {
s := asString(dest)
f64, err := strconv.ParseFloat(s, 64)
if err != nil {
err = strconvErr(err)
return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", dest, s, field.Kind(), err)
}
field.Set(reflect.ValueOf(f64))
}
return nil
case "BINARY":
fallthrough
case "VARBINARY":
fallthrough
case "TINYBLOB":
fallthrough
case "BLOB":
fallthrough
case "MEDIUMBLOB":
fallthrough
case "LONGBLOB":
fallthrough
case "JSON":
isdefault, err := assign(field, dest)
if err != nil {
return err
}
if isdefault {
field.Set(reflect.ValueOf(dest.([]byte)))
}
case "CHAR":
fallthrough
case "VARCHAR":
fallthrough
case "TINYTEXT":
fallthrough
case "TEXT":
fallthrough
case "MEDIUMTEXT":
fallthrough
case "LONGTEXT":
isdefault, err := assign(field, dest)
if err != nil {
return err
}
if isdefault {
field.Set(reflect.ValueOf(string(dest.([]byte))))
}
return nil
case "BIT":
var bits []byte = make([]byte, 8)
copy(bits, dest.([]byte))
switch field.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
field.SetInt(int64(binary.LittleEndian.Uint64(bits)))
return nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
field.SetUint(binary.LittleEndian.Uint64(bits))
return nil
case reflect.Interface:
field.Set(reflect.ValueOf(binary.LittleEndian.Uint64(bits)))
return nil
}
return nil
}
// log.Println(fv, columntype.ScanType().Kind())
if iscan, ok := field.Addr().Interface().(sql.Scanner); ok {
err := iscan.Scan(dest)
if err != nil {
return err
}
return nil
} }
return nil return nil
@ -344,5 +456,6 @@ type TSreamer struct {
UserID *sql.NullString `field:"userid"` UserID *sql.NullString `field:"userid"`
Ext *sql.NullString `field:"ext"` Ext *sql.NullString `field:"ext"`
Iface interface{} `field:"tag"` Iface interface{} `field:"tag"`
Bit uint64 `field:"bit"`
Operator int `field:"operator"` Operator int `field:"operator"`
} }

View File

@ -20,4 +20,4 @@ do
projectworkspace=$src/bin/$projectname projectworkspace=$src/bin/$projectname
cd $path && mkdir $projectworkspace -p && go build -o $projectworkspace/$projectname cd $path && mkdir $projectworkspace -p && go build -o $projectworkspace/$projectname
cd $src cd $src
done done

1
go.mod
View File

@ -7,6 +7,7 @@ require (
github.com/474420502/focus v0.12.0 github.com/474420502/focus v0.12.0
github.com/474420502/gcurl v0.4.5 github.com/474420502/gcurl v0.4.5
github.com/474420502/requests v1.9.1 github.com/474420502/requests v1.9.1
github.com/davecgh/go-spew v1.1.1
github.com/go-sql-driver/mysql v1.5.0 github.com/go-sql-driver/mysql v1.5.0
github.com/lestrrat-go/libxml2 v0.0.0-20200215080510-6483566f52cb github.com/lestrrat-go/libxml2 v0.0.0-20200215080510-6483566f52cb
github.com/tebeka/selenium v0.9.9 github.com/tebeka/selenium v0.9.9