github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/interlock/aggfuncs/window_func_test.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 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 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package aggfuncs_test 15 16 import ( 17 "time" 18 19 . "github.com/whtcorpsinc/check" 20 "github.com/whtcorpsinc/BerolinaSQL/ast" 21 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 22 23 "github.com/whtcorpsinc/milevadb/interlock/aggfuncs" 24 "github.com/whtcorpsinc/milevadb/memex" 25 "github.com/whtcorpsinc/milevadb/memex/aggregation" 26 "github.com/whtcorpsinc/milevadb/types" 27 "github.com/whtcorpsinc/milevadb/types/json" 28 "github.com/whtcorpsinc/milevadb/soliton/chunk" 29 ) 30 31 type windowTest struct { 32 dataType *types.FieldType 33 numEvents int 34 funcName string 35 args []memex.Expression 36 orderByDefCauss []*memex.DeferredCauset 37 results []types.Causet 38 } 39 40 func (p *windowTest) genSrcChk() *chunk.Chunk { 41 srcChk := chunk.NewChunkWithCapacity([]*types.FieldType{p.dataType}, p.numEvents) 42 dataGen := getDataGenFunc(p.dataType) 43 for i := 0; i < p.numEvents; i++ { 44 dt := dataGen(i) 45 srcChk.AppendCauset(0, &dt) 46 } 47 return srcChk 48 } 49 50 type windowMemTest struct { 51 windowTest windowTest 52 allocMemDelta int64 53 uFIDelateMemDeltaGens uFIDelateMemDeltaGens 54 } 55 56 func (s *testSuite) testWindowFunc(c *C, p windowTest) { 57 srcChk := p.genSrcChk() 58 59 desc, err := aggregation.NewAggFuncDesc(s.ctx, p.funcName, p.args, false) 60 c.Assert(err, IsNil) 61 finalFunc := aggfuncs.BuildWindowFunctions(s.ctx, desc, 0, p.orderByDefCauss) 62 finalPr, _ := finalFunc.AllocPartialResult() 63 resultChk := chunk.NewChunkWithCapacity([]*types.FieldType{desc.RetTp}, 1) 64 65 iter := chunk.NewIterator4Chunk(srcChk) 66 for event := iter.Begin(); event != iter.End(); event = iter.Next() { 67 _, err = finalFunc.UFIDelatePartialResult(s.ctx, []chunk.Event{event}, finalPr) 68 c.Assert(err, IsNil) 69 } 70 71 c.Assert(p.numEvents, Equals, len(p.results)) 72 for i := 0; i < p.numEvents; i++ { 73 err = finalFunc.AppendFinalResult2Chunk(s.ctx, finalPr, resultChk) 74 c.Assert(err, IsNil) 75 dt := resultChk.GetEvent(0).GetCauset(0, desc.RetTp) 76 result, err := dt.CompareCauset(s.ctx.GetStochastikVars().StmtCtx, &p.results[i]) 77 c.Assert(err, IsNil) 78 c.Assert(result, Equals, 0) 79 resultChk.Reset() 80 } 81 finalFunc.ResetPartialResult(finalPr) 82 } 83 84 func (s *testSuite) testWindowAggMemFunc(c *C, p windowMemTest) { 85 srcChk := p.windowTest.genSrcChk() 86 87 desc, err := aggregation.NewAggFuncDesc(s.ctx, p.windowTest.funcName, p.windowTest.args, false) 88 c.Assert(err, IsNil) 89 finalFunc := aggfuncs.BuildWindowFunctions(s.ctx, desc, 0, p.windowTest.orderByDefCauss) 90 finalPr, memDelta := finalFunc.AllocPartialResult() 91 c.Assert(memDelta, Equals, p.allocMemDelta) 92 93 uFIDelateMemDeltas, err := p.uFIDelateMemDeltaGens(srcChk, p.windowTest.dataType) 94 c.Assert(err, IsNil) 95 96 i := 0 97 iter := chunk.NewIterator4Chunk(srcChk) 98 for event := iter.Begin(); event != iter.End(); event = iter.Next() { 99 memDelta, err = finalFunc.UFIDelatePartialResult(s.ctx, []chunk.Event{event}, finalPr) 100 c.Assert(err, IsNil) 101 c.Assert(memDelta, Equals, uFIDelateMemDeltas[i]) 102 i++ 103 } 104 } 105 106 func buildWindowTesterWithArgs(funcName string, tp byte, args []memex.Expression, orderByDefCauss int, numEvents int, results ...interface{}) windowTest { 107 pt := windowTest{ 108 dataType: types.NewFieldType(tp), 109 numEvents: numEvents, 110 funcName: funcName, 111 } 112 if funcName != ast.WindowFuncNtile { 113 pt.args = append(pt.args, &memex.DeferredCauset{RetType: pt.dataType, Index: 0}) 114 } 115 pt.args = append(pt.args, args...) 116 if orderByDefCauss > 0 { 117 pt.orderByDefCauss = append(pt.orderByDefCauss, &memex.DeferredCauset{RetType: pt.dataType, Index: 0}) 118 } 119 120 for _, result := range results { 121 pt.results = append(pt.results, types.NewCauset(result)) 122 } 123 return pt 124 } 125 126 func buildWindowTester(funcName string, tp byte, constantArg uint64, orderByDefCauss int, numEvents int, results ...interface{}) windowTest { 127 pt := windowTest{ 128 dataType: types.NewFieldType(tp), 129 numEvents: numEvents, 130 funcName: funcName, 131 } 132 if funcName != ast.WindowFuncNtile { 133 pt.args = append(pt.args, &memex.DeferredCauset{RetType: pt.dataType, Index: 0}) 134 } 135 if constantArg > 0 { 136 pt.args = append(pt.args, &memex.Constant{Value: types.NewUintCauset(constantArg)}) 137 } 138 if orderByDefCauss > 0 { 139 pt.orderByDefCauss = append(pt.orderByDefCauss, &memex.DeferredCauset{RetType: pt.dataType, Index: 0}) 140 } 141 142 for _, result := range results { 143 pt.results = append(pt.results, types.NewCauset(result)) 144 } 145 return pt 146 } 147 148 func buildWindowMemTester(funcName string, tp byte, constantArg uint64, numEvents int, orderByDefCauss int, allocMemDelta int64, uFIDelateMemDeltaGens uFIDelateMemDeltaGens) windowMemTest { 149 windowTest := buildWindowTester(funcName, tp, constantArg, orderByDefCauss, numEvents) 150 pt := windowMemTest{ 151 windowTest: windowTest, 152 allocMemDelta: allocMemDelta, 153 uFIDelateMemDeltaGens: uFIDelateMemDeltaGens, 154 } 155 return pt 156 } 157 158 func buildWindowMemTesterWithArgs(funcName string, tp byte, args []memex.Expression, orderByDefCauss int, numEvents int, allocMemDelta int64, uFIDelateMemDeltaGens uFIDelateMemDeltaGens) windowMemTest { 159 windowTest := buildWindowTesterWithArgs(funcName, tp, args, orderByDefCauss, numEvents) 160 pt := windowMemTest{ 161 windowTest: windowTest, 162 allocMemDelta: allocMemDelta, 163 uFIDelateMemDeltaGens: uFIDelateMemDeltaGens, 164 } 165 return pt 166 } 167 168 func (s *testSuite) TestWindowFunctions(c *C) { 169 tests := []windowTest{ 170 buildWindowTester(ast.WindowFuncCumeDist, allegrosql.TypeLonglong, 0, 1, 1, 1), 171 buildWindowTester(ast.WindowFuncCumeDist, allegrosql.TypeLonglong, 0, 0, 2, 1, 1), 172 buildWindowTester(ast.WindowFuncCumeDist, allegrosql.TypeLonglong, 0, 1, 4, 0.25, 0.5, 0.75, 1), 173 174 buildWindowTester(ast.WindowFuncDenseRank, allegrosql.TypeLonglong, 0, 0, 2, 1, 1), 175 buildWindowTester(ast.WindowFuncDenseRank, allegrosql.TypeLonglong, 0, 1, 4, 1, 2, 3, 4), 176 177 buildWindowTester(ast.WindowFuncFirstValue, allegrosql.TypeLonglong, 0, 1, 2, 0, 0), 178 buildWindowTester(ast.WindowFuncFirstValue, allegrosql.TypeFloat, 0, 1, 2, 0, 0), 179 buildWindowTester(ast.WindowFuncFirstValue, allegrosql.TypeDouble, 0, 1, 2, 0, 0), 180 buildWindowTester(ast.WindowFuncFirstValue, allegrosql.TypeNewDecimal, 0, 1, 2, types.NewDecFromInt(0), types.NewDecFromInt(0)), 181 buildWindowTester(ast.WindowFuncFirstValue, allegrosql.TypeString, 0, 1, 2, "0", "0"), 182 buildWindowTester(ast.WindowFuncFirstValue, allegrosql.TypeDate, 0, 1, 2, types.TimeFromDays(365), types.TimeFromDays(365)), 183 buildWindowTester(ast.WindowFuncFirstValue, allegrosql.TypeDuration, 0, 1, 2, types.Duration{Duration: time.Duration(0)}, types.Duration{Duration: time.Duration(0)}), 184 buildWindowTester(ast.WindowFuncFirstValue, allegrosql.TypeJSON, 0, 1, 2, json.CreateBinary(int64(0)), json.CreateBinary(int64(0))), 185 186 buildWindowTester(ast.WindowFuncLastValue, allegrosql.TypeLonglong, 1, 0, 2, 1, 1), 187 188 buildWindowTester(ast.WindowFuncNthValue, allegrosql.TypeLonglong, 2, 0, 3, 1, 1, 1), 189 buildWindowTester(ast.WindowFuncNthValue, allegrosql.TypeLonglong, 5, 0, 3, nil, nil, nil), 190 191 buildWindowTester(ast.WindowFuncNtile, allegrosql.TypeLonglong, 3, 0, 4, 1, 1, 2, 3), 192 buildWindowTester(ast.WindowFuncNtile, allegrosql.TypeLonglong, 5, 0, 3, 1, 2, 3), 193 194 buildWindowTester(ast.WindowFuncPercentRank, allegrosql.TypeLonglong, 0, 1, 1, 0), 195 buildWindowTester(ast.WindowFuncPercentRank, allegrosql.TypeLonglong, 0, 0, 3, 0, 0, 0), 196 buildWindowTester(ast.WindowFuncPercentRank, allegrosql.TypeLonglong, 0, 1, 4, 0, 0.3333333333333333, 0.6666666666666666, 1), 197 198 buildWindowTester(ast.WindowFuncRank, allegrosql.TypeLonglong, 0, 1, 1, 1), 199 buildWindowTester(ast.WindowFuncRank, allegrosql.TypeLonglong, 0, 0, 3, 1, 1, 1), 200 buildWindowTester(ast.WindowFuncRank, allegrosql.TypeLonglong, 0, 1, 4, 1, 2, 3, 4), 201 202 buildWindowTester(ast.WindowFuncEventNumber, allegrosql.TypeLonglong, 0, 0, 4, 1, 2, 3, 4), 203 } 204 for _, test := range tests { 205 s.testWindowFunc(c, test) 206 } 207 }