diff --git a/database/gdb/gdb.go b/database/gdb/gdb.go index 084e6c27a..be9d9dcc8 100644 --- a/database/gdb/gdb.go +++ b/database/gdb/gdb.go @@ -209,6 +209,12 @@ type Link interface { Prepare(sql string) (*sql.Stmt, error) } +// Counter is the type for update count. +type Counter struct { + Field string + Value float64 +} + type ( // Value is the field value type. Value = *gvar.Var diff --git a/database/gdb/gdb_core.go b/database/gdb/gdb_core.go index 71979a0f6..c8a631940 100644 --- a/database/gdb/gdb_core.go +++ b/database/gdb/gdb_core.go @@ -699,8 +699,35 @@ func (c *Core) DoUpdate(link Link, table string, data interface{}, condition str dataMap = ConvertDataForTableRecord(data) ) for k, v := range dataMap { - fields = append(fields, c.DB.QuoteWord(k)+"=?") - params = append(params, v) + switch value := v.(type) { + case *Counter: + if value.Value != 0 { + column := c.DB.QuoteWord(value.Field) + var symbol string + if value.Value < 0 { + symbol = "-" + } else { + symbol = "+" + } + fields = append(fields, fmt.Sprintf("%s=%s%s?", column, column, symbol)) + params = append(params, value.Value) + } + case Counter: + if value.Value != 0 { + column := c.DB.QuoteWord(value.Field) + var symbol string + if value.Value < 0 { + symbol = "-" + } else { + symbol = "+" + } + fields = append(fields, fmt.Sprintf("%s=%s%s?", column, column, symbol)) + params = append(params, value.Value) + } + default: + fields = append(fields, c.DB.QuoteWord(k)+"=?") + params = append(params, v) + } } updates = strings.Join(fields, ",") default: diff --git a/database/gdb/gdb_func.go b/database/gdb/gdb_func.go index 25c6b368f..6d5ca0c83 100644 --- a/database/gdb/gdb_func.go +++ b/database/gdb/gdb_func.go @@ -127,6 +127,8 @@ func ConvertDataForTableRecord(value interface{}) map[string]interface{} { switch v.(type) { case time.Time, *time.Time, gtime.Time, *gtime.Time: continue + case Counter, *Counter: + continue default: // Use string conversion in default. if s, ok := v.(apiString); ok { diff --git a/database/gdb/gdb_z_mysql_method_test.go b/database/gdb/gdb_z_mysql_method_test.go index a0b5f819c..1929713c5 100644 --- a/database/gdb/gdb_z_mysql_method_test.go +++ b/database/gdb/gdb_z_mysql_method_test.go @@ -10,6 +10,7 @@ import ( "fmt" "github.com/gogf/gf/container/garray" "github.com/gogf/gf/encoding/gparser" + "github.com/gogf/gf/util/gconv" "testing" "time" @@ -1405,3 +1406,47 @@ func Test_Empty_Slice_Argument(t *testing.T) { t.Assert(len(result), 0) }) } + +// update counter test +func Test_DB_UpdateCounter(t *testing.T) { + tableName := "gf_update_counter_test" + defer dropTable(tableName) + _, err := db.Exec(fmt.Sprintf(` + CREATE TABLE IF NOT EXISTS %s ( + id int(10) unsigned NOT NULL, + views int(8) unsigned DEFAULT '0' NOT NULL , + updated_time int(10) unsigned DEFAULT '0' NOT NULL + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableName)) + if err != nil { + gtest.Fatal(err) + } + id := 1 + insertData := g.Map{ + "id": id, + "views": 0, + "updated_time": 0, + } + _, err = db.Insert(tableName, insertData) + if err != nil { + gtest.Fatal(err) + } + gtest.C(t, func(t *gtest.T) { + gdbCounter := &gdb.Counter{ + Field: "views", + Value: 1, + } + updateData := g.Map{ + "views": gdbCounter, + "updated_time": gtime.Now().Unix(), + } + result, err := db.Update(tableName, updateData, "id="+gconv.String(id)) + t.Assert(err, nil) + n, _ := result.RowsAffected() + t.Assert(n, 1) + one, err := db.Table(tableName).Where("id", id).One() + t.Assert(err, nil) + t.Assert(one["id"].Int(), 1) + t.Assert(one["views"].String(), "1") + }) +} diff --git a/util/gvalid/gvalid_check.go b/util/gvalid/gvalid_check.go index be420b392..0db27f0df 100644 --- a/util/gvalid/gvalid_check.go +++ b/util/gvalid/gvalid_check.go @@ -58,6 +58,7 @@ var ( "date-format": {}, "email": {}, "phone": {}, + "phone-loose": {}, "telephone": {}, "passport": {}, "password": {}, @@ -356,6 +357,7 @@ func doCheckBuildInRules( // 1. China Mobile: // 134, 135, 136, 137, 138, 139, 150, 151, 152, 157, 158, 159, 182, 183, 184, 187, 188, // 178(4G), 147(Net); + // 172 // // 2. China Unicom: // 130, 131, 132, 155, 156, 185, 186 ,176(4G), 145(Net), 175 @@ -372,7 +374,12 @@ func doCheckBuildInRules( // 6. 2018: // 16x, 19x case "phone": - match = gregex.IsMatchString(`^13[\d]{9}$|^14[5,7]{1}\d{8}$|^15[^4]{1}\d{8}$|^16[\d]{9}$|^17[0,3,5,6,7,8]{1}\d{8}$|^18[\d]{9}$|^19[\d]{9}$`, valueStr) + match = gregex.IsMatchString(`^13[\d]{9}$|^14[5,7]{1}\d{8}$|^15[^4]{1}\d{8}$|^16[\d]{9}$|^17[0,2,3,5,6,7,8]{1}\d{8}$|^18[\d]{9}$|^19[\d]{9}$`, valueStr) + // Loose mobile phone number verification(宽松的手机号验证) + // As long as the 11 digit numbers beginning with + // 13, 14, 15, 16, 17, 18, 19 can pass the verification (只要满足 13、14、15、16、17、18、19开头的11位数字都可以通过验证) + case "phone-loose": + match = gregex.IsMatchString(`^1(3|4|5|6|7|8|9)\d{9}$`, valueStr) // Telephone number: // "XXXX-XXXXXXX" diff --git a/util/gvalid/gvalid_unit_basic_all_test.go b/util/gvalid/gvalid_unit_basic_all_test.go index f147aea06..2b62d2782 100755 --- a/util/gvalid/gvalid_unit_basic_all_test.go +++ b/util/gvalid/gvalid_unit_basic_all_test.go @@ -237,6 +237,22 @@ func Test_Phone(t *testing.T) { }) } +func Test_PhoneLoose(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + err1 := gvalid.Check("13333333333", "phone-loose", nil) + err2 := gvalid.Check("15555555555", "phone-loose", nil) + err3 := gvalid.Check("16666666666", "phone-loose", nil) + err4 := gvalid.Check("23333333333", "phone-loose", nil) + err5 := gvalid.Check("1333333333", "phone-loose", nil) + err6 := gvalid.Check("10333333333", "phone-loose", nil) + t.Assert(err1, nil) + t.Assert(err2, nil) + t.Assert(err3, nil) + t.AssertNE(err4, nil) + t.AssertNE(err5, nil) + t.AssertNE(err6, nil) + }) +} func Test_Telephone(t *testing.T) { gtest.C(t, func(t *gtest.T) { rule := "telephone" diff --git a/util/gvalid/i18n/cn/validation.toml b/util/gvalid/i18n/cn/validation.toml index 7ed7501a0..fab6dfba6 100644 --- a/util/gvalid/i18n/cn/validation.toml +++ b/util/gvalid/i18n/cn/validation.toml @@ -9,6 +9,7 @@ "gf.gvalid.rule.date-format" = ":attribute 日期格式不满足:format" "gf.gvalid.rule.email" = ":attribute 邮箱地址格式不正确" "gf.gvalid.rule.phone" = ":attribute 手机号码格式不正确" +"gf.gvalid.rule.phone-loose" = ":attribute 手机号码格式不正确" "gf.gvalid.rule.telephone" = ":attribute 电话号码格式不正确" "gf.gvalid.rule.passport" = ":attribute 账号格式不合法,必需以字母开头,只能包含字母、数字和下划线,长度在6~18之间" "gf.gvalid.rule.password" = ":attribute 密码格式不合法,密码格式为任意6-18位的可见字符" diff --git a/util/gvalid/i18n/en/validation.toml b/util/gvalid/i18n/en/validation.toml index f6cb071da..7dc56cab0 100644 --- a/util/gvalid/i18n/en/validation.toml +++ b/util/gvalid/i18n/en/validation.toml @@ -9,6 +9,7 @@ "gf.gvalid.rule.date-format" = "The :attribute value does not match the format :format" "gf.gvalid.rule.email" = "The :attribute value must be a valid email address" "gf.gvalid.rule.phone" = "The :attribute value must be a valid phone number" +"gf.gvalid.rule.phone-loose" = "The :attribute value must be a valid phone number" "gf.gvalid.rule.telephone" = "The :attribute value must be a valid telephone number" "gf.gvalid.rule.passport" = "The :attribute value is not a valid passport format" "gf.gvalid.rule.password" = "The :attribute value is not a valid passport format"