Skip to content

Commit f503347

Browse files
authored
feat: Add several statistical functions (#47)
1 parent e4ec28f commit f503347

File tree

5 files changed

+136
-41
lines changed

5 files changed

+136
-41
lines changed

constants/keyword.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,10 @@ const (
3232
Between = "BETWEEN"
3333
Desc = "DESC"
3434
Asc = "ASC"
35+
As = "AS"
36+
SUM = "SUM"
37+
AVG = "AVG"
38+
MAX = "MAX"
39+
MIN = "MIN"
40+
COUNT = "COUNT"
3541
)

gplus/cache.go

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -31,30 +31,43 @@ var columnNameCache sync.Map
3131
var modelInstanceCache sync.Map
3232

3333
// Cache 缓存实体对象所有的字段名
34-
func Cache(model any, namingStrategy ...schema.Namer) {
35-
valueOf := reflect.ValueOf(model).Elem()
36-
typeOf := reflect.TypeOf(model).Elem()
34+
func Cache(models ...any) {
35+
for _, model := range models {
36+
valueOf := reflect.ValueOf(model).Elem()
37+
typeOf := reflect.TypeOf(model).Elem()
3738

38-
for i := 0; i < valueOf.NumField(); i++ {
39-
field := typeOf.Field(i)
40-
// 如果当前实体嵌入了其他实体,同样需要缓存它的字段名
41-
if field.Anonymous {
42-
// 如果存在多重嵌套,通过递归方式获取他们的字段名
43-
subFieldMap := getSubFieldColumnNameMap(valueOf, field)
44-
for key, value := range subFieldMap {
45-
columnNameCache.Store(key, value)
39+
for i := 0; i < valueOf.NumField(); i++ {
40+
field := typeOf.Field(i)
41+
// 如果当前实体嵌入了其他实体,同样需要缓存它的字段名
42+
if field.Anonymous {
43+
// 如果存在多重嵌套,通过递归方式获取他们的字段名
44+
subFieldMap := getSubFieldColumnNameMap(valueOf, field)
45+
for key, value := range subFieldMap {
46+
columnNameCache.Store(key, value)
47+
}
48+
} else {
49+
// 获取对象字段指针值
50+
pointer := valueOf.Field(i).Addr().Pointer()
51+
name := parseColumnName(field)
52+
columnNameCache.Store(pointer, name)
4653
}
47-
} else {
48-
// 获取对象字段指针值
49-
pointer := valueOf.Field(i).Addr().Pointer()
50-
name := parseColumnName(field, namingStrategy...)
51-
columnNameCache.Store(pointer, name)
5254
}
55+
56+
// 缓存对象
57+
modelTypeStr := reflect.TypeOf(model).Elem().String()
58+
modelInstanceCache.Store(modelTypeStr, model)
5359
}
60+
}
5461

55-
// 缓存对象
56-
modelTypeStr := reflect.TypeOf(model).Elem().String()
57-
modelInstanceCache.Store(modelTypeStr, model)
62+
// GetModel 获取
63+
func GetModel[T any]() *T {
64+
modelTypeStr := reflect.TypeOf((*T)(nil)).Elem().String()
65+
if model, ok := modelInstanceCache.Load(modelTypeStr); ok {
66+
return model.(*T)
67+
}
68+
t := new(T)
69+
Cache(t)
70+
return t
5871
}
5972

6073
// 递归获取嵌套字段名
@@ -83,17 +96,11 @@ func getSubFieldColumnNameMap(valueOf reflect.Value, field reflect.StructField)
8396
}
8497

8598
// 获取字段名称
86-
func parseColumnName(field reflect.StructField, namingStrategy ...schema.Namer) string {
99+
func parseColumnName(field reflect.StructField) string {
87100
tagSetting := schema.ParseTagSetting(field.Tag.Get("gorm"), ";")
88101
name, ok := tagSetting["COLUMN"]
89102
if ok {
90103
return name
91104
}
92-
93-
if len(namingStrategy) > 0 {
94-
return namingStrategy[0].ColumnName("", field.Name)
95-
}
96-
97-
strategy := schema.NamingStrategy{}
98-
return strategy.ColumnName("", field.Name)
105+
return globalDb.Config.NamingStrategy.ColumnName("", field.Name)
99106
}

gplus/dao.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ type Dao[T any] struct{}
4545

4646
func (dao Dao[T]) NewQuery() (*QueryCond[T], *T) {
4747
q := &QueryCond[T]{}
48-
return q, q.buildColumnNameMap()
48+
return q, nil
4949
}
5050

5151
func NewPage[T any](current, size int) *Page[T] {

gplus/function.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Licensed to the AcmeStack under one or more contributor license
3+
* agreements. See the NOTICE file distributed with this work for
4+
* additional information regarding copyright ownership.
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package gplus
19+
20+
import "github.com/acmestack/gorm-plus/constants"
21+
22+
func As(columnName any, asName any) string {
23+
return getColumnName(columnName) + " " + constants.As + " " + getColumnName(asName)
24+
}
25+
26+
func SumAs(columnName any, asName any) string {
27+
return buildFunction(constants.SUM, getColumnName(columnName), getColumnName(asName))
28+
}
29+
30+
func AvgAs(columnName any, asName any) string {
31+
return buildFunction(constants.AVG, getColumnName(columnName), getColumnName(asName))
32+
}
33+
34+
func MaxAs(columnName any, asName any) string {
35+
return buildFunction(constants.MAX, getColumnName(columnName), getColumnName(asName))
36+
}
37+
38+
func MinAs(columnName any, asName any) string {
39+
return buildFunction(constants.MIN, getColumnName(columnName), getColumnName(asName))
40+
}
41+
42+
func CountAs(columnName any, asName any) string {
43+
return buildFunction(constants.COUNT, getColumnName(columnName), getColumnName(asName))
44+
}
45+
46+
func buildFunction(function string, columnNameStr string, asNameStr string) string {
47+
columnNameStr = function + constants.LeftBracket + columnNameStr + constants.RightBracket +
48+
" " + constants.As + " " + asNameStr
49+
return columnNameStr
50+
}

gplus/query.go

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,57 @@ type QueryCond[T any] struct {
4545
// NewQuery 构建查询条件
4646
func NewQuery[T any]() (*QueryCond[T], *T) {
4747
q := &QueryCond[T]{}
48-
return q, q.buildColumnNameMap()
48+
49+
modelTypeStr := reflect.TypeOf((*T)(nil)).Elem().String()
50+
if model, ok := modelInstanceCache.Load(modelTypeStr); ok {
51+
return q, model.(*T)
52+
}
53+
m := new(T)
54+
Cache(m)
55+
return q, m
56+
}
57+
58+
// NewQueryModel 构建查询条件
59+
func NewQueryModel[T any, R any]() (*QueryCond[T], *T, *R) {
60+
q := &QueryCond[T]{}
61+
var t *T
62+
var r *R
63+
entityTypeStr := reflect.TypeOf((*T)(nil)).Elem().String()
64+
if model, ok := modelInstanceCache.Load(entityTypeStr); ok {
65+
t = model.(*T)
66+
}
67+
68+
modelTypeStr := reflect.TypeOf((*R)(nil)).Elem().String()
69+
if model, ok := modelInstanceCache.Load(modelTypeStr); ok {
70+
r = model.(*R)
71+
}
72+
73+
if t == nil {
74+
t = new(T)
75+
Cache(t)
76+
}
77+
78+
if r == nil {
79+
r = new(R)
80+
Cache(r)
81+
}
82+
83+
return q, t, r
4984
}
5085

5186
// NewQueryMap 构建Map查询条件
5287
func NewQueryMap[T any]() (*QueryCond[T], *T) {
5388
q := &QueryCond[T]{}
89+
90+
modelTypeStr := reflect.TypeOf((*T)(nil)).Elem().String()
91+
if model, ok := modelInstanceCache.Load(modelTypeStr); ok {
92+
return q, model.(*T)
93+
}
94+
m := new(T)
95+
Cache(m)
96+
5497
q.ConditionMap = make(map[any]any)
55-
return q, q.buildColumnNameMap()
98+
return q, m
5699
}
57100

58101
// Eq 等于 =
@@ -297,17 +340,6 @@ func (q *QueryCond[T]) buildOrder(orderType string, columns ...string) {
297340
}
298341
}
299342

300-
func (q *QueryCond[T]) buildColumnNameMap() *T {
301-
// first try to load from cache
302-
modelTypeStr := reflect.TypeOf((*T)(nil)).Elem().String()
303-
if model, ok := modelInstanceCache.Load(modelTypeStr); ok {
304-
return model.(*T)
305-
}
306-
model := new(T)
307-
Cache(model, globalDb.Config.NamingStrategy)
308-
return model
309-
}
310-
311343
func getColumnName(v any) string {
312344
var columnName string
313345
valueOf := reflect.ValueOf(v)

0 commit comments

Comments
 (0)