Skip to content

Commit 7b1fd2b

Browse files
分库分表:结果集处理——聚合函数(不含 Group By 子句) (#187)
close #179
1 parent 96d0b3c commit 7b1fd2b

File tree

16 files changed

+2091
-9
lines changed

16 files changed

+2091
-9
lines changed

.CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
- [eorm: Datasource 抽象](https://github.com/ecodeclub/eorm/pull/167)
2323
- [eorm: 分库分表: hash、shadow_hash算法不符合预期](https://github.com/ecodeclub/eorm/pull/174)
2424
- [eorm: 分库分表: Merger分页实现](https://github.com/ecodeclub/eorm/pull/175)
25-
- [eorm: BasicTypeValue重命名](https://github.com/ecodeclub/eorm/pull/177)
25+
- [eorm: 分库分表: 结果集处理--聚合函数(不含GroupBy子句)](https://github.com/ecodeclub/eorm/pull/187)
2626
- [eorm: 分库分表: 范围查询支持](https://github.com/ecodeclub/eorm/pull/178)
2727
- [eorm: 修复单条查询时连接泄露问题](https://github.com/ecodeclub/eorm/pull/188)
2828

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
// Copyright 2021 ecodeclub
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package aggregator
16+
17+
import (
18+
"reflect"
19+
20+
"github.com/ecodeclub/eorm/internal/merger/internal/errs"
21+
)
22+
23+
// AVG 用于求平均值,通过sum/count求得。
24+
// AVG 我们并不能预期在不同的数据库上,精度会不会损失,以及损失的话会有多少的损失。这很大程度上跟数据库类型,数据库驱动实现都有关
25+
type AVG struct {
26+
sumColumnInfo ColumnInfo
27+
countColumnInfo ColumnInfo
28+
avgName string
29+
}
30+
31+
// NewAVG sumInfo是sum的信息,countInfo是count的信息,avgName用于Column方法
32+
func NewAVG(sumInfo ColumnInfo, countInfo ColumnInfo, avgName string) *AVG {
33+
return &AVG{
34+
sumColumnInfo: sumInfo,
35+
countColumnInfo: countInfo,
36+
avgName: avgName,
37+
}
38+
}
39+
40+
func (a *AVG) Aggregate(cols [][]any) (any, error) {
41+
// cols[0] 代表第一个sql.Rows,用于确定avgFunc
42+
avgFunc, err := a.findAvgFunc(cols[0])
43+
if err != nil {
44+
return nil, err
45+
}
46+
return avgFunc(cols, a.sumColumnInfo.Index, a.countColumnInfo.Index)
47+
}
48+
49+
func (a *AVG) findAvgFunc(col []any) (func([][]any, int, int) (float64, error), error) {
50+
sumIndex := a.sumColumnInfo.Index
51+
countIndex := a.countColumnInfo.Index
52+
if sumIndex >= len(col) || sumIndex < 0 || countIndex >= len(col) || countIndex < 0 {
53+
return nil, errs.ErrMergerInvalidAggregateColumnIndex
54+
}
55+
sumKind := reflect.TypeOf(col[sumIndex]).Kind()
56+
countKind := reflect.TypeOf(col[countIndex]).Kind()
57+
val, ok := avgAggregateFuncMapping[[2]reflect.Kind{sumKind, countKind}]
58+
if !ok {
59+
return nil, errs.ErrMergerAggregateFuncNotFound
60+
}
61+
return val, nil
62+
}
63+
64+
func (a *AVG) ColumnName() string {
65+
return a.avgName
66+
}
67+
68+
// avgAggregator cols就是上面Aggregate的入参cols可以参Aggregate的描述
69+
func avgAggregator[S AggregateElement, C AggregateElement](cols [][]any, sumIndex int, countIndex int) (float64, error) {
70+
var sum S
71+
var count C
72+
for _, col := range cols {
73+
sum += col[sumIndex].(S)
74+
count += col[countIndex].(C)
75+
}
76+
val := float64(sum) / float64(count)
77+
return val, nil
78+
79+
}
80+
81+
var avgAggregateFuncMapping = map[[2]reflect.Kind]func([][]any, int, int) (float64, error){
82+
[2]reflect.Kind{reflect.Int, reflect.Int}: avgAggregator[int, int],
83+
[2]reflect.Kind{reflect.Int, reflect.Int8}: avgAggregator[int, int8],
84+
[2]reflect.Kind{reflect.Int, reflect.Int16}: avgAggregator[int, int16],
85+
[2]reflect.Kind{reflect.Int, reflect.Int32}: avgAggregator[int, int32],
86+
[2]reflect.Kind{reflect.Int, reflect.Int64}: avgAggregator[int, int64],
87+
[2]reflect.Kind{reflect.Int, reflect.Uint}: avgAggregator[int, uint],
88+
[2]reflect.Kind{reflect.Int, reflect.Uint8}: avgAggregator[int, uint8],
89+
[2]reflect.Kind{reflect.Int, reflect.Uint16}: avgAggregator[int, uint16],
90+
[2]reflect.Kind{reflect.Int, reflect.Uint32}: avgAggregator[int, uint32],
91+
[2]reflect.Kind{reflect.Int, reflect.Uint64}: avgAggregator[int, uint64],
92+
[2]reflect.Kind{reflect.Int, reflect.Float32}: avgAggregator[int, float32],
93+
[2]reflect.Kind{reflect.Int, reflect.Float64}: avgAggregator[int, float64],
94+
95+
[2]reflect.Kind{reflect.Int8, reflect.Int}: avgAggregator[int8, int],
96+
[2]reflect.Kind{reflect.Int8, reflect.Int8}: avgAggregator[int8, int8],
97+
[2]reflect.Kind{reflect.Int8, reflect.Int16}: avgAggregator[int8, int16],
98+
[2]reflect.Kind{reflect.Int8, reflect.Int32}: avgAggregator[int8, int32],
99+
[2]reflect.Kind{reflect.Int8, reflect.Int64}: avgAggregator[int8, int64],
100+
[2]reflect.Kind{reflect.Int8, reflect.Uint}: avgAggregator[int8, uint],
101+
[2]reflect.Kind{reflect.Int8, reflect.Uint8}: avgAggregator[int8, uint8],
102+
[2]reflect.Kind{reflect.Int8, reflect.Uint16}: avgAggregator[int8, uint16],
103+
[2]reflect.Kind{reflect.Int8, reflect.Uint32}: avgAggregator[int8, uint32],
104+
[2]reflect.Kind{reflect.Int8, reflect.Uint64}: avgAggregator[int8, uint64],
105+
[2]reflect.Kind{reflect.Int8, reflect.Float32}: avgAggregator[int8, float32],
106+
[2]reflect.Kind{reflect.Int8, reflect.Float64}: avgAggregator[int8, float64],
107+
108+
[2]reflect.Kind{reflect.Int16, reflect.Int}: avgAggregator[int16, int],
109+
[2]reflect.Kind{reflect.Int16, reflect.Int8}: avgAggregator[int16, int8],
110+
[2]reflect.Kind{reflect.Int16, reflect.Int16}: avgAggregator[int16, int16],
111+
[2]reflect.Kind{reflect.Int16, reflect.Int32}: avgAggregator[int16, int32],
112+
[2]reflect.Kind{reflect.Int16, reflect.Int64}: avgAggregator[int16, int64],
113+
[2]reflect.Kind{reflect.Int16, reflect.Uint}: avgAggregator[int16, uint],
114+
[2]reflect.Kind{reflect.Int16, reflect.Uint8}: avgAggregator[int16, uint8],
115+
[2]reflect.Kind{reflect.Int16, reflect.Uint16}: avgAggregator[int16, uint16],
116+
[2]reflect.Kind{reflect.Int16, reflect.Uint32}: avgAggregator[int16, uint32],
117+
[2]reflect.Kind{reflect.Int16, reflect.Uint64}: avgAggregator[int16, uint64],
118+
[2]reflect.Kind{reflect.Int16, reflect.Float32}: avgAggregator[int16, float32],
119+
[2]reflect.Kind{reflect.Int16, reflect.Float64}: avgAggregator[int16, float64],
120+
121+
[2]reflect.Kind{reflect.Int32, reflect.Int}: avgAggregator[int16, int],
122+
[2]reflect.Kind{reflect.Int32, reflect.Int8}: avgAggregator[int16, int8],
123+
[2]reflect.Kind{reflect.Int32, reflect.Int16}: avgAggregator[int16, int16],
124+
[2]reflect.Kind{reflect.Int32, reflect.Int32}: avgAggregator[int16, int32],
125+
[2]reflect.Kind{reflect.Int32, reflect.Int64}: avgAggregator[int16, int64],
126+
[2]reflect.Kind{reflect.Int32, reflect.Uint}: avgAggregator[int16, uint],
127+
[2]reflect.Kind{reflect.Int32, reflect.Uint8}: avgAggregator[int16, uint8],
128+
[2]reflect.Kind{reflect.Int32, reflect.Uint16}: avgAggregator[int16, uint16],
129+
[2]reflect.Kind{reflect.Int32, reflect.Uint32}: avgAggregator[int16, uint32],
130+
[2]reflect.Kind{reflect.Int32, reflect.Uint64}: avgAggregator[int16, uint64],
131+
[2]reflect.Kind{reflect.Int32, reflect.Float32}: avgAggregator[int16, float32],
132+
[2]reflect.Kind{reflect.Int32, reflect.Float64}: avgAggregator[int16, float64],
133+
134+
[2]reflect.Kind{reflect.Int64, reflect.Int}: avgAggregator[int64, int],
135+
[2]reflect.Kind{reflect.Int64, reflect.Int8}: avgAggregator[int64, int8],
136+
[2]reflect.Kind{reflect.Int64, reflect.Int16}: avgAggregator[int64, int16],
137+
[2]reflect.Kind{reflect.Int64, reflect.Int32}: avgAggregator[int64, int32],
138+
[2]reflect.Kind{reflect.Int64, reflect.Int64}: avgAggregator[int64, int64],
139+
[2]reflect.Kind{reflect.Int64, reflect.Uint}: avgAggregator[int64, uint],
140+
[2]reflect.Kind{reflect.Int64, reflect.Uint8}: avgAggregator[int64, uint8],
141+
[2]reflect.Kind{reflect.Int64, reflect.Uint16}: avgAggregator[int64, uint16],
142+
[2]reflect.Kind{reflect.Int64, reflect.Uint32}: avgAggregator[int64, uint32],
143+
[2]reflect.Kind{reflect.Int64, reflect.Uint64}: avgAggregator[int64, uint64],
144+
[2]reflect.Kind{reflect.Int64, reflect.Float32}: avgAggregator[int64, float32],
145+
[2]reflect.Kind{reflect.Int64, reflect.Float64}: avgAggregator[int64, float64],
146+
147+
[2]reflect.Kind{reflect.Uint, reflect.Int}: avgAggregator[uint, int],
148+
[2]reflect.Kind{reflect.Uint, reflect.Int8}: avgAggregator[uint, int8],
149+
[2]reflect.Kind{reflect.Uint, reflect.Int16}: avgAggregator[uint, int16],
150+
[2]reflect.Kind{reflect.Uint, reflect.Int32}: avgAggregator[uint, int32],
151+
[2]reflect.Kind{reflect.Uint, reflect.Int64}: avgAggregator[uint, int64],
152+
[2]reflect.Kind{reflect.Uint, reflect.Uint}: avgAggregator[uint, uint],
153+
[2]reflect.Kind{reflect.Uint, reflect.Uint8}: avgAggregator[uint, uint8],
154+
[2]reflect.Kind{reflect.Uint, reflect.Uint16}: avgAggregator[uint, uint16],
155+
[2]reflect.Kind{reflect.Uint, reflect.Uint32}: avgAggregator[uint, uint32],
156+
[2]reflect.Kind{reflect.Uint, reflect.Uint64}: avgAggregator[uint, uint64],
157+
[2]reflect.Kind{reflect.Uint, reflect.Float32}: avgAggregator[uint, float32],
158+
[2]reflect.Kind{reflect.Uint, reflect.Float64}: avgAggregator[uint, float64],
159+
160+
[2]reflect.Kind{reflect.Uint8, reflect.Int}: avgAggregator[uint8, int],
161+
[2]reflect.Kind{reflect.Uint8, reflect.Int8}: avgAggregator[uint8, int8],
162+
[2]reflect.Kind{reflect.Uint8, reflect.Int16}: avgAggregator[uint8, int16],
163+
[2]reflect.Kind{reflect.Uint8, reflect.Int32}: avgAggregator[uint8, int32],
164+
[2]reflect.Kind{reflect.Uint8, reflect.Int64}: avgAggregator[uint8, int64],
165+
[2]reflect.Kind{reflect.Uint8, reflect.Uint}: avgAggregator[uint8, uint],
166+
[2]reflect.Kind{reflect.Uint8, reflect.Uint8}: avgAggregator[uint8, uint8],
167+
[2]reflect.Kind{reflect.Uint8, reflect.Uint16}: avgAggregator[uint8, uint16],
168+
[2]reflect.Kind{reflect.Uint8, reflect.Uint32}: avgAggregator[uint8, uint32],
169+
[2]reflect.Kind{reflect.Uint8, reflect.Uint64}: avgAggregator[uint8, uint64],
170+
[2]reflect.Kind{reflect.Uint8, reflect.Float32}: avgAggregator[uint8, float32],
171+
[2]reflect.Kind{reflect.Uint8, reflect.Float64}: avgAggregator[uint8, float64],
172+
173+
[2]reflect.Kind{reflect.Uint16, reflect.Int}: avgAggregator[uint16, int],
174+
[2]reflect.Kind{reflect.Uint16, reflect.Int8}: avgAggregator[uint16, int8],
175+
[2]reflect.Kind{reflect.Uint16, reflect.Int16}: avgAggregator[uint16, int16],
176+
[2]reflect.Kind{reflect.Uint16, reflect.Int32}: avgAggregator[uint16, int32],
177+
[2]reflect.Kind{reflect.Uint16, reflect.Int64}: avgAggregator[uint16, int64],
178+
[2]reflect.Kind{reflect.Uint16, reflect.Uint}: avgAggregator[uint16, uint],
179+
[2]reflect.Kind{reflect.Uint16, reflect.Uint8}: avgAggregator[uint16, uint8],
180+
[2]reflect.Kind{reflect.Uint16, reflect.Uint16}: avgAggregator[uint16, uint16],
181+
[2]reflect.Kind{reflect.Uint16, reflect.Uint32}: avgAggregator[uint16, uint32],
182+
[2]reflect.Kind{reflect.Uint16, reflect.Uint64}: avgAggregator[uint16, uint64],
183+
[2]reflect.Kind{reflect.Uint16, reflect.Float32}: avgAggregator[uint16, float32],
184+
[2]reflect.Kind{reflect.Uint16, reflect.Float64}: avgAggregator[uint16, float64],
185+
186+
[2]reflect.Kind{reflect.Uint32, reflect.Int}: avgAggregator[uint32, int],
187+
[2]reflect.Kind{reflect.Uint32, reflect.Int8}: avgAggregator[uint32, int8],
188+
[2]reflect.Kind{reflect.Uint32, reflect.Int16}: avgAggregator[uint32, int16],
189+
[2]reflect.Kind{reflect.Uint32, reflect.Int32}: avgAggregator[uint32, int32],
190+
[2]reflect.Kind{reflect.Uint32, reflect.Int64}: avgAggregator[uint32, int64],
191+
[2]reflect.Kind{reflect.Uint32, reflect.Uint}: avgAggregator[uint32, uint],
192+
[2]reflect.Kind{reflect.Uint32, reflect.Uint8}: avgAggregator[uint32, uint8],
193+
[2]reflect.Kind{reflect.Uint32, reflect.Uint16}: avgAggregator[uint32, uint16],
194+
[2]reflect.Kind{reflect.Uint32, reflect.Uint32}: avgAggregator[uint32, uint32],
195+
[2]reflect.Kind{reflect.Uint32, reflect.Uint64}: avgAggregator[uint32, uint64],
196+
[2]reflect.Kind{reflect.Uint32, reflect.Float32}: avgAggregator[uint32, float32],
197+
[2]reflect.Kind{reflect.Uint32, reflect.Float64}: avgAggregator[uint32, float64],
198+
199+
[2]reflect.Kind{reflect.Uint64, reflect.Int}: avgAggregator[uint64, int],
200+
[2]reflect.Kind{reflect.Uint64, reflect.Int8}: avgAggregator[uint64, int8],
201+
[2]reflect.Kind{reflect.Uint64, reflect.Int16}: avgAggregator[uint64, int16],
202+
[2]reflect.Kind{reflect.Uint64, reflect.Int32}: avgAggregator[uint64, int32],
203+
[2]reflect.Kind{reflect.Uint64, reflect.Int64}: avgAggregator[uint64, int64],
204+
[2]reflect.Kind{reflect.Uint64, reflect.Uint}: avgAggregator[uint64, uint],
205+
[2]reflect.Kind{reflect.Uint64, reflect.Uint8}: avgAggregator[uint64, uint8],
206+
[2]reflect.Kind{reflect.Uint64, reflect.Uint16}: avgAggregator[uint64, uint16],
207+
[2]reflect.Kind{reflect.Uint64, reflect.Uint32}: avgAggregator[uint64, uint32],
208+
[2]reflect.Kind{reflect.Uint64, reflect.Uint64}: avgAggregator[uint64, uint64],
209+
[2]reflect.Kind{reflect.Uint64, reflect.Float32}: avgAggregator[uint64, float32],
210+
[2]reflect.Kind{reflect.Uint64, reflect.Float64}: avgAggregator[uint64, float64],
211+
212+
[2]reflect.Kind{reflect.Float32, reflect.Int}: avgAggregator[float32, int],
213+
[2]reflect.Kind{reflect.Float32, reflect.Int8}: avgAggregator[float32, int8],
214+
[2]reflect.Kind{reflect.Float32, reflect.Int16}: avgAggregator[float32, int16],
215+
[2]reflect.Kind{reflect.Float32, reflect.Int32}: avgAggregator[float32, int32],
216+
[2]reflect.Kind{reflect.Float32, reflect.Int64}: avgAggregator[float32, int64],
217+
[2]reflect.Kind{reflect.Float32, reflect.Uint}: avgAggregator[float32, uint],
218+
[2]reflect.Kind{reflect.Float32, reflect.Uint8}: avgAggregator[float32, uint8],
219+
[2]reflect.Kind{reflect.Float32, reflect.Uint16}: avgAggregator[float32, uint16],
220+
[2]reflect.Kind{reflect.Float32, reflect.Uint32}: avgAggregator[float32, uint32],
221+
[2]reflect.Kind{reflect.Float32, reflect.Uint64}: avgAggregator[float32, uint64],
222+
[2]reflect.Kind{reflect.Float32, reflect.Float32}: avgAggregator[float32, float32],
223+
[2]reflect.Kind{reflect.Float32, reflect.Float64}: avgAggregator[float32, float64],
224+
225+
[2]reflect.Kind{reflect.Float64, reflect.Int}: avgAggregator[float64, int],
226+
[2]reflect.Kind{reflect.Float64, reflect.Int8}: avgAggregator[float64, int8],
227+
[2]reflect.Kind{reflect.Float64, reflect.Int16}: avgAggregator[float64, int16],
228+
[2]reflect.Kind{reflect.Float64, reflect.Int32}: avgAggregator[float64, int32],
229+
[2]reflect.Kind{reflect.Float64, reflect.Int64}: avgAggregator[float64, int64],
230+
[2]reflect.Kind{reflect.Float64, reflect.Uint}: avgAggregator[float64, uint],
231+
[2]reflect.Kind{reflect.Float64, reflect.Uint8}: avgAggregator[float64, uint8],
232+
[2]reflect.Kind{reflect.Float64, reflect.Uint16}: avgAggregator[float64, uint16],
233+
[2]reflect.Kind{reflect.Float64, reflect.Uint32}: avgAggregator[float64, uint32],
234+
[2]reflect.Kind{reflect.Float64, reflect.Uint64}: avgAggregator[float64, uint64],
235+
[2]reflect.Kind{reflect.Float64, reflect.Float32}: avgAggregator[float64, float32],
236+
[2]reflect.Kind{reflect.Float64, reflect.Float64}: avgAggregator[float64, float64],
237+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Copyright 2021 ecodeclub
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package aggregator
16+
17+
import (
18+
"testing"
19+
20+
"github.com/ecodeclub/eorm/internal/merger/internal/errs"
21+
22+
"github.com/stretchr/testify/assert"
23+
)
24+
25+
func TestAvg_Aggregate(t *testing.T) {
26+
testcases := []struct {
27+
name string
28+
input [][]any
29+
index []int
30+
wantVal any
31+
wantErr error
32+
}{
33+
{
34+
name: "avg正常合并",
35+
input: [][]any{
36+
{
37+
int64(10),
38+
int64(2),
39+
},
40+
{
41+
int64(20),
42+
int64(2),
43+
},
44+
{
45+
int64(30),
46+
int64(2),
47+
},
48+
},
49+
index: []int{0, 1},
50+
wantVal: float64(10),
51+
},
52+
{
53+
name: "传入的参数非AggregateElement类型",
54+
input: [][]any{
55+
{
56+
"1",
57+
"2",
58+
},
59+
{
60+
"3",
61+
"4",
62+
},
63+
},
64+
index: []int{0, 1},
65+
wantErr: errs.ErrMergerAggregateFuncNotFound,
66+
},
67+
{
68+
name: "columnInfo的index不合法",
69+
input: [][]any{
70+
{
71+
int64(10),
72+
int64(2),
73+
},
74+
{
75+
int64(20),
76+
int64(2),
77+
},
78+
},
79+
index: []int{0, 10},
80+
wantErr: errs.ErrMergerInvalidAggregateColumnIndex,
81+
},
82+
}
83+
for _, tc := range testcases {
84+
t.Run(tc.name, func(t *testing.T) {
85+
avg := NewAVG(NewColumnInfo(tc.index[0], "SUM(grade)"), NewColumnInfo(tc.index[1], "COUNT(grade)"), "AVG(grade)")
86+
val, err := avg.Aggregate(tc.input)
87+
assert.Equal(t, tc.wantErr, err)
88+
if err != nil {
89+
return
90+
}
91+
assert.Equal(t, tc.wantVal, val)
92+
assert.Equal(t, "AVG(grade)", avg.ColumnName())
93+
})
94+
}
95+
96+
}

0 commit comments

Comments
 (0)