mirror of
https://gitee.com/johng/gf
synced 2026-06-06 16:21:40 +08:00
Merge branch 'master' of https://github.com/gogf/gf
This commit is contained in:
@ -159,6 +159,7 @@ func (c *Core) convertFieldValueToLocalValue(fieldValue interface{}, fieldType s
|
||||
return gconv.Bool(fieldValue)
|
||||
|
||||
case "date":
|
||||
// Date without time.
|
||||
if t, ok := fieldValue.(time.Time); ok {
|
||||
return gtime.NewFromTime(t).Format("Y-m-d")
|
||||
}
|
||||
@ -173,7 +174,7 @@ func (c *Core) convertFieldValueToLocalValue(fieldValue interface{}, fieldType s
|
||||
return gtime.NewFromTime(t)
|
||||
}
|
||||
t, _ := gtime.StrToTime(gconv.String(fieldValue))
|
||||
return t.String()
|
||||
return t
|
||||
|
||||
default:
|
||||
// Auto-detect field type, using key match.
|
||||
@ -199,7 +200,7 @@ func (c *Core) convertFieldValueToLocalValue(fieldValue interface{}, fieldType s
|
||||
if err != nil {
|
||||
return s
|
||||
}
|
||||
return t.String()
|
||||
return t
|
||||
|
||||
case strings.Contains(typeName, "date"):
|
||||
s := gconv.String(fieldValue)
|
||||
@ -207,7 +208,7 @@ func (c *Core) convertFieldValueToLocalValue(fieldValue interface{}, fieldType s
|
||||
if err != nil {
|
||||
return s
|
||||
}
|
||||
return t.Format("Y-m-d")
|
||||
return t
|
||||
|
||||
default:
|
||||
return gconv.String(fieldValue)
|
||||
|
||||
@ -374,13 +374,11 @@ func formatWhereHolder(db DB, in formatWhereHolderInput) (newWhere string, newAr
|
||||
|
||||
case reflect.Map:
|
||||
for key, value := range DataToMapDeep(in.Where) {
|
||||
if gregex.IsMatchString(regularFieldNameRegPattern, key) {
|
||||
if in.OmitNil && empty.IsNil(value) {
|
||||
continue
|
||||
}
|
||||
if in.OmitEmpty && empty.IsEmpty(value) {
|
||||
continue
|
||||
}
|
||||
if in.OmitNil && empty.IsNil(value) {
|
||||
continue
|
||||
}
|
||||
if in.OmitEmpty && empty.IsEmpty(value) {
|
||||
continue
|
||||
}
|
||||
newArgs = formatWhereKeyValue(formatWhereKeyValueInput{
|
||||
Db: db,
|
||||
@ -406,13 +404,11 @@ func formatWhereHolder(db DB, in formatWhereHolderInput) (newWhere string, newAr
|
||||
if iterator, ok := in.Where.(iIterator); ok {
|
||||
iterator.Iterator(func(key, value interface{}) bool {
|
||||
ketStr := gconv.String(key)
|
||||
if gregex.IsMatchString(regularFieldNameRegPattern, ketStr) {
|
||||
if in.OmitNil && empty.IsNil(value) {
|
||||
return true
|
||||
}
|
||||
if in.OmitEmpty && empty.IsEmpty(value) {
|
||||
return true
|
||||
}
|
||||
if in.OmitNil && empty.IsNil(value) {
|
||||
return true
|
||||
}
|
||||
if in.OmitEmpty && empty.IsEmpty(value) {
|
||||
return true
|
||||
}
|
||||
newArgs = formatWhereKeyValue(formatWhereKeyValueInput{
|
||||
Db: db,
|
||||
|
||||
@ -1520,6 +1520,7 @@ func Test_Types(t *testing.T) {
|
||||
%s binary(8) NOT NULL,
|
||||
%s date NOT NULL,
|
||||
%s time NOT NULL,
|
||||
%s timestamp(6) NOT NULL,
|
||||
%s decimal(5,2) NOT NULL,
|
||||
%s double NOT NULL,
|
||||
%s bit(2) NOT NULL,
|
||||
@ -1532,6 +1533,7 @@ func Test_Types(t *testing.T) {
|
||||
"`binary`",
|
||||
"`date`",
|
||||
"`time`",
|
||||
"`timestamp`",
|
||||
"`decimal`",
|
||||
"`double`",
|
||||
"`bit`",
|
||||
@ -1541,16 +1543,17 @@ func Test_Types(t *testing.T) {
|
||||
}
|
||||
defer dropTable("types")
|
||||
data := g.Map{
|
||||
"id": 1,
|
||||
"blob": "i love gf",
|
||||
"binary": []byte("abcdefgh"),
|
||||
"date": "1880-10-24",
|
||||
"time": "10:00:01",
|
||||
"decimal": -123.456,
|
||||
"double": -123.456,
|
||||
"bit": 2,
|
||||
"tinyint": true,
|
||||
"bool": false,
|
||||
"id": 1,
|
||||
"blob": "i love gf",
|
||||
"binary": []byte("abcdefgh"),
|
||||
"date": "1880-10-24",
|
||||
"time": "10:00:01",
|
||||
"timestamp": "2022-02-14 12:00:01.123456",
|
||||
"decimal": -123.456,
|
||||
"double": -123.456,
|
||||
"bit": 2,
|
||||
"tinyint": true,
|
||||
"bool": false,
|
||||
}
|
||||
r, err := db.Model("types").Data(data).Insert()
|
||||
t.AssertNil(err)
|
||||
@ -1564,21 +1567,23 @@ func Test_Types(t *testing.T) {
|
||||
t.Assert(one["binary"].String(), data["binary"])
|
||||
t.Assert(one["date"].String(), data["date"])
|
||||
t.Assert(one["time"].String(), `10:00:01`)
|
||||
t.Assert(one["timestamp"].GTime().Format(`Y-m-d H:i:s.u`), `2022-02-14 12:00:01.123`)
|
||||
t.Assert(one["decimal"].String(), -123.46)
|
||||
t.Assert(one["double"].String(), data["double"])
|
||||
t.Assert(one["bit"].Int(), data["bit"])
|
||||
t.Assert(one["tinyint"].Bool(), data["tinyint"])
|
||||
|
||||
type T struct {
|
||||
Id int
|
||||
Blob []byte
|
||||
Binary []byte
|
||||
Date *gtime.Time
|
||||
Time *gtime.Time
|
||||
Decimal float64
|
||||
Double float64
|
||||
Bit int8
|
||||
TinyInt bool
|
||||
Id int
|
||||
Blob []byte
|
||||
Binary []byte
|
||||
Date *gtime.Time
|
||||
Time *gtime.Time
|
||||
Timestamp *gtime.Time
|
||||
Decimal float64
|
||||
Double float64
|
||||
Bit int8
|
||||
TinyInt bool
|
||||
}
|
||||
var obj *T
|
||||
err = db.Model("types").Scan(&obj)
|
||||
@ -1588,6 +1593,7 @@ func Test_Types(t *testing.T) {
|
||||
t.Assert(obj.Binary, data["binary"])
|
||||
t.Assert(obj.Date.Format("Y-m-d"), data["date"])
|
||||
t.Assert(obj.Time.String(), `10:00:01`)
|
||||
t.Assert(obj.Timestamp.Format(`Y-m-d H:i:s.u`), `2022-02-14 12:00:01.123`)
|
||||
t.Assert(obj.Decimal, -123.46)
|
||||
t.Assert(obj.Double, data["double"])
|
||||
t.Assert(obj.Bit, data["bit"])
|
||||
|
||||
@ -1454,7 +1454,7 @@ func Test_Model_Where_ISNULL_2(t *testing.T) {
|
||||
"create_time > 0": nil,
|
||||
"id": g.Slice{1, 2, 3},
|
||||
}
|
||||
result, err := db.Model(table).WherePri(conditions).Order("id asc").All()
|
||||
result, err := db.Model(table).Where(conditions).Order("id asc").All()
|
||||
t.AssertNil(err)
|
||||
t.Assert(len(result), 3)
|
||||
t.Assert(result[0]["id"].Int(), 1)
|
||||
@ -1468,19 +1468,19 @@ func Test_Model_Where_OmitEmpty(t *testing.T) {
|
||||
conditions := g.Map{
|
||||
"id < 4": "",
|
||||
}
|
||||
result, err := db.Model(table).WherePri(conditions).Order("id asc").All()
|
||||
result, err := db.Model(table).Where(conditions).Order("id desc").All()
|
||||
t.AssertNil(err)
|
||||
t.Assert(len(result), 3)
|
||||
t.Assert(result[0]["id"].Int(), 1)
|
||||
t.Assert(result[0]["id"].Int(), 3)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
conditions := g.Map{
|
||||
"id < 4": "",
|
||||
}
|
||||
result, err := db.Model(table).WherePri(conditions).OmitEmpty().Order("id asc").All()
|
||||
result, err := db.Model(table).Where(conditions).OmitEmpty().Order("id desc").All()
|
||||
t.AssertNil(err)
|
||||
t.Assert(len(result), 3)
|
||||
t.Assert(result[0]["id"].Int(), 1)
|
||||
t.Assert(len(result), 10)
|
||||
t.Assert(result[0]["id"].Int(), 10)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -117,6 +117,10 @@ func (s *Server) setHandler(ctx context.Context, in setHandlerInput) {
|
||||
if prefix != "" {
|
||||
uri = prefix + "/" + strings.TrimLeft(uri, "/")
|
||||
}
|
||||
uri = strings.TrimRight(uri, "/")
|
||||
if uri == "" {
|
||||
uri = "/"
|
||||
}
|
||||
|
||||
if len(uri) == 0 || uri[0] != '/' {
|
||||
s.Logger().Fatalf(ctx, `invalid pattern "%s", URI should lead with '/'`, pattern)
|
||||
|
||||
@ -58,7 +58,7 @@ func Test_Params_Json_Request(t *testing.T) {
|
||||
t.Assert(client.GetContent(ctx, "/get", `{"id":1,"name":"john","password1":"123Abc!@#","password2":"123Abc!@#"}`), ``)
|
||||
t.Assert(client.GetContent(ctx, "/map", `{"id":1,"name":"john","password1":"123Abc!@#","password2":"123Abc!@#"}`), ``)
|
||||
t.Assert(client.PostContent(ctx, "/parse", `{"id":1,"name":"john","password1":"123Abc!@#","password2":"123Abc!@#"}`), `1john123Abc!@#123Abc!@#`)
|
||||
t.Assert(client.PostContent(ctx, "/parse", `{"id":1,"name":"john","password1":"123Abc!@#","password2":"123"}`), `密码强度不足; 两次密码不一致`)
|
||||
t.Assert(client.PostContent(ctx, "/parse", `{"id":1,"name":"john","password1":"123Abc!@#","password2":"123"}`), `密码强度不足`)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -453,7 +453,7 @@ func Test_Params_Struct(t *testing.T) {
|
||||
t.Assert(client.PostContent(ctx, "/struct2", `id=1&name=john&password1=123&password2=456`), `1john123456`)
|
||||
t.Assert(client.PostContent(ctx, "/struct2", ``), ``)
|
||||
t.Assert(client.PostContent(ctx, "/struct-valid", `id=1&name=john&password1=123&password2=0`), "The password2 value `0` length must be between 2 and 20; 密码强度不足")
|
||||
t.Assert(client.PostContent(ctx, "/parse", `id=1&name=john&password1=123&password2=0`), "The password2 value `0` length must be between 2 and 20; 密码强度不足")
|
||||
t.Assert(client.PostContent(ctx, "/parse", `id=1&name=john&password1=123&password2=0`), "The password2 value `0` length must be between 2 and 20")
|
||||
t.Assert(client.PostContent(ctx, "/parse", `{"id":1,"name":"john","password1":"123Abc!@#","password2":"123Abc!@#"}`), `1john123Abc!@#123Abc!@#`)
|
||||
})
|
||||
}
|
||||
|
||||
@ -564,8 +564,8 @@ func Test_Params_Parse_Validation(t *testing.T) {
|
||||
client := g.Client()
|
||||
client.SetPrefix(prefix)
|
||||
|
||||
t.Assert(client.GetContent(ctx, "/parse"), `请输入账号; 账号长度为6到30位; 请输入密码; 密码长度不够; 请确认密码; 密码长度不够; 两次密码不一致`)
|
||||
t.Assert(client.GetContent(ctx, "/parse?name=john11&password1=123456&password2=123"), `密码长度不够; 两次密码不一致`)
|
||||
t.Assert(client.GetContent(ctx, "/parse"), `请输入账号`)
|
||||
t.Assert(client.GetContent(ctx, "/parse?name=john11&password1=123456&password2=123"), `密码长度不够`)
|
||||
t.Assert(client.GetContent(ctx, "/parse?name=john&password1=123456&password2=123456"), `账号长度为6到30位`)
|
||||
t.Assert(client.GetContent(ctx, "/parse?name=john11&password1=123456&password2=123456"), `ok`)
|
||||
})
|
||||
|
||||
@ -61,6 +61,6 @@ func Test_Params_Xml_Request(t *testing.T) {
|
||||
t.Assert(client.GetContent(ctx, "/map", content1), ``)
|
||||
t.Assert(client.PostContent(ctx, "/map", content1), `1john123Abc!@#123Abc!@#`)
|
||||
t.Assert(client.PostContent(ctx, "/parse", content1), `1john123Abc!@#123Abc!@#`)
|
||||
t.Assert(client.PostContent(ctx, "/parse", content2), `密码强度不足; 两次密码不一致`)
|
||||
t.Assert(client.PostContent(ctx, "/parse", content2), `密码强度不足`)
|
||||
})
|
||||
}
|
||||
|
||||
@ -189,3 +189,26 @@ func Test_Router_Group_Map(t *testing.T) {
|
||||
t.Assert(c.PostContent(ctx, "/test"), "post")
|
||||
})
|
||||
}
|
||||
|
||||
// https://github.com/gogf/gf/issues/1609
|
||||
func Test_Issue1609(t *testing.T) {
|
||||
p, _ := gtcp.GetFreePort()
|
||||
s := g.Server(p)
|
||||
group := s.Group("/api/get")
|
||||
group.GET("/", func(r *ghttp.Request) {
|
||||
r.Response.Write("get")
|
||||
})
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouterMap(false)
|
||||
gtest.Assert(s.Start(), nil)
|
||||
defer s.Shutdown()
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
c := g.Client()
|
||||
c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
|
||||
t.Assert(c.GetContent(ctx, "/api/get"), "get")
|
||||
t.Assert(c.PostContent(ctx, "/test"), "Not Found")
|
||||
})
|
||||
}
|
||||
|
||||
@ -121,12 +121,12 @@ func TestDelayAddSingleton(t *testing.T) {
|
||||
func TestDelayAddOnce(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
array := garray.New(true)
|
||||
gtimer.DelayAddOnce(ctx, 200*time.Millisecond, 200*time.Millisecond, func(ctx context.Context) {
|
||||
gtimer.DelayAddOnce(ctx, 1000*time.Millisecond, 2000*time.Millisecond, func(ctx context.Context) {
|
||||
array.Append(1)
|
||||
})
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
time.Sleep(2000 * time.Millisecond)
|
||||
t.Assert(array.Len(), 0)
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
time.Sleep(2000 * time.Millisecond)
|
||||
t.Assert(array.Len(), 1)
|
||||
})
|
||||
}
|
||||
|
||||
@ -279,9 +279,7 @@ func doConvert(in doConvertInput) interface{} {
|
||||
|
||||
default:
|
||||
if in.ReferValue != nil {
|
||||
var (
|
||||
referReflectValue reflect.Value
|
||||
)
|
||||
var referReflectValue reflect.Value
|
||||
if v, ok := in.ReferValue.(reflect.Value); ok {
|
||||
referReflectValue = v
|
||||
} else {
|
||||
|
||||
@ -338,6 +338,12 @@ func bindVarToStructAttr(elem reflect.Value, name string, value interface{}, map
|
||||
if empty.IsNil(value) {
|
||||
structFieldValue.Set(reflect.Zero(structFieldValue.Type()))
|
||||
} else {
|
||||
// Common interface check.
|
||||
var ok bool
|
||||
if err, ok = bindVarToReflectValueWithInterfaceCheck(structFieldValue, value); ok {
|
||||
return err
|
||||
}
|
||||
// Default converting.
|
||||
structFieldValue.Set(reflect.ValueOf(doConvert(
|
||||
doConvertInput{
|
||||
FromValue: value,
|
||||
@ -420,11 +426,6 @@ func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}, ma
|
||||
return nil
|
||||
}
|
||||
|
||||
// Common interface check.
|
||||
if err, ok = bindVarToReflectValueWithInterfaceCheck(structFieldValue, value); ok {
|
||||
return err
|
||||
}
|
||||
|
||||
kind := structFieldValue.Kind()
|
||||
// Converting using interface, for some kinds.
|
||||
switch kind {
|
||||
|
||||
@ -8,11 +8,13 @@ package gconv_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/v2/container/gvar"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/test/gtest"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_Scan_StructStructs(t *testing.T) {
|
||||
@ -601,3 +603,30 @@ func Test_ScanList_Embedded(t *testing.T) {
|
||||
t.Assert(len(entities[2].UserScores), 0)
|
||||
})
|
||||
}
|
||||
|
||||
type Float64 float64
|
||||
|
||||
func (f *Float64) UnmarshalValue(value interface{}) error {
|
||||
if v, ok := value.(*big.Rat); ok {
|
||||
f64, _ := v.Float64()
|
||||
*f = Float64(f64)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Test_Issue1607(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type Demo struct {
|
||||
B Float64
|
||||
}
|
||||
rat := &big.Rat{}
|
||||
rat.SetFloat64(1.5)
|
||||
|
||||
var demos = make([]Demo, 1)
|
||||
err := gconv.Scan([]map[string]interface{}{
|
||||
{"A": 1, "B": rat},
|
||||
}, &demos)
|
||||
t.AssertNil(err)
|
||||
t.Assert(demos[0].B, 1.5)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user