github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/colexec/aggexec/register.go (about) 1 // Copyright 2024 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 aggexec 16 17 import ( 18 "fmt" 19 "github.com/matrixorigin/matrixone/pkg/common/moerr" 20 "github.com/matrixorigin/matrixone/pkg/container/types" 21 ) 22 23 /* 24 methods to register the aggregation function. 25 after registered, the function `MakeAgg` can make the aggregation function executor. 26 */ 27 28 func RegisterCountColumnAgg(id int64) { 29 specialAgg[id] = true 30 aggIdOfCountColumn = id 31 } 32 33 func RegisterCountStarAgg(id int64) { 34 specialAgg[id] = true 35 aggIdOfCountStar = id 36 } 37 38 func RegisterGroupConcatAgg(id int64, sep string) { 39 specialAgg[id] = true 40 aggIdOfGroupConcat = id 41 groupConcatSep = sep 42 } 43 44 func RegisterApproxCountAgg(id int64) { 45 specialAgg[id] = true 46 aggIdOfApproxCount = id 47 } 48 49 func RegisterMedian(id int64) { 50 specialAgg[id] = true 51 aggIdOfMedian = id 52 } 53 54 func RegisterClusterCenters(id int64) { 55 specialAgg[id] = true 56 aggIdOfClusterCenters = id 57 } 58 59 func RegisterRowNumberWin(id int64) { 60 specialAgg[id] = true 61 winIdOfRowNumber = id 62 } 63 64 func RegisterRankWin(id int64) { 65 specialAgg[id] = true 66 winIdOfRank = id 67 } 68 69 func RegisterDenseRankWin(id int64) { 70 specialAgg[id] = true 71 winIdOfDenseRank = id 72 } 73 74 type registeredAggInfo struct { 75 isSingleAgg bool 76 acceptNull bool 77 setNullForEmptyGroup bool 78 } 79 80 type aggKey string 81 82 func generateKeyOfSingleColumnAgg(aggID int64, argType types.Type) aggKey { 83 return aggKey(fmt.Sprintf("s_%d_%d", aggID, argType.Oid)) 84 } 85 86 func generateKeyOfMultiColumnsAgg(overloadID int64, argTypes []types.Type) aggKey { 87 key := fmt.Sprintf("m_%d", overloadID) 88 for _, argType := range argTypes { 89 key += fmt.Sprintf("_%d", argType.Oid) 90 } 91 return aggKey(key) 92 } 93 94 var ( 95 // agg type record map. 96 singleAgg = make(map[int64]bool) 97 multiAgg = make(map[int64]bool) 98 specialAgg = make(map[int64]bool) 99 100 // agg implementation map. 101 registeredAggFunctions = make(map[aggKey]aggImplementation) 102 registeredMultiColumnAggFunctions = make(map[aggKey]multiColumnAggImplementation) 103 104 // list of special aggregation function IDs. 105 aggIdOfCountColumn = int64(-1) 106 aggIdOfCountStar = int64(-2) 107 aggIdOfGroupConcat = int64(-3) 108 aggIdOfApproxCount = int64(-4) 109 aggIdOfMedian = int64(-5) 110 aggIdOfClusterCenters = int64(-6) 111 winIdOfRowNumber = int64(-7) 112 winIdOfRank = int64(-8) 113 winIdOfDenseRank = int64(-9) 114 groupConcatSep = "," 115 getCroupConcatRet = func(args ...types.Type) types.Type { 116 for _, p := range args { 117 if p.Oid == types.T_binary || p.Oid == types.T_varbinary || p.Oid == types.T_blob { 118 return types.T_blob.ToType() 119 } 120 } 121 return types.T_text.ToType() 122 } 123 ) 124 125 func getSingleAggImplByInfo( 126 id int64, arg types.Type) (aggInfo aggImplementation, err error) { 127 key := generateKeyOfSingleColumnAgg(id, arg) 128 129 if impl, ok := registeredAggFunctions[key]; ok { 130 return impl, nil 131 } 132 return aggImplementation{}, moerr.NewInternalErrorNoCtx("no implementation for aggID %d with argType %s", id, arg) 133 } 134 135 func getMultiArgAggImplByInfo( 136 id int64, args []types.Type) (aggInfo multiColumnAggImplementation, err error) { 137 key := generateKeyOfMultiColumnsAgg(id, args) 138 139 if impl, ok := registeredMultiColumnAggFunctions[key]; ok { 140 return impl, nil 141 } 142 return multiColumnAggImplementation{}, moerr.NewInternalErrorNoCtx("no implementation for aggID %d with argTypes %v", id, args) 143 } 144 145 type aggImplementation struct { 146 registeredAggInfo 147 148 generator any 149 ret func([]types.Type) types.Type 150 151 init any 152 fill any 153 fillNull any 154 fills any 155 merge any 156 flush any 157 } 158 159 type multiColumnAggImplementation struct { 160 setNullForEmptyGroup bool 161 162 generator any 163 ret func([]types.Type) types.Type 164 165 init any 166 fillWhich []any 167 fillNullWhich any 168 rowValid any 169 merge any 170 eval any 171 flush any 172 } 173 174 type SingleColumnAggInformation struct { 175 id int64 176 arg types.Type 177 ret func(p []types.Type) types.Type 178 acceptNull bool 179 setNullForEmptyGroup bool 180 } 181 182 type MultiColumnAggInformation struct { 183 id int64 184 arg []types.Type 185 ret func(p []types.Type) types.Type 186 setNullForEmptyGroup bool 187 } 188 189 func MakeSingleColumnAggInformation( 190 id int64, paramType types.Type, getRetType func(p []types.Type) types.Type, 191 acceptNull bool, setNullForEmptyGroup bool) SingleColumnAggInformation { 192 return SingleColumnAggInformation{ 193 id: id, 194 arg: paramType, 195 ret: getRetType, 196 acceptNull: acceptNull, 197 setNullForEmptyGroup: setNullForEmptyGroup, 198 } 199 } 200 201 func MakeMultiColumnAggInformation( 202 id int64, params []types.Type, getRetType func(p []types.Type) types.Type, 203 setNullForEmptyGroup bool) MultiColumnAggInformation { 204 return MultiColumnAggInformation{ 205 id: id, 206 arg: params, 207 ret: getRetType, 208 setNullForEmptyGroup: setNullForEmptyGroup, 209 } 210 } 211 212 type SingleAggImplementationFixedFixed[from, to types.FixedSizeTExceptStrType] struct { 213 SingleColumnAggInformation 214 generator func() SingleAggFromFixedRetFixed[from, to] 215 216 init SingleAggInit1[from, to] 217 fill SingleAggFill1[from, to] 218 fillNull SingleAggFillNull1[from, to] 219 fills SingleAggFills1[from, to] 220 merge SingleAggMerge1[from, to] 221 flush SingleAggFlush1[from, to] 222 } 223 224 func MakeSingleAgg1RegisteredInfo[from, to types.FixedSizeTExceptStrType]( 225 info SingleColumnAggInformation, 226 impl func() SingleAggFromFixedRetFixed[from, to], 227 init SingleAggInit1[from, to], 228 fill SingleAggFill1[from, to], 229 fillNull SingleAggFillNull1[from, to], 230 fills SingleAggFills1[from, to], 231 merge SingleAggMerge1[from, to], 232 flush SingleAggFlush1[from, to], 233 ) SingleAggImplementationFixedFixed[from, to] { 234 235 registeredInfo1 := SingleAggImplementationFixedFixed[from, to]{ 236 SingleColumnAggInformation: info, 237 generator: impl, 238 init: init, 239 fill: fill, 240 fillNull: fillNull, 241 fills: fills, 242 merge: merge, 243 flush: flush, 244 } 245 return registeredInfo1 246 } 247 248 func RegisterSingleAggFromFixedToFixed[from, to types.FixedSizeTExceptStrType]( 249 info SingleAggImplementationFixedFixed[from, to]) { 250 251 key := generateKeyOfSingleColumnAgg(info.id, info.arg) 252 if _, ok := registeredAggFunctions[key]; ok { 253 panic(fmt.Sprintf("aggID %d with argType %s has been registered", info.id, info.arg)) 254 } 255 256 registeredAggFunctions[key] = aggImplementation{ 257 registeredAggInfo: registeredAggInfo{ 258 isSingleAgg: true, 259 acceptNull: info.acceptNull, 260 setNullForEmptyGroup: info.setNullForEmptyGroup, 261 }, 262 generator: info.generator, 263 ret: info.ret, 264 init: info.init, 265 fill: info.fill, 266 fillNull: info.fillNull, 267 fills: info.fills, 268 merge: info.merge, 269 flush: info.flush, 270 } 271 singleAgg[info.id] = true 272 } 273 274 type SingleAggImplementationFixedVar[from types.FixedSizeTExceptStrType] struct { 275 SingleColumnAggInformation 276 generator func() SingleAggFromFixedRetVar[from] 277 278 init SingleAggInit2[from] 279 fill SingleAggFill2[from] 280 fillNull SingleAggFillNull2[from] 281 fills SingleAggFills2[from] 282 merge SingleAggMerge2[from] 283 flush SingleAggFlush2[from] 284 } 285 286 func MakeSingleAgg2RegisteredInfo[from types.FixedSizeTExceptStrType]( 287 info SingleColumnAggInformation, 288 impl func() SingleAggFromFixedRetVar[from], 289 init SingleAggInit2[from], 290 fill SingleAggFill2[from], 291 fillNull SingleAggFillNull2[from], 292 fills SingleAggFills2[from], 293 merge SingleAggMerge2[from], 294 flush SingleAggFlush2[from], 295 ) SingleAggImplementationFixedVar[from] { 296 297 registeredInfo2 := SingleAggImplementationFixedVar[from]{ 298 SingleColumnAggInformation: info, 299 generator: impl, 300 init: init, 301 fill: fill, 302 fillNull: fillNull, 303 fills: fills, 304 merge: merge, 305 flush: flush, 306 } 307 return registeredInfo2 308 } 309 310 func RegisterSingleAggFromFixedToVar[from types.FixedSizeTExceptStrType]( 311 info SingleAggImplementationFixedVar[from]) { 312 313 key := generateKeyOfSingleColumnAgg(info.id, info.arg) 314 if _, ok := registeredAggFunctions[key]; ok { 315 panic(fmt.Sprintf("aggID %d with argType %s has been registered", info.id, info.arg)) 316 } 317 318 registeredAggFunctions[key] = aggImplementation{ 319 registeredAggInfo: registeredAggInfo{ 320 isSingleAgg: true, 321 acceptNull: info.acceptNull, 322 setNullForEmptyGroup: info.setNullForEmptyGroup, 323 }, 324 generator: info.generator, 325 ret: info.ret, 326 init: info.init, 327 fill: info.fill, 328 fillNull: info.fillNull, 329 fills: info.fills, 330 merge: info.merge, 331 flush: info.flush, 332 } 333 singleAgg[info.id] = true 334 } 335 336 type SingleAggImplementationVarVar struct { 337 SingleColumnAggInformation 338 generator func() SingleAggFromVarRetVar 339 init SingleAggInit4 340 fill SingleAggFill4 341 fillNull SingleAggFillNull4 342 fills SingleAggFills4 343 merge SingleAggMerge4 344 flush SingleAggFlush4 345 } 346 347 func MakeSingleAgg4RegisteredInfo( 348 info SingleColumnAggInformation, 349 impl func() SingleAggFromVarRetVar, 350 init SingleAggInit4, 351 fill SingleAggFill4, 352 fillNull SingleAggFillNull4, 353 fills SingleAggFills4, 354 merge SingleAggMerge4, 355 flush SingleAggFlush4, 356 ) SingleAggImplementationVarVar { 357 358 registeredInfo4 := SingleAggImplementationVarVar{ 359 SingleColumnAggInformation: info, 360 generator: impl, 361 init: init, 362 fill: fill, 363 fillNull: fillNull, 364 fills: fills, 365 merge: merge, 366 flush: flush, 367 } 368 return registeredInfo4 369 } 370 371 func RegisterSingleAggFromVarToVar( 372 info SingleAggImplementationVarVar) { 373 374 key := generateKeyOfSingleColumnAgg(info.id, info.arg) 375 if _, ok := registeredAggFunctions[key]; ok { 376 panic(fmt.Sprintf("aggID %d with argType %s has been registered", info.id, info.arg)) 377 } 378 379 registeredAggFunctions[key] = aggImplementation{ 380 registeredAggInfo: registeredAggInfo{ 381 isSingleAgg: true, 382 acceptNull: info.acceptNull, 383 setNullForEmptyGroup: info.setNullForEmptyGroup, 384 }, 385 generator: info.generator, 386 ret: info.ret, 387 init: info.init, 388 fill: info.fill, 389 fillNull: info.fillNull, 390 fills: info.fills, 391 merge: info.merge, 392 flush: info.flush, 393 } 394 singleAgg[info.id] = true 395 } 396 397 type MultiColumnAggRetFixedRegisteredInfo[to types.FixedSizeTExceptStrType] struct { 398 MultiColumnAggInformation 399 generator func() MultiAggRetFixed[to] 400 init MultiAggInit1[to] 401 fillWhich []any 402 fillNullWhich []MultiAggFillNull1[to] 403 rowValid rowValidForMultiAgg1[to] 404 merge MultiAggMerge1[to] 405 evaluateRow MultiAggEval1[to] 406 flush MultiAggFlush1[to] 407 } 408 409 func MakeMultiAggRetFixedRegisteredInfo[to types.FixedSizeTExceptStrType]( 410 info MultiColumnAggInformation, 411 impl func() MultiAggRetFixed[to], 412 init MultiAggInit1[to], 413 fillWhich []any, 414 fillNullWhich []MultiAggFillNull1[to], 415 rowValid rowValidForMultiAgg1[to], 416 eval MultiAggEval1[to], 417 merge MultiAggMerge1[to], 418 flush MultiAggFlush1[to], 419 ) MultiColumnAggRetFixedRegisteredInfo[to] { 420 // legal check. 421 if len(fillWhich) != len(info.arg) || len(fillNullWhich) != len(fillWhich) || len(info.arg) < 2 { 422 panic("illegal info.arg or fillWhich or fillNullWhich") 423 } 424 // todo: need more check here. fillWhich[i] should be the same type as info.arg[i]. 425 426 registeredInfo := MultiColumnAggRetFixedRegisteredInfo[to]{ 427 MultiColumnAggInformation: info, 428 generator: impl, 429 init: init, 430 fillWhich: fillWhich, 431 fillNullWhich: fillNullWhich, 432 rowValid: rowValid, 433 merge: merge, 434 evaluateRow: eval, 435 flush: flush, 436 } 437 return registeredInfo 438 } 439 440 func RegisterMultiAggRetFixed[to types.FixedSizeTExceptStrType]( 441 info MultiColumnAggRetFixedRegisteredInfo[to]) { 442 443 key := generateKeyOfMultiColumnsAgg(info.id, info.arg) 444 if _, ok := registeredMultiColumnAggFunctions[key]; ok { 445 panic(fmt.Sprintf("aggID %d with argTypes %v has been registered", info.id, info.arg)) 446 } 447 448 registeredMultiColumnAggFunctions[key] = multiColumnAggImplementation{ 449 setNullForEmptyGroup: info.setNullForEmptyGroup, 450 generator: info.generator, 451 ret: info.ret, 452 init: info.init, 453 fillWhich: info.fillWhich, 454 fillNullWhich: any(info.fillNullWhich), 455 rowValid: info.rowValid, 456 merge: info.merge, 457 eval: info.evaluateRow, 458 flush: info.flush, 459 } 460 multiAgg[info.id] = true 461 }