github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/colexec/group/group_test.go (about) 1 // Copyright 2021 Matrix Origin 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 group 16 17 import ( 18 "bytes" 19 "github.com/matrixorigin/matrixone/pkg/sql/colexec/aggexec" 20 "testing" 21 22 "github.com/matrixorigin/matrixone/pkg/sql/plan/function" 23 24 "github.com/matrixorigin/matrixone/pkg/common/mpool" 25 "github.com/matrixorigin/matrixone/pkg/sql/colexec/value_scan" 26 "github.com/matrixorigin/matrixone/pkg/vm" 27 28 "github.com/matrixorigin/matrixone/pkg/container/batch" 29 "github.com/matrixorigin/matrixone/pkg/container/types" 30 "github.com/matrixorigin/matrixone/pkg/pb/plan" 31 "github.com/matrixorigin/matrixone/pkg/testutil" 32 "github.com/matrixorigin/matrixone/pkg/vm/process" 33 "github.com/stretchr/testify/require" 34 ) 35 36 const ( 37 Rows = 10 // default rows 38 BenchmarkRows = 100000 // default rows for benchmark 39 ) 40 41 // add unit tests for cases 42 type groupTestCase struct { 43 arg *Argument 44 flgs []bool // flgs[i] == true: nullable 45 proc *process.Process 46 } 47 48 var ( 49 tcs []groupTestCase 50 ) 51 52 func init() { 53 tcs = []groupTestCase{ 54 newTestCase([]bool{false}, []types.Type{types.T_int8.ToType()}, nil, 0), 55 newTestCase([]bool{false}, []types.Type{types.T_int8.ToType()}, []int{0}, 0), 56 newTestCase([]bool{false, true, false, true}, []types.Type{ 57 types.T_int8.ToType(), 58 types.T_int16.ToType(), 59 }, []int{0, 1}, 0), 60 newTestCase([]bool{false, true, false, true}, []types.Type{ 61 types.T_int8.ToType(), 62 types.T_int16.ToType(), 63 types.T_int32.ToType(), 64 types.T_int64.ToType(), 65 }, []int{0, 3}, 0), 66 newTestCase([]bool{false, true, false, true}, []types.Type{ 67 types.T_int64.ToType(), 68 types.T_int64.ToType(), 69 types.T_int64.ToType(), 70 types.T_decimal128.ToType(), 71 }, []int{1, 3}, 0), 72 newTestCase([]bool{false, true, false, true}, []types.Type{ 73 types.T_int64.ToType(), 74 types.T_int64.ToType(), 75 types.T_int64.ToType(), 76 types.T_decimal128.ToType(), 77 }, []int{1, 2, 3}, 0), 78 newTestCase([]bool{false, true, false, true}, []types.Type{ 79 types.T_int64.ToType(), 80 types.T_int64.ToType(), 81 types.New(types.T_varchar, 2, 0), 82 types.T_decimal128.ToType(), 83 }, []int{1, 2, 3}, 0), 84 newTestCase([]bool{false, true, false, true}, []types.Type{ 85 types.T_int64.ToType(), 86 types.T_int64.ToType(), 87 types.T_varchar.ToType(), 88 types.T_decimal128.ToType(), 89 }, []int{1, 2, 3}, 0), 90 } 91 } 92 93 func TestString(t *testing.T) { 94 buf := new(bytes.Buffer) 95 for _, tc := range tcs { 96 tc.arg.String(buf) 97 } 98 } 99 100 func TestGroup(t *testing.T) { 101 for _, tc := range tcs { 102 err := tc.arg.Prepare(tc.proc) 103 require.NoError(t, err) 104 105 bats := []*batch.Batch{ 106 newBatch(tc.arg.Types, tc.proc, Rows), 107 newBatch(tc.arg.Types, tc.proc, Rows), 108 batch.EmptyBatch, 109 } 110 resetChildren(tc.arg, bats) 111 _, err = tc.arg.Call(tc.proc) 112 require.NoError(t, err) 113 114 tc.arg.Free(tc.proc, false, nil) 115 tc.arg.GetChildren(0).Free(tc.proc, false, nil) 116 tc.proc.FreeVectors() 117 require.Equal(t, int64(0), tc.proc.Mp().CurrNB()) 118 } 119 } 120 121 func BenchmarkGroup(b *testing.B) { 122 for i := 0; i < b.N; i++ { 123 tcs = []groupTestCase{ 124 newTestCase([]bool{false}, []types.Type{types.T_int8.ToType()}, nil, 0), 125 newTestCase([]bool{false}, []types.Type{types.T_int8.ToType()}, []int{0}, 0), 126 } 127 t := new(testing.T) 128 for _, tc := range tcs { 129 err := tc.arg.Prepare(tc.proc) 130 require.NoError(t, err) 131 bats := []*batch.Batch{ 132 newBatch(tc.arg.Types, tc.proc, BenchmarkRows), 133 newBatch(tc.arg.Types, tc.proc, BenchmarkRows), 134 batch.EmptyBatch, 135 } 136 resetChildren(tc.arg, bats) 137 _, err = tc.arg.Call(tc.proc) 138 require.NoError(t, err) 139 140 tc.arg.Free(tc.proc, false, nil) 141 tc.arg.GetChildren(0).Free(tc.proc, false, nil) 142 tc.proc.FreeVectors() 143 } 144 } 145 } 146 147 func newTestCase(flgs []bool, ts []types.Type, exprIdx []int, pos int32) groupTestCase { 148 exprs := []*plan.Expr{} 149 for _, idx := range exprIdx { 150 exprs = append(exprs, newExpression(int32(idx), ts)) 151 } 152 aggs := []aggexec.AggFuncExecExpression{ 153 aggexec.MakeAggFunctionExpression(function.AggSumOverloadID, false, []*plan.Expr{newExpression(pos, ts)}, nil)} 154 155 for _, expr := range exprs { 156 if col, ok := expr.Expr.(*plan.Expr_Col); ok { 157 idx := col.Col.ColPos 158 expr.Typ = plan.Type{ 159 Id: int32(ts[idx].Oid), 160 Width: ts[idx].Width, 161 Scale: ts[idx].Scale, 162 } 163 } 164 } 165 return groupTestCase{ 166 flgs: flgs, 167 proc: testutil.NewProcessWithMPool(mpool.MustNewZero()), 168 arg: &Argument{ 169 Exprs: exprs, 170 Types: ts, 171 Aggs: aggs, 172 OperatorBase: vm.OperatorBase{ 173 OperatorInfo: vm.OperatorInfo{ 174 Idx: 1, 175 IsFirst: false, 176 IsLast: false, 177 }, 178 }, 179 }, 180 } 181 } 182 183 func newExpression(pos int32, typs []types.Type) *plan.Expr { 184 return &plan.Expr{ 185 Typ: plan.Type{Id: int32(typs[pos].Oid)}, 186 Expr: &plan.Expr_Col{ 187 Col: &plan.ColRef{ 188 ColPos: pos, 189 }, 190 }, 191 } 192 } 193 194 // create a new block based on the type information, flgs[i] == ture: has null 195 func newBatch(ts []types.Type, proc *process.Process, rows int64) *batch.Batch { 196 return testutil.NewBatch(ts, false, int(rows), proc.Mp()) 197 } 198 199 func resetChildren(arg *Argument, bats []*batch.Batch) { 200 if arg.NumChildren() == 0 { 201 arg.AppendChild(&value_scan.Argument{ 202 Batchs: bats, 203 }) 204 205 } else { 206 arg.SetChildren( 207 []vm.Operator{ 208 &value_scan.Argument{ 209 Batchs: bats, 210 }, 211 }) 212 } 213 arg.ctr.state = vm.Build 214 }