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 } // */}}