github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/colexec/avg_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 avg_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_DIV_INT64 is the template division function for assigning the first
    43  // input to the result of the second input / the third input, where the third
    44  // input is an int64.
    45  func _ASSIGN_DIV_INT64(_, _, _, _, _, _ string) {
    46  	colexecerror.InternalError("")
    47  }
    48  
    49  // _ASSIGN_ADD is the template addition function for assigning the first input
    50  // to the result of the second input + the third input.
    51  func _ASSIGN_ADD(_, _, _, _, _, _ string) {
    52  	colexecerror.InternalError("")
    53  }
    54  
    55  // */}}
    56  
    57  func newAvgAggAlloc(
    58  	allocator *colmem.Allocator, t *types.T, allocSize int64,
    59  ) (aggregateFuncAlloc, error) {
    60  	switch typeconv.TypeFamilyToCanonicalTypeFamily(t.Family()) {
    61  	// {{range .}}
    62  	case _CANONICAL_TYPE_FAMILY:
    63  		switch t.Width() {
    64  		// {{range .WidthOverloads}}
    65  		case _TYPE_WIDTH:
    66  			return &avg_TYPEAggAlloc{allocator: allocator, allocSize: allocSize}, nil
    67  			// {{end}}
    68  		}
    69  		// {{end}}
    70  	}
    71  	return nil, errors.Errorf("unsupported avg agg type %s", t.Name())
    72  }
    73  
    74  // {{range .}}
    75  // {{range .WidthOverloads}}
    76  
    77  type avg_TYPEAgg struct {
    78  	groups  []bool
    79  	scratch struct {
    80  		curIdx int
    81  		// curSum keeps track of the sum of elements belonging to the current group,
    82  		// so we can index into the slice once per group, instead of on each
    83  		// iteration.
    84  		curSum _GOTYPE
    85  		// curCount keeps track of the number of elements that we've seen
    86  		// belonging to the current group.
    87  		curCount int64
    88  		// vec points to the output vector.
    89  		vec []_GOTYPE
    90  		// nulls points to the output null vector that we are updating.
    91  		nulls *coldata.Nulls
    92  		// foundNonNullForCurrentGroup tracks if we have seen any non-null values
    93  		// for the group that is currently being aggregated.
    94  		foundNonNullForCurrentGroup bool
    95  	}
    96  }
    97  
    98  var _ aggregateFunc = &avg_TYPEAgg{}
    99  
   100  const sizeOfAvg_TYPEAgg = int64(unsafe.Sizeof(avg_TYPEAgg{}))
   101  
   102  func (a *avg_TYPEAgg) Init(groups []bool, v coldata.Vec) {
   103  	a.groups = groups
   104  	a.scratch.vec = v.TemplateType()
   105  	a.scratch.nulls = v.Nulls()
   106  	a.Reset()
   107  }
   108  
   109  func (a *avg_TYPEAgg) Reset() {
   110  	a.scratch.curIdx = -1
   111  	a.scratch.curSum = zero_TYPEValue
   112  	a.scratch.curCount = 0
   113  	a.scratch.foundNonNullForCurrentGroup = false
   114  	a.scratch.nulls.UnsetNulls()
   115  }
   116  
   117  func (a *avg_TYPEAgg) CurrentOutputIndex() int {
   118  	return a.scratch.curIdx
   119  }
   120  
   121  func (a *avg_TYPEAgg) SetOutputIndex(idx int) {
   122  	if a.scratch.curIdx != -1 {
   123  		a.scratch.curIdx = idx
   124  		a.scratch.nulls.UnsetNullsAfter(idx + 1)
   125  	}
   126  }
   127  
   128  func (a *avg_TYPEAgg) Compute(b coldata.Batch, inputIdxs []uint32) {
   129  	inputLen := b.Length()
   130  	vec, sel := b.ColVec(int(inputIdxs[0])), b.Selection()
   131  	col, nulls := vec.TemplateType(), vec.Nulls()
   132  	if nulls.MaybeHasNulls() {
   133  		if sel != nil {
   134  			sel = sel[:inputLen]
   135  			for _, i := range sel {
   136  				_ACCUMULATE_AVG(a, nulls, i, true)
   137  			}
   138  		} else {
   139  			col = col[:inputLen]
   140  			for i := range col {
   141  				_ACCUMULATE_AVG(a, nulls, i, true)
   142  			}
   143  		}
   144  	} else {
   145  		if sel != nil {
   146  			sel = sel[:inputLen]
   147  			for _, i := range sel {
   148  				_ACCUMULATE_AVG(a, nulls, i, false)
   149  			}
   150  		} else {
   151  			col = col[:inputLen]
   152  			for i := range col {
   153  				_ACCUMULATE_AVG(a, nulls, i, false)
   154  			}
   155  		}
   156  	}
   157  }
   158  
   159  func (a *avg_TYPEAgg) Flush() {
   160  	// The aggregation is finished. Flush the last value. If we haven't found
   161  	// any non-nulls for this group so far, the output for this group should be
   162  	// NULL.
   163  	if !a.scratch.foundNonNullForCurrentGroup {
   164  		a.scratch.nulls.SetNull(a.scratch.curIdx)
   165  	} else {
   166  		_ASSIGN_DIV_INT64(a.scratch.vec[a.scratch.curIdx], a.scratch.curSum, a.scratch.curCount, a.scratch.vec, _, _)
   167  	}
   168  	a.scratch.curIdx++
   169  }
   170  
   171  func (a *avg_TYPEAgg) HandleEmptyInputScalar() {
   172  	a.scratch.nulls.SetNull(0)
   173  }
   174  
   175  type avg_TYPEAggAlloc struct {
   176  	allocator *colmem.Allocator
   177  	allocSize int64
   178  	aggFuncs  []avg_TYPEAgg
   179  }
   180  
   181  var _ aggregateFuncAlloc = &avg_TYPEAggAlloc{}
   182  
   183  func (a *avg_TYPEAggAlloc) newAggFunc() aggregateFunc {
   184  	if len(a.aggFuncs) == 0 {
   185  		a.allocator.AdjustMemoryUsage(sizeOfAvg_TYPEAgg * a.allocSize)
   186  		a.aggFuncs = make([]avg_TYPEAgg, a.allocSize)
   187  	}
   188  	f := &a.aggFuncs[0]
   189  	a.aggFuncs = a.aggFuncs[1:]
   190  	return f
   191  }
   192  
   193  // {{end}}
   194  // {{end}}
   195  
   196  // {{/*
   197  // _ACCUMULATE_AVG updates the total sum/count for current group using the value
   198  // of the ith row. If this is the first row of a new group, then the average is
   199  // computed for the current group. If no non-nulls have been found for the
   200  // current group, then the output for the current group is set to null.
   201  func _ACCUMULATE_AVG(a *_AGG_TYPEAgg, nulls *coldata.Nulls, i int, _HAS_NULLS bool) { // */}}
   202  
   203  	// {{define "accumulateAvg"}}
   204  	if a.groups[i] {
   205  		// If we encounter a new group, and we haven't found any non-nulls for the
   206  		// current group, the output for this group should be null. If
   207  		// a.scratch.curIdx is negative, it means that this is the first group.
   208  		if a.scratch.curIdx >= 0 {
   209  			if !a.scratch.foundNonNullForCurrentGroup {
   210  				a.scratch.nulls.SetNull(a.scratch.curIdx)
   211  			} else {
   212  				// {{with .Global}}
   213  				_ASSIGN_DIV_INT64(a.scratch.vec[a.scratch.curIdx], a.scratch.curSum, a.scratch.curCount, a.scratch.vec, _, _)
   214  				// {{end}}
   215  			}
   216  		}
   217  		a.scratch.curIdx++
   218  		// {{with .Global}}
   219  		a.scratch.curSum = zero_TYPEValue
   220  		// {{end}}
   221  		a.scratch.curCount = 0
   222  
   223  		// {{/*
   224  		// We only need to reset this flag if there are nulls. If there are no
   225  		// nulls, this will be updated unconditionally below.
   226  		// */}}
   227  		// {{if .HasNulls}}
   228  		a.scratch.foundNonNullForCurrentGroup = false
   229  		// {{end}}
   230  	}
   231  	var isNull bool
   232  	// {{if .HasNulls}}
   233  	isNull = nulls.NullAt(i)
   234  	// {{else}}
   235  	isNull = false
   236  	// {{end}}
   237  	if !isNull {
   238  		_ASSIGN_ADD(a.scratch.curSum, a.scratch.curSum, col[i], _, _, col)
   239  		a.scratch.curCount++
   240  		a.scratch.foundNonNullForCurrentGroup = true
   241  	}
   242  	// {{end}}
   243  
   244  	// {{/*
   245  } // */}}