From 04c70f20372f1e9068462ff37b4a8efce56f289f Mon Sep 17 00:00:00 2001 From: John Guo Date: Fri, 28 Apr 2023 14:55:37 +0800 Subject: [PATCH] fix empty string converted to none empty string type slice (#2612) --- contrib/config/polaris/go.sum | 7 ++-- contrib/drivers/mssql/mssql_z_basic_test.go | 1 - database/gdb/gdb_model_select.go | 37 +++++++++++------- example/go.mod | 2 +- example/go.sum | 3 +- internal/httputil/httputils.go | 5 +++ internal/httputil/httputils_test.go | 38 ++++++++++++++++++ util/gconv/gconv_struct.go | 20 +++++++++- util/gconv/gconv_z_unit_slice_test.go | 43 +++++++++++++++++++++ 9 files changed, 135 insertions(+), 21 deletions(-) create mode 100644 internal/httputil/httputils_test.go diff --git a/contrib/config/polaris/go.sum b/contrib/config/polaris/go.sum index 78feefc14..6822a8623 100644 --- a/contrib/config/polaris/go.sum +++ b/contrib/config/polaris/go.sum @@ -227,8 +227,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polarismesh/polaris-go v1.3.0 h1:KZKX//ow4OPPoS5+s7h07ptprg+2AcNVGrN6WakC9QM= -github.com/polarismesh/polaris-go v1.3.0/go.mod h1:HsN0ierETIujHpmnnYJ3qkwQw4QGAECuHvBZTDaw1tI= +github.com/polarismesh/polaris-go v1.4.1 h1:3sWkFi4tE2thgs1BqokC89+jjmU4/Sxj1ciIeZE0xng= +github.com/polarismesh/polaris-go v1.4.1/go.mod h1:TjTxtDfw1e8n/e86UPgQ8thGZDo4oPkfmG+riiynTAA= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -583,8 +583,9 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/contrib/drivers/mssql/mssql_z_basic_test.go b/contrib/drivers/mssql/mssql_z_basic_test.go index f27a3095e..b4d26aa92 100644 --- a/contrib/drivers/mssql/mssql_z_basic_test.go +++ b/contrib/drivers/mssql/mssql_z_basic_test.go @@ -256,7 +256,6 @@ func Test_DB_Insert(t *testing.T) { t.Assert(one["PASSPORT"].String(), "t4") t.Assert(one["PASSWORD"].String(), "25d55ad283aa400af464c76d713c07ad") t.Assert(one["NICKNAME"].String(), "name_4") - t.Assert(one["CREATE_TIME"].GTime(), timeNow) // batch with Insert timeNow = gtime.Now() diff --git a/database/gdb/gdb_model_select.go b/database/gdb/gdb_model_select.go index e27407c44..c6f96c57c 100644 --- a/database/gdb/gdb_model_select.go +++ b/database/gdb/gdb_model_select.go @@ -97,7 +97,18 @@ func (m *Model) Array(fieldsAndWhere ...interface{}) ([]Value, error) { if err != nil { return nil, err } - return all.Array(), nil + var field string + if len(all) > 0 { + if internalData := m.db.GetCore().GetInternalCtxDataFromCtx(m.GetCtx()); internalData != nil { + field = internalData.FirstResultColumn + } else { + return nil, gerror.NewCode( + gcode.CodeInternalError, + `query array error: the internal context data is missing. there's internal issue should be fixed`, + ) + } + } + return all.Array(field), nil } // Struct retrieves one record from table and converts it into given struct. @@ -292,15 +303,15 @@ func (m *Model) Value(fieldsAndWhere ...interface{}) (Value, error) { } if len(all) > 0 { if internalData := m.db.GetCore().GetInternalCtxDataFromCtx(ctx); internalData != nil { - record := all[0] - if v, ok := record[internalData.FirstResultColumn]; ok { + if v, ok := all[0][internalData.FirstResultColumn]; ok { return v, nil } + } else { + return nil, gerror.NewCode( + gcode.CodeInternalError, + `query value error: the internal context data is missing. there's internal issue should be fixed`, + ) } - return nil, gerror.NewCode( - gcode.CodeInternalError, - `query value error: the internal context data is missing. there's internal issue should be fixed`, - ) } return nil, nil } @@ -322,15 +333,15 @@ func (m *Model) Count(where ...interface{}) (int, error) { } if len(all) > 0 { if internalData := m.db.GetCore().GetInternalCtxDataFromCtx(ctx); internalData != nil { - record := all[0] - if v, ok := record[internalData.FirstResultColumn]; ok { + if v, ok := all[0][internalData.FirstResultColumn]; ok { return v.Int(), nil } + } else { + return 0, gerror.NewCode( + gcode.CodeInternalError, + `query count error: the internal context data is missing. there's internal issue should be fixed`, + ) } - return 0, gerror.NewCode( - gcode.CodeInternalError, - `query count error: the internal context data is missing. there's internal issue should be fixed`, - ) } return 0, nil } diff --git a/example/go.mod b/example/go.mod index ed51c3b2c..6531242f8 100644 --- a/example/go.mod +++ b/example/go.mod @@ -16,7 +16,7 @@ require ( github.com/gogf/gf/contrib/trace/jaeger/v2 v2.4.0 github.com/gogf/gf/v2 v2.4.0 github.com/nacos-group/nacos-sdk-go v1.1.2 - github.com/polarismesh/polaris-go v1.3.0 + github.com/polarismesh/polaris-go v1.4.1 google.golang.org/grpc v1.49.0 google.golang.org/protobuf v1.28.1 k8s.io/client-go v0.25.2 diff --git a/example/go.sum b/example/go.sum index 07f96187c..9801f6951 100644 --- a/example/go.sum +++ b/example/go.sum @@ -440,8 +440,9 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polarismesh/polaris-go v1.3.0 h1:KZKX//ow4OPPoS5+s7h07ptprg+2AcNVGrN6WakC9QM= github.com/polarismesh/polaris-go v1.3.0/go.mod h1:HsN0ierETIujHpmnnYJ3qkwQw4QGAECuHvBZTDaw1tI= +github.com/polarismesh/polaris-go v1.4.1 h1:3sWkFi4tE2thgs1BqokC89+jjmU4/Sxj1ciIeZE0xng= +github.com/polarismesh/polaris-go v1.4.1/go.mod h1:TjTxtDfw1e8n/e86UPgQ8thGZDo4oPkfmG+riiynTAA= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= diff --git a/internal/httputil/httputils.go b/internal/httputil/httputils.go index 1c0631dec..5fc9bb6f8 100644 --- a/internal/httputil/httputils.go +++ b/internal/httputil/httputils.go @@ -12,6 +12,7 @@ import ( "strings" "github.com/gogf/gf/v2/encoding/gurl" + "github.com/gogf/gf/v2/internal/empty" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" ) @@ -55,6 +56,10 @@ func BuildParams(params interface{}, noUrlEncode ...bool) (encodedParamStr strin } s := "" for k, v := range m { + // Ignore nil attributes. + if empty.IsNil(v) { + continue + } if len(encodedParamStr) > 0 { encodedParamStr += "&" } diff --git a/internal/httputil/httputils_test.go b/internal/httputil/httputils_test.go new file mode 100644 index 000000000..b021d55b3 --- /dev/null +++ b/internal/httputil/httputils_test.go @@ -0,0 +1,38 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package httputil_test + +import ( + "testing" + + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/internal/httputil" + "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/text/gstr" +) + +func TestBuildParams(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + data := g.Map{ + "a": "1", + "b": "2", + } + params := httputil.BuildParams(data) + t.Assert(gstr.Contains(params, "a=1"), true) + t.Assert(gstr.Contains(params, "b=2"), true) + }) + gtest.C(t, func(t *gtest.T) { + data := g.Map{ + "a": "1", + "b": nil, + } + params := httputil.BuildParams(data) + t.Assert(gstr.Contains(params, "a=1"), true) + t.Assert(gstr.Contains(params, "b="), false) + t.Assert(gstr.Contains(params, "b"), false) + }) +} diff --git a/util/gconv/gconv_struct.go b/util/gconv/gconv_struct.go index d2c7a7d72..514c595b1 100644 --- a/util/gconv/gconv_struct.go +++ b/util/gconv/gconv_struct.go @@ -541,13 +541,28 @@ func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}, ma } } } else { - reflectArray = reflect.MakeSlice(structFieldValue.Type(), 1, 1) var ( elem reflect.Value - elemType = reflectArray.Index(0).Type() + elemType = structFieldValue.Type().Elem() elemTypeName = elemType.Name() converted bool ) + switch reflectValue.Kind() { + case reflect.String: + // Value is empty string. + if reflectValue.IsZero() { + var elemKind = elemType.Kind() + // Try to find the original type kind of the slice element. + if elemKind == reflect.Ptr { + elemKind = elemType.Elem().Kind() + } + switch elemKind { + case reflect.String: + // Empty string cannot be assigned to string slice. + return nil + } + } + } if elemTypeName == "" { elemTypeName = elemType.String() } @@ -572,6 +587,7 @@ func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}, ma // Before it sets the `elem` to array, do pointer converting if necessary. elem = elem.Addr() } + reflectArray = reflect.MakeSlice(structFieldValue.Type(), 1, 1) reflectArray.Index(0).Set(elem) } structFieldValue.Set(reflectArray) diff --git a/util/gconv/gconv_z_unit_slice_test.go b/util/gconv/gconv_z_unit_slice_test.go index e1afb2eed..8862bea73 100644 --- a/util/gconv/gconv_z_unit_slice_test.go +++ b/util/gconv/gconv_z_unit_slice_test.go @@ -414,3 +414,46 @@ func Test_Slice_Structs(t *testing.T) { t.Assert(users[1].Age, 20) }) } + +func Test_EmptyString_To_CustomType(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + type Status string + type Req struct { + Name string + Statuses []Status + Types []string + } + var ( + req *Req + data = g.Map{ + "Name": "john", + "Statuses": "", + "Types": "", + } + ) + err := gconv.Scan(data, &req) + t.AssertNil(err) + t.Assert(len(req.Statuses), 0) + t.Assert(len(req.Types), 0) + }) + gtest.C(t, func(t *gtest.T) { + type Status string + type Req struct { + Name string + Statuses []*Status + Types []string + } + var ( + req *Req + data = g.Map{ + "Name": "john", + "Statuses": "", + "Types": "", + } + ) + err := gconv.Scan(data, &req) + t.AssertNil(err) + t.Assert(len(req.Statuses), 0) + t.Assert(len(req.Types), 0) + }) +}