From 8d9dd17eac2aba1e459515ef6bea9a805dc18b6a Mon Sep 17 00:00:00 2001 From: John Date: Mon, 27 Apr 2020 21:18:42 +0800 Subject: [PATCH] add Walk function for package gset; improve fields handling feature for package gdb --- .example/other/test.go | 49 ++++------- container/gset/gset_any_set.go | 10 +++ container/gset/gset_int_set.go | 10 +++ container/gset/gset_str_set.go | 10 +++ database/gdb/gdb_driver_mysql.go | 9 +- database/gdb/gdb_model_fields.go | 95 ++++++++++++++------- database/gdb/gdb_model_utility.go | 3 + database/gdb/gdb_unit_z_mysql_model_test.go | 8 +- 8 files changed, 124 insertions(+), 70 deletions(-) diff --git a/.example/other/test.go b/.example/other/test.go index 646c37cfa..480b68fc2 100644 --- a/.example/other/test.go +++ b/.example/other/test.go @@ -1,40 +1,25 @@ package main import ( - "fmt" - "time" - "github.com/gogf/gf/frame/g" - "github.com/gogf/gf/net/ghttp" - "github.com/gogf/gf/os/gtimer" + "github.com/gogf/gf/util/gconv" ) func main() { - s := g.Server() - s.SetDumpRouterMap(false) - - s.Group("/", func(group *ghttp.RouterGroup) { - group.ALL("/", func(r *ghttp.Request) { - paramsMap := r.GetRequestMap() - fmt.Print("打印参数\n", paramsMap) - }) - }) - - addr := "localhost:8199" - gtimer.SetTimeout(time.Second, func() { - client := g.Client().SetHeader("Content-Type", "application/x-www-form-urlencoded") - client.PostContent( - fmt.Sprintf("http://%s", addr), - "time_end2020-04-18 16:11:58&returnmsg=Success&attach=", - ) - - fmt.Print("\n") - client.PostContent( - fmt.Sprintf("http://%s", addr), - "returnmsg=Success&attach=", - ) - }) - - s.SetAddr(addr) - s.Run() + type SaveReq1 struct { + Id uint + Tags string + } + type SaveReq2 struct { + Id uint + Tags []string + } + r1 := SaveReq1{ + Id: 1, + Tags: "ac", + } + var r2 *SaveReq2 + err := gconv.Struct(r1, &r2) + g.Dump(err) + g.Dump(r2) } diff --git a/container/gset/gset_any_set.go b/container/gset/gset_any_set.go index d1826bcb3..488c9c3f6 100644 --- a/container/gset/gset_any_set.go +++ b/container/gset/gset_any_set.go @@ -452,6 +452,16 @@ func (set *Set) Pops(size int) []interface{} { return array } +// Walk applies a user supplied function to every item of set. +func (set *Set) Walk(f func(item interface{}) interface{}) *Set { + set.mu.Lock() + defer set.mu.Unlock() + for k, v := range set.data { + set.data[f(k)] = v + } + return set +} + // MarshalJSON implements the interface MarshalJSON for json.Marshal. func (set *Set) MarshalJSON() ([]byte, error) { return json.Marshal(set.Slice()) diff --git a/container/gset/gset_int_set.go b/container/gset/gset_int_set.go index 70d810edc..e5edaabff 100644 --- a/container/gset/gset_int_set.go +++ b/container/gset/gset_int_set.go @@ -412,6 +412,16 @@ func (set *IntSet) Pops(size int) []int { return array } +// Walk applies a user supplied function to every item of set. +func (set *IntSet) Walk(f func(item int) int) *IntSet { + set.mu.Lock() + defer set.mu.Unlock() + for k, v := range set.data { + set.data[f(k)] = v + } + return set +} + // MarshalJSON implements the interface MarshalJSON for json.Marshal. func (set *IntSet) MarshalJSON() ([]byte, error) { return json.Marshal(set.Slice()) diff --git a/container/gset/gset_str_set.go b/container/gset/gset_str_set.go index fe02c817f..17df27b54 100644 --- a/container/gset/gset_str_set.go +++ b/container/gset/gset_str_set.go @@ -426,6 +426,16 @@ func (set *StrSet) Pops(size int) []string { return array } +// Walk applies a user supplied function to every item of set. +func (set *StrSet) Walk(f func(item string) string) *StrSet { + set.mu.Lock() + defer set.mu.Unlock() + for k, v := range set.data { + set.data[f(k)] = v + } + return set +} + // MarshalJSON implements the interface MarshalJSON for json.Marshal. func (set *StrSet) MarshalJSON() ([]byte, error) { return json.Marshal(set.Slice()) diff --git a/database/gdb/gdb_driver_mysql.go b/database/gdb/gdb_driver_mysql.go index 2d0dea44a..2aecc9b3b 100644 --- a/database/gdb/gdb_driver_mysql.go +++ b/database/gdb/gdb_driver_mysql.go @@ -83,12 +83,15 @@ func (d *DriverMysql) Tables(schema ...string) (tables []string, err error) { return } -// TableFields retrieves and returns the fields information of specified table of current schema. +// TableFields retrieves and returns the fields information of specified table of current +// schema. // // Note that it returns a map containing the field name and its corresponding fields. -// As a map is unsorted, the TableField struct has a "Index" field marks its sequence in the fields. +// As a map is unsorted, the TableField struct has a "Index" field marks its sequence in +// the fields. // -// It's using cache feature to enhance the performance, which is never expired util the process restarts. +// It's using cache feature to enhance the performance, which is never expired util the +// process restarts. func (d *DriverMysql) TableFields(table string, schema ...string) (fields map[string]*TableField, err error) { charL, charR := d.GetChars() table = gstr.Trim(table, charL+charR) diff --git a/database/gdb/gdb_model_fields.go b/database/gdb/gdb_model_fields.go index 163385377..c28df6524 100644 --- a/database/gdb/gdb_model_fields.go +++ b/database/gdb/gdb_model_fields.go @@ -7,7 +7,7 @@ package gdb import ( - "github.com/gogf/gf/container/garray" + "fmt" "github.com/gogf/gf/container/gset" "github.com/gogf/gf/text/gstr" ) @@ -34,21 +34,31 @@ func (m *Model) FieldsEx(fields string) *Model { if gstr.Contains(m.tables, " ") { panic("function FieldsEx supports only single table operations") } + tableFields, err := m.db.TableFields(m.tables) + if err != nil { + panic(err) + } + if len(tableFields) == 0 { + panic(fmt.Sprintf(`empty table fields for table "%s"`, m.tables)) + } model := m.getModel() model.fieldsEx = fields fieldsExSet := gset.NewStrSetFrom(gstr.SplitAndTrim(fields, ",")) - if m, err := m.db.TableFields(m.tables); err == nil { - model.fields = "" - for k, _ := range m { - if fieldsExSet.Contains(k) { - continue - } - if len(model.fields) > 0 { - model.fields += "," - } - model.fields += k - } + fieldsArray := make([]string, len(tableFields)) + for k, v := range tableFields { + fieldsArray[v.Index] = k } + model.fields = "" + for _, k := range fieldsArray { + if fieldsExSet.Contains(k) { + continue + } + if len(model.fields) > 0 { + model.fields += "," + } + model.fields += k + } + model.fields = model.db.QuoteString(model.fields) return model } @@ -59,14 +69,26 @@ func (m *Model) FieldsStr(prefix ...string) string { if len(prefix) > 0 { prefixStr = prefix[0] } - if m, err := m.db.TableFields(m.tables); err == nil { - fieldsArray := garray.NewStrArraySize(len(m), len(m)) - for _, field := range m { - fieldsArray.Set(field.Index, prefixStr+field.Name) - } - return fieldsArray.Join(",") + tableFields, err := m.db.TableFields(m.tables) + if err != nil { + panic(err) } - return "" + if len(tableFields) == 0 { + panic(fmt.Sprintf(`empty table fields for table "%s"`, m.tables)) + } + fieldsArray := make([]string, len(tableFields)) + for k, v := range tableFields { + fieldsArray[v.Index] = k + } + newFields := "" + for _, k := range fieldsArray { + if len(newFields) > 0 { + newFields += "," + } + newFields += prefixStr + k + } + newFields = m.db.QuoteString(newFields) + return newFields } // FieldsExStr retrieves and returns fields which are not in parameter from the table, @@ -78,17 +100,28 @@ func (m *Model) FieldsExStr(fields string, prefix ...string) string { if len(prefix) > 0 { prefixStr = prefix[0] } - if m, err := m.db.TableFields(m.tables); err == nil { - fieldsArray := garray.NewStrArraySize(len(m), len(m)) - fieldsExSet := gset.NewStrSetFrom(gstr.SplitAndTrim(fields, ",")) - for _, field := range m { - if fieldsExSet.Contains(field.Name) { - continue - } - fieldsArray.Set(field.Index, prefixStr+field.Name) - } - fieldsArray.FilterEmpty() - return fieldsArray.Join(",") + tableFields, err := m.db.TableFields(m.tables) + if err != nil { + panic(err) } - return "" + if len(tableFields) == 0 { + panic(fmt.Sprintf(`empty table fields for table "%s"`, m.tables)) + } + fieldsExSet := gset.NewStrSetFrom(gstr.SplitAndTrim(fields, ",")) + fieldsArray := make([]string, len(tableFields)) + for k, v := range tableFields { + fieldsArray[v.Index] = k + } + newFields := "" + for _, k := range fieldsArray { + if fieldsExSet.Contains(k) { + continue + } + if len(newFields) > 0 { + newFields += "," + } + newFields += prefixStr + k + } + newFields = m.db.QuoteString(newFields) + return newFields } diff --git a/database/gdb/gdb_model_utility.go b/database/gdb/gdb_model_utility.go index 93fe47566..4a8c51bd5 100644 --- a/database/gdb/gdb_model_utility.go +++ b/database/gdb/gdb_model_utility.go @@ -80,6 +80,9 @@ func (m *Model) doFilterDataMapForInsertOrUpdate(data Map, allowOmitEmpty bool) charL, charR = m.db.GetChars() chars = charL + charR ) + set.Walk(func(item string) string { + return gstr.Trim(item, chars) + }) for k := range data { k = gstr.Trim(k, chars) if !set.Contains(k) { diff --git a/database/gdb/gdb_unit_z_mysql_model_test.go b/database/gdb/gdb_unit_z_mysql_model_test.go index 69cb8afb9..6310e08b4 100644 --- a/database/gdb/gdb_unit_z_mysql_model_test.go +++ b/database/gdb/gdb_unit_z_mysql_model_test.go @@ -1870,8 +1870,8 @@ func Test_Model_FieldsStr(t *testing.T) { defer dropTable(table) gtest.C(t, func(t *gtest.T) { - t.Assert(db.Table(table).FieldsStr(), "id,passport,password,nickname,create_time") - t.Assert(db.Table(table).FieldsStr("a."), "a.id,a.passport,a.password,a.nickname,a.create_time") + t.Assert(db.Table(table).FieldsStr(), "`id`,`passport`,`password`,`nickname`,`create_time`") + t.Assert(db.Table(table).FieldsStr("a."), "`a`.`id`,`a`.`passport`,`a`.`password`,`a`.`nickname`,`a`.`create_time`") }) } @@ -1880,8 +1880,8 @@ func Test_Model_FieldsExStr(t *testing.T) { defer dropTable(table) gtest.C(t, func(t *gtest.T) { - t.Assert(db.Table(table).FieldsExStr("create_time,nickname"), "id,passport,password") - t.Assert(db.Table(table).FieldsExStr("create_time,nickname", "a."), "a.id,a.passport,a.password") + t.Assert(db.Table(table).FieldsExStr("create_time,nickname"), "`id`,`passport`,`password`") + t.Assert(db.Table(table).FieldsExStr("create_time,nickname", "a."), "`a`.`id`,`a`.`passport`,`a`.`password`") }) }