Skip to content

Commit 607f079

Browse files
authored
fix: cache value assertion panic if the cache adapter is not in-memory for soft time feature of package gdb; improve converting performance for gconv.Scan (#3351)
1 parent cab6b89 commit 607f079

16 files changed

+797
-709
lines changed

database/gdb/gdb.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
// You can obtain one at https://github.com/gogf/gf.
66

77
// Package gdb provides ORM features for popular relationship databases.
8+
//
9+
// TODO use context.Context as required parameter for all DB operations.
810
package gdb
911

1012
import (

database/gdb/gdb_model_cache.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"time"
1212

1313
"github.com/gogf/gf/v2/internal/intlog"
14-
"github.com/gogf/gf/v2/internal/json"
1514
)
1615

1716
// CacheOption is options for model cache control in query.
@@ -67,7 +66,6 @@ func (m *Model) getSelectResultFromCache(ctx context.Context, sql string, args .
6766
return
6867
}
6968
var (
70-
ok bool
7169
cacheItem *selectCacheItem
7270
cacheKey = m.makeSelectCacheKey(sql, args...)
7371
cacheObj = m.db.GetCache()
@@ -82,12 +80,7 @@ func (m *Model) getSelectResultFromCache(ctx context.Context, sql string, args .
8280
}
8381
}()
8482
if v, _ := cacheObj.Get(ctx, cacheKey); !v.IsNil() {
85-
if cacheItem, ok = v.Val().(*selectCacheItem); ok {
86-
// In-memory cache.
87-
return cacheItem.Result, nil
88-
}
89-
// Other cache, it needs conversion.
90-
if err = json.UnmarshalUseNumber(v.Bytes(), &cacheItem); err != nil {
83+
if err = v.Scan(&cacheItem); err != nil {
9184
return nil, err
9285
}
9386
return cacheItem.Result, nil

database/gdb/gdb_model_soft_time.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,10 @@ func (m *softTimeMaintainer) getSoftFieldNameAndType(
219219
intlog.Error(ctx, err)
220220
}
221221
if result != nil {
222-
var cacheItem = result.Val().(getSoftFieldNameAndTypeCacheItem)
222+
var cacheItem getSoftFieldNameAndTypeCacheItem
223+
if err = result.Scan(&cacheItem); err != nil {
224+
return "", ""
225+
}
223226
fieldName = cacheItem.FieldName
224227
fieldType = cacheItem.FieldType
225228
}

util/gconv/gconv_maptomap.go

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,13 @@ import (
1111

1212
"github.com/gogf/gf/v2/errors/gcode"
1313
"github.com/gogf/gf/v2/errors/gerror"
14-
"github.com/gogf/gf/v2/internal/json"
1514
)
1615

1716
// MapToMap converts any map type variable `params` to another map type variable `pointer`
1817
// using reflect.
1918
// See doMapToMap.
2019
func MapToMap(params interface{}, pointer interface{}, mapping ...map[string]string) error {
21-
return doMapToMap(params, pointer, mapping...)
20+
return Scan(params, pointer, mapping...)
2221
}
2322

2423
// doMapToMap converts any map type variable `params` to another map type variable `pointer`.
@@ -32,29 +31,6 @@ func MapToMap(params interface{}, pointer interface{}, mapping ...map[string]str
3231
// The optional parameter `mapping` is used for struct attribute to map key mapping, which makes
3332
// sense only if the items of original map `params` is type struct.
3433
func doMapToMap(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
35-
// If given `params` is JSON, it then uses json.Unmarshal doing the converting.
36-
switch r := params.(type) {
37-
case []byte:
38-
if json.Valid(r) {
39-
if rv, ok := pointer.(reflect.Value); ok {
40-
if rv.Kind() == reflect.Ptr {
41-
return json.UnmarshalUseNumber(r, rv.Interface())
42-
}
43-
} else {
44-
return json.UnmarshalUseNumber(r, pointer)
45-
}
46-
}
47-
case string:
48-
if paramsBytes := []byte(r); json.Valid(paramsBytes) {
49-
if rv, ok := pointer.(reflect.Value); ok {
50-
if rv.Kind() == reflect.Ptr {
51-
return json.UnmarshalUseNumber(paramsBytes, rv.Interface())
52-
}
53-
} else {
54-
return json.UnmarshalUseNumber(paramsBytes, pointer)
55-
}
56-
}
57-
}
5834
var (
5935
paramsRv reflect.Value
6036
paramsKind reflect.Kind
@@ -92,7 +68,11 @@ func doMapToMap(params interface{}, pointer interface{}, mapping ...map[string]s
9268
pointerKind = pointerRv.Kind()
9369
}
9470
if pointerKind != reflect.Map {
95-
return gerror.NewCodef(gcode.CodeInvalidParameter, "pointer should be type of *map, but got:%s", pointerKind)
71+
return gerror.NewCodef(
72+
gcode.CodeInvalidParameter,
73+
`destination pointer should be type of *map, but got: %s`,
74+
pointerKind,
75+
)
9676
}
9777
defer func() {
9878
// Catch the panic, especially the reflection operation panics.
@@ -119,7 +99,9 @@ func doMapToMap(params interface{}, pointer interface{}, mapping ...map[string]s
11999
mapValue := reflect.New(pointerValueType).Elem()
120100
switch pointerValueKind {
121101
case reflect.Map, reflect.Struct:
122-
if err = doStruct(paramsRv.MapIndex(key).Interface(), mapValue, keyToAttributeNameMapping, ""); err != nil {
102+
if err = doStruct(
103+
paramsRv.MapIndex(key).Interface(), mapValue, keyToAttributeNameMapping, "",
104+
); err != nil {
123105
return err
124106
}
125107
default:

util/gconv/gconv_maptomaps.go

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,12 @@ import (
1111

1212
"github.com/gogf/gf/v2/errors/gcode"
1313
"github.com/gogf/gf/v2/errors/gerror"
14-
"github.com/gogf/gf/v2/internal/json"
1514
)
1615

1716
// MapToMaps converts any slice type variable `params` to another map slice type variable `pointer`.
1817
// See doMapToMaps.
1918
func MapToMaps(params interface{}, pointer interface{}, mapping ...map[string]string) error {
20-
return doMapToMaps(params, pointer, mapping...)
19+
return Scan(params, pointer, mapping...)
2120
}
2221

2322
// doMapToMaps converts any map type variable `params` to another map slice variable `pointer`.
@@ -29,29 +28,6 @@ func MapToMaps(params interface{}, pointer interface{}, mapping ...map[string]st
2928
// The optional parameter `mapping` is used for struct attribute to map key mapping, which makes
3029
// sense only if the item of `params` is type struct.
3130
func doMapToMaps(params interface{}, pointer interface{}, paramKeyToAttrMap ...map[string]string) (err error) {
32-
// If given `params` is JSON, it then uses json.Unmarshal doing the converting.
33-
switch r := params.(type) {
34-
case []byte:
35-
if json.Valid(r) {
36-
if rv, ok := pointer.(reflect.Value); ok {
37-
if rv.Kind() == reflect.Ptr {
38-
return json.UnmarshalUseNumber(r, rv.Interface())
39-
}
40-
} else {
41-
return json.UnmarshalUseNumber(r, pointer)
42-
}
43-
}
44-
case string:
45-
if paramsBytes := []byte(r); json.Valid(paramsBytes) {
46-
if rv, ok := pointer.(reflect.Value); ok {
47-
if rv.Kind() == reflect.Ptr {
48-
return json.UnmarshalUseNumber(paramsBytes, rv.Interface())
49-
}
50-
} else {
51-
return json.UnmarshalUseNumber(paramsBytes, pointer)
52-
}
53-
}
54-
}
5531
// Params and its element type check.
5632
var (
5733
paramsRv reflect.Value
@@ -68,7 +44,10 @@ func doMapToMaps(params interface{}, pointer interface{}, paramKeyToAttrMap ...m
6844
paramsKind = paramsRv.Kind()
6945
}
7046
if paramsKind != reflect.Array && paramsKind != reflect.Slice {
71-
return gerror.NewCode(gcode.CodeInvalidParameter, "params should be type of slice, eg: []map/[]*map/[]struct/[]*struct")
47+
return gerror.NewCode(
48+
gcode.CodeInvalidParameter,
49+
"params should be type of slice, example: []map/[]*map/[]struct/[]*struct",
50+
)
7251
}
7352
var (
7453
paramsElem = paramsRv.Type().Elem()
@@ -78,8 +57,14 @@ func doMapToMaps(params interface{}, pointer interface{}, paramKeyToAttrMap ...m
7857
paramsElem = paramsElem.Elem()
7958
paramsElemKind = paramsElem.Kind()
8059
}
81-
if paramsElemKind != reflect.Map && paramsElemKind != reflect.Struct && paramsElemKind != reflect.Interface {
82-
return gerror.NewCodef(gcode.CodeInvalidParameter, "params element should be type of map/*map/struct/*struct, but got: %s", paramsElemKind)
60+
if paramsElemKind != reflect.Map &&
61+
paramsElemKind != reflect.Struct &&
62+
paramsElemKind != reflect.Interface {
63+
return gerror.NewCodef(
64+
gcode.CodeInvalidParameter,
65+
"params element should be type of map/*map/struct/*struct, but got: %s",
66+
paramsElemKind,
67+
)
8368
}
8469
// Empty slice, no need continue.
8570
if paramsRv.Len() == 0 {

0 commit comments

Comments
 (0)