github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/interlock/aggfuncs/func_max_min_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 "fmt" 18 "time" 19 20 . "github.com/whtcorpsinc/check" 21 "github.com/whtcorpsinc/BerolinaSQL/ast" 22 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 23 "github.com/whtcorpsinc/milevadb/interlock/aggfuncs" 24 "github.com/whtcorpsinc/milevadb/types" 25 "github.com/whtcorpsinc/milevadb/types/json" 26 "github.com/whtcorpsinc/milevadb/soliton/chunk" 27 "github.com/whtcorpsinc/milevadb/soliton/testkit" 28 ) 29 30 func maxMinUFIDelateMemDeltaGens(srcChk *chunk.Chunk, dataType *types.FieldType, isMax bool) (memDeltas []int64, err error) { 31 memDeltas = make([]int64, srcChk.NumEvents()) 32 var ( 33 preStringVal string 34 preJSONVal string 35 preEnumVal types.Enum 36 preSetVal types.Set 37 ) 38 39 for i := 0; i < srcChk.NumEvents(); i++ { 40 event := srcChk.GetEvent(i) 41 if event.IsNull(0) { 42 continue 43 } 44 switch dataType.Tp { 45 case allegrosql.TypeString: 46 curVal := event.GetString(0) 47 if i == 0 { 48 memDeltas[i] = int64(len(curVal)) 49 preStringVal = curVal 50 } else if isMax && curVal > preStringVal || !isMax && curVal < preStringVal { 51 memDeltas[i] = int64(len(curVal)) - int64(len(preStringVal)) 52 preStringVal = curVal 53 } 54 case allegrosql.TypeJSON: 55 curVal := event.GetJSON(0) 56 curStringVal := string(curVal.Value) 57 if i == 0 { 58 memDeltas[i] = int64(len(curStringVal)) 59 preJSONVal = curStringVal 60 } else if isMax && curStringVal > preJSONVal || !isMax && curStringVal < preJSONVal { 61 memDeltas[i] = int64(len(curStringVal)) - int64(len(preJSONVal)) 62 preJSONVal = curStringVal 63 } 64 case allegrosql.TypeEnum: 65 curVal := event.GetEnum(0) 66 if i == 0 { 67 memDeltas[i] = int64(len(curVal.Name)) 68 preEnumVal = curVal 69 } else if isMax && curVal.Value > preEnumVal.Value || !isMax && curVal.Value < preEnumVal.Value { 70 memDeltas[i] = int64(len(curVal.Name)) - int64(len(preEnumVal.Name)) 71 preEnumVal = curVal 72 } 73 case allegrosql.TypeSet: 74 curVal := event.GetSet(0) 75 if i == 0 { 76 memDeltas[i] = int64(len(curVal.Name)) 77 preSetVal = curVal 78 } else if isMax && curVal.Value > preSetVal.Value || !isMax && curVal.Value < preSetVal.Value { 79 memDeltas[i] = int64(len(curVal.Name)) - int64(len(preSetVal.Name)) 80 preSetVal = curVal 81 } 82 } 83 } 84 return memDeltas, nil 85 } 86 87 func maxUFIDelateMemDeltaGens(srcChk *chunk.Chunk, dataType *types.FieldType) (memDeltas []int64, err error) { 88 return maxMinUFIDelateMemDeltaGens(srcChk, dataType, true) 89 } 90 91 func minUFIDelateMemDeltaGens(srcChk *chunk.Chunk, dataType *types.FieldType) (memDeltas []int64, err error) { 92 return maxMinUFIDelateMemDeltaGens(srcChk, dataType, false) 93 } 94 95 func (s *testSuite) TestMergePartialResult4MaxMin(c *C) { 96 elems := []string{"a", "b", "c", "d", "e"} 97 enumA, _ := types.ParseEnumName(elems, "a", allegrosql.DefaultDefCauslationName) 98 enumC, _ := types.ParseEnumName(elems, "c", allegrosql.DefaultDefCauslationName) 99 enumE, _ := types.ParseEnumName(elems, "e", allegrosql.DefaultDefCauslationName) 100 101 setA, _ := types.ParseSetName(elems, "a", allegrosql.DefaultDefCauslationName) // setA.Value == 1 102 setAB, _ := types.ParseSetName(elems, "a,b", allegrosql.DefaultDefCauslationName) // setAB.Value == 3 103 setAC, _ := types.ParseSetName(elems, "a,c", allegrosql.DefaultDefCauslationName) // setAC.Value == 5 104 105 unsignedType := types.NewFieldType(allegrosql.TypeLonglong) 106 unsignedType.Flag |= allegrosql.UnsignedFlag 107 tests := []aggTest{ 108 builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeLonglong, 5, 4, 4, 4), 109 builPosetDaggTesterWithFieldType(ast.AggFuncMax, unsignedType, 5, 4, 4, 4), 110 builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeFloat, 5, 4.0, 4.0, 4.0), 111 builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeDouble, 5, 4.0, 4.0, 4.0), 112 builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeNewDecimal, 5, types.NewDecFromInt(4), types.NewDecFromInt(4), types.NewDecFromInt(4)), 113 builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeString, 5, "4", "4", "4"), 114 builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeDate, 5, types.TimeFromDays(369), types.TimeFromDays(369), types.TimeFromDays(369)), 115 builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeDuration, 5, types.Duration{Duration: time.Duration(4)}, types.Duration{Duration: time.Duration(4)}, types.Duration{Duration: time.Duration(4)}), 116 builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeJSON, 5, json.CreateBinary(int64(4)), json.CreateBinary(int64(4)), json.CreateBinary(int64(4))), 117 builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeEnum, 5, enumE, enumE, enumE), 118 builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeSet, 5, setAC, setAC, setAC), 119 120 builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeLonglong, 5, 0, 2, 0), 121 builPosetDaggTesterWithFieldType(ast.AggFuncMin, unsignedType, 5, 0, 2, 0), 122 builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeFloat, 5, 0.0, 2.0, 0.0), 123 builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeDouble, 5, 0.0, 2.0, 0.0), 124 builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeNewDecimal, 5, types.NewDecFromInt(0), types.NewDecFromInt(2), types.NewDecFromInt(0)), 125 builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeString, 5, "0", "2", "0"), 126 builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeDate, 5, types.TimeFromDays(365), types.TimeFromDays(367), types.TimeFromDays(365)), 127 builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeDuration, 5, types.Duration{Duration: time.Duration(0)}, types.Duration{Duration: time.Duration(2)}, types.Duration{Duration: time.Duration(0)}), 128 builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeJSON, 5, json.CreateBinary(int64(0)), json.CreateBinary(int64(2)), json.CreateBinary(int64(0))), 129 builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeEnum, 5, enumA, enumC, enumA), 130 builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeSet, 5, setA, setAB, setA), 131 } 132 for _, test := range tests { 133 s.testMergePartialResult(c, test) 134 } 135 } 136 137 func (s *testSuite) TestMaxMin(c *C) { 138 unsignedType := types.NewFieldType(allegrosql.TypeLonglong) 139 unsignedType.Flag |= allegrosql.UnsignedFlag 140 tests := []aggTest{ 141 builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeLonglong, 5, nil, 4), 142 builPosetDaggTesterWithFieldType(ast.AggFuncMax, unsignedType, 5, nil, 4), 143 builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeFloat, 5, nil, 4.0), 144 builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeDouble, 5, nil, 4.0), 145 builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeNewDecimal, 5, nil, types.NewDecFromInt(4)), 146 builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeString, 5, nil, "4", "4"), 147 builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeDate, 5, nil, types.TimeFromDays(369)), 148 builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeDuration, 5, nil, types.Duration{Duration: time.Duration(4)}), 149 builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeJSON, 5, nil, json.CreateBinary(int64(4))), 150 151 builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeLonglong, 5, nil, 0), 152 builPosetDaggTesterWithFieldType(ast.AggFuncMin, unsignedType, 5, nil, 0), 153 builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeFloat, 5, nil, 0.0), 154 builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeDouble, 5, nil, 0.0), 155 builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeNewDecimal, 5, nil, types.NewDecFromInt(0)), 156 builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeString, 5, nil, "0"), 157 builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeDate, 5, nil, types.TimeFromDays(365)), 158 builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeDuration, 5, nil, types.Duration{Duration: time.Duration(0)}), 159 builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeJSON, 5, nil, json.CreateBinary(int64(0))), 160 } 161 for _, test := range tests { 162 s.testAggFunc(c, test) 163 } 164 } 165 166 func (s *testSuite) TestMemMaxMin(c *C) { 167 tests := []aggMemTest{ 168 builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeLonglong, 5, 169 aggfuncs.DefPartialResult4MaxMinIntSize, defaultUFIDelateMemDeltaGens, false), 170 builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeLonglong, 5, 171 aggfuncs.DefPartialResult4MaxMinUintSize, defaultUFIDelateMemDeltaGens, false), 172 builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeNewDecimal, 5, 173 aggfuncs.DefPartialResult4MaxMinDecimalSize, defaultUFIDelateMemDeltaGens, false), 174 builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeFloat, 5, 175 aggfuncs.DefPartialResult4MaxMinFloat32Size, defaultUFIDelateMemDeltaGens, false), 176 builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeDouble, 5, 177 aggfuncs.DefPartialResult4MaxMinFloat64Size, defaultUFIDelateMemDeltaGens, false), 178 builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeDate, 5, 179 aggfuncs.DefPartialResult4TimeSize, defaultUFIDelateMemDeltaGens, false), 180 builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeDuration, 5, 181 aggfuncs.DefPartialResult4MaxMinDurationSize, defaultUFIDelateMemDeltaGens, false), 182 builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeString, 99, 183 aggfuncs.DefPartialResult4MaxMinStringSize, maxUFIDelateMemDeltaGens, false), 184 builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeJSON, 99, 185 aggfuncs.DefPartialResult4MaxMinJSONSize, maxUFIDelateMemDeltaGens, false), 186 builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeEnum, 99, 187 aggfuncs.DefPartialResult4MaxMinEnumSize, maxUFIDelateMemDeltaGens, false), 188 builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeSet, 99, 189 aggfuncs.DefPartialResult4MaxMinSetSize, maxUFIDelateMemDeltaGens, false), 190 191 builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeLonglong, 5, 192 aggfuncs.DefPartialResult4MaxMinIntSize, defaultUFIDelateMemDeltaGens, false), 193 builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeLonglong, 5, 194 aggfuncs.DefPartialResult4MaxMinUintSize, defaultUFIDelateMemDeltaGens, false), 195 builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeNewDecimal, 5, 196 aggfuncs.DefPartialResult4MaxMinDecimalSize, defaultUFIDelateMemDeltaGens, false), 197 builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeFloat, 5, 198 aggfuncs.DefPartialResult4MaxMinFloat32Size, defaultUFIDelateMemDeltaGens, false), 199 builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeDouble, 5, 200 aggfuncs.DefPartialResult4MaxMinFloat64Size, defaultUFIDelateMemDeltaGens, false), 201 builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeDate, 5, 202 aggfuncs.DefPartialResult4TimeSize, defaultUFIDelateMemDeltaGens, false), 203 builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeDuration, 5, 204 aggfuncs.DefPartialResult4MaxMinDurationSize, defaultUFIDelateMemDeltaGens, false), 205 builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeString, 99, 206 aggfuncs.DefPartialResult4MaxMinStringSize, minUFIDelateMemDeltaGens, false), 207 builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeJSON, 99, 208 aggfuncs.DefPartialResult4MaxMinJSONSize, minUFIDelateMemDeltaGens, false), 209 builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeEnum, 99, 210 aggfuncs.DefPartialResult4MaxMinEnumSize, minUFIDelateMemDeltaGens, false), 211 builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeSet, 99, 212 aggfuncs.DefPartialResult4MaxMinSetSize, minUFIDelateMemDeltaGens, false), 213 } 214 for _, test := range tests { 215 s.testAggMemFunc(c, test) 216 } 217 } 218 219 type maxSlidingWindowTestCase struct { 220 rowType string 221 insertValue string 222 expect []string 223 orderByExpect []string 224 orderBy bool 225 frameType ast.FrameType 226 } 227 228 func testMaxSlidingWindow(tk *testkit.TestKit, tc maxSlidingWindowTestCase) { 229 tk.MustInterDirc(fmt.Sprintf("CREATE TABLE t (a %s);", tc.rowType)) 230 tk.MustInterDirc(fmt.Sprintf("insert into t values %s;", tc.insertValue)) 231 var orderBy string 232 if tc.orderBy { 233 orderBy = "ORDER BY a" 234 } 235 var result *testkit.Result 236 switch tc.frameType { 237 case ast.Events: 238 result = tk.MustQuery(fmt.Sprintf("SELECT max(a) OVER (%s ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM t;", orderBy)) 239 case ast.Ranges: 240 result = tk.MustQuery(fmt.Sprintf("SELECT max(a) OVER (%s RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM t;", orderBy)) 241 default: 242 result = tk.MustQuery(fmt.Sprintf("SELECT max(a) OVER (%s) FROM t;", orderBy)) 243 if tc.orderBy { 244 result.Check(testkit.Events(tc.orderByExpect...)) 245 return 246 } 247 } 248 result.Check(testkit.Events(tc.expect...)) 249 } 250 251 func (s *testSuite) TestMaxSlidingWindow(c *C) { 252 tk := testkit.NewTestKitWithInit(c, s.causetstore) 253 testCases := []maxSlidingWindowTestCase{ 254 { 255 rowType: "bigint", 256 insertValue: "(1), (3), (2)", 257 expect: []string{"3", "3", "3"}, 258 orderByExpect: []string{"1", "2", "3"}, 259 }, 260 { 261 rowType: "float", 262 insertValue: "(1.1), (3.3), (2.2)", 263 expect: []string{"3.3", "3.3", "3.3"}, 264 orderByExpect: []string{"1.1", "2.2", "3.3"}, 265 }, 266 { 267 rowType: "double", 268 insertValue: "(1.1), (3.3), (2.2)", 269 expect: []string{"3.3", "3.3", "3.3"}, 270 orderByExpect: []string{"1.1", "2.2", "3.3"}, 271 }, 272 { 273 rowType: "decimal(5, 2)", 274 insertValue: "(1.1), (3.3), (2.2)", 275 expect: []string{"3.30", "3.30", "3.30"}, 276 orderByExpect: []string{"1.10", "2.20", "3.30"}, 277 }, 278 { 279 rowType: "text", 280 insertValue: "('1.1'), ('3.3'), ('2.2')", 281 expect: []string{"3.3", "3.3", "3.3"}, 282 orderByExpect: []string{"1.1", "2.2", "3.3"}, 283 }, 284 { 285 rowType: "time", 286 insertValue: "('00:00:00'), ('03:00:00'), ('02:00:00')", 287 expect: []string{"03:00:00", "03:00:00", "03:00:00"}, 288 orderByExpect: []string{"00:00:00", "02:00:00", "03:00:00"}, 289 }, 290 { 291 rowType: "date", 292 insertValue: "('2020-09-08'), ('2022-09-10'), ('2020-09-10')", 293 expect: []string{"2022-09-10", "2022-09-10", "2022-09-10"}, 294 orderByExpect: []string{"2020-09-08", "2020-09-10", "2022-09-10"}, 295 }, 296 { 297 rowType: "datetime", 298 insertValue: "('2020-09-08 02:00:00'), ('2022-09-10 00:00:00'), ('2020-09-10 00:00:00')", 299 expect: []string{"2022-09-10 00:00:00", "2022-09-10 00:00:00", "2022-09-10 00:00:00"}, 300 orderByExpect: []string{"2020-09-08 02:00:00", "2020-09-10 00:00:00", "2022-09-10 00:00:00"}, 301 }, 302 } 303 304 orderBy := []bool{false, true} 305 frameType := []ast.FrameType{ast.Events, ast.Ranges, -1} 306 for _, o := range orderBy { 307 for _, f := range frameType { 308 for _, tc := range testCases { 309 tc.frameType = f 310 tc.orderBy = o 311 tk.MustInterDirc("drop causet if exists t;") 312 testMaxSlidingWindow(tk, tc) 313 } 314 } 315 } 316 }