This commit is contained in:
huangqian
2022-02-19 19:49:36 +08:00
14 changed files with 117 additions and 59 deletions

View File

@ -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)

View File

@ -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,

View File

@ -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"])

View File

@ -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)
})
}

View File

@ -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)

View File

@ -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"}`), `密码强度不足`)
})
}

View File

@ -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!@#`)
})
}

View File

@ -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`)
})

View File

@ -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), `密码强度不足`)
})
}

View File

@ -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")
})
}

View File

@ -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)
})
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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)
})
}