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  }