github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/colexec/sum_agg_tmpl.go (about)

     1  // Copyright 2018 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  // {{/*
    12  // +build execgen_template
    13  //
    14  // This file is the execgen template for sum_agg.eg.go. It's formatted in a
    15  // special way, so it's both valid Go and a valid text/template input. This
    16  // permits editing this file with editor support.
    17  //
    18  // */}}
    19  
    20  package colexec
    21  
    22  import (
    23  	"unsafe"
    24  
    25  	"github.com/cockroachdb/cockroach/pkg/col/coldata"
    26  	"github.com/cockroachdb/cockroach/pkg/col/typeconv"
    27  	"github.com/cockroachdb/cockroach/pkg/sql/colexecbase/colexecerror"
    28  	"github.com/cockroachdb/cockroach/pkg/sql/colmem"
    29  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    30  	"github.com/cockroachdb/errors"
    31  )
    32  
    33  // {{/*
    34  // Declarations to make the template compile properly
    35  
    36  // _CANONICAL_TYPE_FAMILY is the template variable.
    37  const _CANONICAL_TYPE_FAMILY = types.UnknownFamily
    38  
    39  // _TYPE_WIDTH is the template variable.
    40  const _TYPE_WIDTH = 0
    41  
    42  // _ASSIGN_ADD is the template addition function for assigning the first input
    43  // to the result of the second input + the third input.
    44  func _ASSIGN_ADD(_, _, _, _, _, _ string) {
    45  	colexecerror.InternalError("")
    46  }
    47  
    48  // */}}
    49  
    50  func newSumAggAlloc(
    51  	allocator *colmem.Allocator, t *types.T, allocSize int64,
    52  ) (aggregateFuncAlloc, error) {
    53  	switch typeconv.TypeFamilyToCanonicalTypeFamily(t.Family()) {
    54  	// {{range .}}
    55  	case _CANONICAL_TYPE_FAMILY:
    56  		switch t.Width() {
    57  		// {{range .WidthOverloads}}
    58  		case _TYPE_WIDTH:
    59  			return &sum_TYPEAggAlloc{allocator: allocator, allocSize: allocSize}, nil
    60  			// {{end}}
    61  		}
    62  		// {{end}}
    63  	}
    64  	return nil, errors.Errorf("unsupported sum agg type %s", t)
    65  }
    66  
    67  // {{range .}}
    68  // {{range .WidthOverloads}}
    69  
    70  type sum_TYPEAgg struct {
    71  	groups  []bool
    72  	scratch struct {
    73  		curIdx int
    74  		// curAgg holds the running total, so we can index into the slice once per
    75  		// group, instead of on each iteration.
    76  		curAgg _GOTYPE
    77  		// vec points to the output vector we are updating.
    78  		vec []_GOTYPE
    79  		// nulls points to the output null vector that we are updating.
    80  		nulls *coldata.Nulls
    81  		// foundNonNullForCurrentGroup tracks if we have seen any non-null values
    82  		// for the group that is currently being aggregated.
    83  		foundNonNullForCurrentGroup bool
    84  	}
    85  }
    86  
    87  var _ aggregateFunc = &sum_TYPEAgg{}
    88  
    89  const sizeOfSum_TYPEAgg = int64(unsafe.Sizeof(sum_TYPEAgg{}))
    90  
    91  func (a *sum_TYPEAgg) Init(groups []bool, v coldata.Vec) {
    92  	a.groups = groups
    93  	a.scratch.vec = v.TemplateType()
    94  	a.scratch.nulls = v.Nulls()
    95  	a.Reset()
    96  }
    97  
    98  func (a *sum_TYPEAgg) Reset() {
    99  	a.scratch.curIdx = -1
   100  	a.scratch.foundNonNullForCurrentGroup = false
   101  	a.scratch.nulls.UnsetNulls()
   102  }
   103  
   104  func (a *sum_TYPEAgg) CurrentOutputIndex() int {
   105  	return a.scratch.curIdx
   106  }
   107  
   108  func (a *sum_TYPEAgg) SetOutputIndex(idx int) {
   109  	if a.scratch.curIdx != -1 {
   110  		a.scratch.curIdx = idx
   111  		a.scratch.nulls.UnsetNullsAfter(idx + 1)
   112  	}
   113  }
   114  
   115  func (a *sum_TYPEAgg) Compute(b coldata.Batch, inputIdxs []uint32) {
   116  	inputLen := b.Length()
   117  	vec, sel := b.ColVec(int(inputIdxs[0])), b.Selection()
   118  	col, nulls := vec.TemplateType(), vec.Nulls()
   119  	if nulls.MaybeHasNulls() {
   120  		if sel != nil {
   121  			sel = sel[:inputLen]
   122  			for _, i := range sel {
   123  				_ACCUMULATE_SUM(a, nulls, i, true)
   124  			}
   125  		} else {
   126  			col = col[:inputLen]
   127  			for i := range col {
   128  				_ACCUMULATE_SUM(a, nulls, i, true)
   129  			}
   130  		}
   131  	} else {
   132  		if sel != nil {
   133  			sel = sel[:inputLen]
   134  			for _, i := range sel {
   135  				_ACCUMULATE_SUM(a, nulls, i, false)
   136  			}
   137  		} else {
   138  			col = col[:inputLen]
   139  			for i := range col {
   140  				_ACCUMULATE_SUM(a, nulls, i, false)
   141  			}
   142  		}
   143  	}
   144  }
   145  
   146  func (a *sum_TYPEAgg) Flush() {
   147  	// The aggregation is finished. Flush the last value. If we haven't found
   148  	// any non-nulls for this group so far, the output for this group should be
   149  	// null.
   150  	if !a.scratch.foundNonNullForCurrentGroup {
   151  		a.scratch.nulls.SetNull(a.scratch.curIdx)
   152  	} else {
   153  		a.scratch.vec[a.scratch.curIdx] = a.scratch.curAgg
   154  	}
   155  	a.scratch.curIdx++
   156  }
   157  
   158  func (a *sum_TYPEAgg) HandleEmptyInputScalar() {
   159  	a.scratch.nulls.SetNull(0)
   160  }
   161  
   162  type sum_TYPEAggAlloc struct {
   163  	allocator *colmem.Allocator
   164  	allocSize int64
   165  	aggFuncs  []sum_TYPEAgg
   166  }
   167  
   168  var _ aggregateFuncAlloc = &sum_TYPEAggAlloc{}
   169  
   170  func (a *sum_TYPEAggAlloc) newAggFunc() aggregateFunc {
   171  	if len(a.aggFuncs) == 0 {
   172  		a.allocator.AdjustMemoryUsage(sizeOfSum_TYPEAgg * a.allocSize)
   173  		a.aggFuncs = make([]sum_TYPEAgg, a.allocSize)
   174  	}
   175  	f := &a.aggFuncs[0]
   176  	a.aggFuncs = a.aggFuncs[1:]
   177  	return f
   178  }
   179  
   180  // {{end}}
   181  // {{end}}
   182  
   183  // {{/*
   184  // _ACCUMULATE_SUM adds the value of the ith row to the output for the current
   185  // group. If this is the first row of a new group, and no non-nulls have been
   186  // found for the current group, then the output for the current group is set to
   187  // null.
   188  func _ACCUMULATE_SUM(a *sum_TYPEAgg, nulls *coldata.Nulls, i int, _HAS_NULLS bool) { // */}}
   189  
   190  	// {{define "accumulateSum"}}
   191  	if a.groups[i] {
   192  		// If we encounter a new group, and we haven't found any non-nulls for the
   193  		// current group, the output for this group should be null. If
   194  		// a.scratch.curIdx is negative, it means that this is the first group.
   195  		if a.scratch.curIdx >= 0 {
   196  			if !a.scratch.foundNonNullForCurrentGroup {
   197  				a.scratch.nulls.SetNull(a.scratch.curIdx)
   198  			} else {
   199  				a.scratch.vec[a.scratch.curIdx] = a.scratch.curAgg
   200  			}
   201  		}
   202  		a.scratch.curIdx++
   203  		// {{with .Global}}
   204  		a.scratch.curAgg = zero_TYPEValue
   205  		// {{end}}
   206  
   207  		// {{/*
   208  		// We only need to reset this flag if there are nulls. If there are no
   209  		// nulls, this will be updated unconditionally below.
   210  		// */}}
   211  		// {{if .HasNulls}}
   212  		a.scratch.foundNonNullForCurrentGroup = false
   213  		// {{end}}
   214  	}
   215  	var isNull bool
   216  	// {{if .HasNulls}}
   217  	isNull = nulls.NullAt(i)
   218  	// {{else}}
   219  	isNull = false
   220  	// {{end}}
   221  	if !isNull {
   222  		_ASSIGN_ADD(a.scratch.curAgg, a.scratch.curAgg, col[i], _, _, col)
   223  		a.scratch.foundNonNullForCurrentGroup = true
   224  	}
   225  	// {{end}}
   226  
   227  	// {{/*
   228  } // */}}