From 2236e13af704a5ea9fbdefc42dd5f202672ba9dc Mon Sep 17 00:00:00 2001 From: eson Date: Thu, 3 Sep 2020 18:50:32 +0800 Subject: [PATCH] TODO: autostore --- autostore_test.go | 157 +++++++++++++++++++++++++++++++++++++++++---- extractor_field.go | 4 +- 2 files changed, 148 insertions(+), 13 deletions(-) diff --git a/autostore_test.go b/autostore_test.go index 2c53220..926573a 100644 --- a/autostore_test.go +++ b/autostore_test.go @@ -1,28 +1,163 @@ package intimate import ( - "log" + "database/sql" + "fmt" "reflect" "testing" ) type Store struct { + db *sql.DB } -func NewStore() *Store { - return &Store{} +type Table struct { + store *Store + name string + setting interface{} + + updatesql string + selectsql string + insertsql string } -func (store *Store) Update(obj interface{}, objfields ...interface{}) { - ov := reflect.ValueOf(obj) - ot := ov.Type() - log.Printf("%#v,%#v", ov, ot) - log.Println(reflect.Indirect(reflect.ValueOf(objfields[0]))) +// const updatesql = "UPDATE %s SET %s WHERE %s = ?" + +func NewStore(uri string) *Store { + db, err := sql.Open("mysql", uri) + if err != nil { + panic(err) + } + s := &Store{db: db} + return s +} + +func (store *Store) Table(name string) *Table { + table := &Table{store: store} + table.name = name + + table.insertsql = `INSERT INTO ` + table.name + `(%s) values(%s)` + table.updatesql = `UPDATE ` + table.name + ` SET %s WHERE %s = ?` + + return table +} + +type Queue struct { + table *Table + obj reflect.Type +} + +func (t *Table) Insert(obj interface{}) error { + ov := reflect.ValueOf(obj).Elem() + ot := reflect.TypeOf(obj) + + fieldsql := "" + argssql := "" + + var args []interface{} + for i := 0; i < ov.NumField(); i++ { + field := ov.Field(i) + ftype := ot.Elem().Field(i) + + if fname, ok := ftype.Tag.Lookup("field"); ok { + if flag, ok := ftype.Tag.Lookup("uid"); ok { + if flag == "auto" { + continue + } + } + + k := ftype.Type.Kind() + if k == reflect.Ptr || k == reflect.Interface { + if !field.IsNil() { + felem := field.Elem() + args = append(args, felem.Interface()) + fieldsql += fname + "," + argssql += "?," + } + } else { + args = append(args, field.Interface()) + fieldsql += fname + "," + argssql += "?," + } + + } + + } + + ssql := fmt.Sprintf(t.insertsql, fieldsql[:len(fieldsql)-1], argssql[:len(argssql)-1]) + _, err := t.store.db.Exec(ssql, args...) + return err +} + +func (t *Table) Update(obj interface{}) error { + + ov := reflect.ValueOf(obj).Elem() + ot := reflect.TypeOf(obj) + + fieldsql := "" + var uidname string + var uidvalue interface{} + + var args []interface{} + for i := 0; i < ov.NumField(); i++ { + field := ov.Field(i) + ftype := ot.Elem().Field(i) + + if fname, ok := ftype.Tag.Lookup("field"); ok { + if _, ok := ftype.Tag.Lookup("uid"); ok { + if uidvalue != nil { + panic(fmt.Errorf("uid must unique, %s and %s", uidname, fname)) + } + uidname = fname + uidvalue = field.Interface() + continue + } + + k := ftype.Type.Kind() + if k == reflect.Ptr || k == reflect.Interface { + if !field.IsNil() { + felem := field.Elem() + args = append(args, felem.Interface()) + fieldsql += fname + " = ?," + } + } else { + args = append(args, field.Interface()) + fieldsql += fname + " = ?," + } + + } + + } + + if uidvalue == nil { + panic(fmt.Errorf("update must contain `uid` tag")) + } + + usql := fmt.Sprintf(t.updatesql, fieldsql[:len(fieldsql)-1], uidname) + args = append(args, uidvalue) + _, err := t.store.db.Exec(usql, args...) + return err +} + +type TSreamer struct { + Uid int `field:"uid" uid:"auto"` + Name interface{} `field:"name"` + UserID *sql.NullString `field:"userid"` + Ext *sql.NullString `field:"ext"` + Iface interface{} `field:"tag"` } func TestAutoStore(t *testing.T) { - store := NewStore() - streamer := &Streamer{} + uri := "root:@tcp(127.0.0.1:4000)/test?parseTime=true&loc=Local&charset=utf8mb4&collation=utf8mb4_unicode_ci" + store := NewStore(uri) + streamer := &TSreamer{} - store.Update(streamer, streamer.Channel) + streamer.Uid = 2 + streamer.UserID = nil + streamer.Name = "streamer" + streamer.Ext = &sql.NullString{String: "ext", Valid: true} + err := store.Table("streamer").Update(streamer) + if err != nil { + t.Error(err) + } } diff --git a/extractor_field.go b/extractor_field.go index 1adda5e..91a6f4a 100644 --- a/extractor_field.go +++ b/extractor_field.go @@ -38,8 +38,8 @@ func (sl *StreamerList) Set(field string, value interface{}) { } type Streamer struct { - Uid int64 // - Platform Platform // + Uid int64 `field:"uid" uid:"auto"` // + Platform Platform `field:"platform"` // UserId string // UserName sql.NullString //