github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/colexec/any_not_null_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 any_not_null_agg.eg.go. It's formatted 15 // in a special way, so it's both valid Go and a valid text/template input. 16 // This 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/colexec/execgen" 28 "github.com/cockroachdb/cockroach/pkg/sql/colmem" 29 "github.com/cockroachdb/cockroach/pkg/sql/types" 30 "github.com/cockroachdb/errors" 31 ) 32 33 // Remove unused warning. 34 var _ = execgen.UNSAFEGET 35 36 // {{/* 37 38 // Declarations to make the template compile properly. 39 40 // _GOTYPESLICE is the template variable. 41 type _GOTYPESLICE interface{} 42 43 // _CANONICAL_TYPE_FAMILY is the template variable. 44 const _CANONICAL_TYPE_FAMILY = types.UnknownFamily 45 46 // _TYPE_WIDTH is the template variable. 47 const _TYPE_WIDTH = 0 48 49 // */}} 50 51 func newAnyNotNullAggAlloc( 52 allocator *colmem.Allocator, t *types.T, allocSize int64, 53 ) (aggregateFuncAlloc, error) { 54 switch typeconv.TypeFamilyToCanonicalTypeFamily(t.Family()) { 55 // {{range .}} 56 case _CANONICAL_TYPE_FAMILY: 57 switch t.Width() { 58 // {{range .WidthOverloads}} 59 case _TYPE_WIDTH: 60 return &anyNotNull_TYPEAggAlloc{allocator: allocator, allocSize: allocSize}, nil 61 // {{end}} 62 } 63 // {{end}} 64 } 65 return nil, errors.Errorf("unsupported any not null agg type %s", t.Name()) 66 } 67 68 // {{range .}} 69 // {{range .WidthOverloads}} 70 71 // anyNotNull_TYPEAgg implements the ANY_NOT_NULL aggregate, returning the 72 // first non-null value in the input column. 73 type anyNotNull_TYPEAgg struct { 74 allocator *colmem.Allocator 75 groups []bool 76 vec coldata.Vec 77 col _GOTYPESLICE 78 nulls *coldata.Nulls 79 curIdx int 80 curAgg _GOTYPE 81 foundNonNullForCurrentGroup bool 82 } 83 84 var _ aggregateFunc = &anyNotNull_TYPEAgg{} 85 86 const sizeOfAnyNotNull_TYPEAgg = int64(unsafe.Sizeof(anyNotNull_TYPEAgg{})) 87 88 func (a *anyNotNull_TYPEAgg) Init(groups []bool, vec coldata.Vec) { 89 a.groups = groups 90 a.vec = vec 91 a.col = vec.TemplateType() 92 a.nulls = vec.Nulls() 93 a.Reset() 94 } 95 96 func (a *anyNotNull_TYPEAgg) Reset() { 97 a.curIdx = -1 98 a.foundNonNullForCurrentGroup = false 99 a.nulls.UnsetNulls() 100 } 101 102 func (a *anyNotNull_TYPEAgg) CurrentOutputIndex() int { 103 return a.curIdx 104 } 105 106 func (a *anyNotNull_TYPEAgg) SetOutputIndex(idx int) { 107 if a.curIdx != -1 { 108 a.curIdx = idx 109 a.nulls.UnsetNullsAfter(idx + 1) 110 } 111 } 112 113 func (a *anyNotNull_TYPEAgg) Compute(b coldata.Batch, inputIdxs []uint32) { 114 inputLen := b.Length() 115 vec, sel := b.ColVec(int(inputIdxs[0])), b.Selection() 116 col, nulls := vec.TemplateType(), vec.Nulls() 117 118 a.allocator.PerformOperation( 119 []coldata.Vec{a.vec}, 120 func() { 121 if nulls.MaybeHasNulls() { 122 if sel != nil { 123 sel = sel[:inputLen] 124 for _, i := range sel { 125 _FIND_ANY_NOT_NULL(a, nulls, i, true) 126 } 127 } else { 128 col = execgen.SLICE(col, 0, inputLen) 129 for execgen.RANGE(i, col, 0, inputLen) { 130 _FIND_ANY_NOT_NULL(a, nulls, i, true) 131 } 132 } 133 } else { 134 if sel != nil { 135 sel = sel[:inputLen] 136 for _, i := range sel { 137 _FIND_ANY_NOT_NULL(a, nulls, i, false) 138 } 139 } else { 140 col = execgen.SLICE(col, 0, inputLen) 141 for execgen.RANGE(i, col, 0, inputLen) { 142 _FIND_ANY_NOT_NULL(a, nulls, i, false) 143 } 144 } 145 } 146 }, 147 ) 148 } 149 150 func (a *anyNotNull_TYPEAgg) Flush() { 151 // If we haven't found any non-nulls for this group so far, the output for 152 // this group should be null. 153 if !a.foundNonNullForCurrentGroup { 154 a.nulls.SetNull(a.curIdx) 155 } else { 156 execgen.SET(a.col, a.curIdx, a.curAgg) 157 } 158 a.curIdx++ 159 } 160 161 func (a *anyNotNull_TYPEAgg) HandleEmptyInputScalar() { 162 a.nulls.SetNull(0) 163 } 164 165 type anyNotNull_TYPEAggAlloc struct { 166 allocator *colmem.Allocator 167 allocSize int64 168 aggFuncs []anyNotNull_TYPEAgg 169 } 170 171 var _ aggregateFuncAlloc = &anyNotNull_TYPEAggAlloc{} 172 173 func (a *anyNotNull_TYPEAggAlloc) newAggFunc() aggregateFunc { 174 if len(a.aggFuncs) == 0 { 175 a.allocator.AdjustMemoryUsage(sizeOfAnyNotNull_TYPEAgg * a.allocSize) 176 a.aggFuncs = make([]anyNotNull_TYPEAgg, a.allocSize) 177 } 178 f := &a.aggFuncs[0] 179 f.allocator = a.allocator 180 a.aggFuncs = a.aggFuncs[1:] 181 return f 182 } 183 184 // {{end}} 185 // {{end}} 186 187 // {{/* 188 // _FIND_ANY_NOT_NULL finds a non-null value for the group that contains the ith 189 // row. If a non-null value was already found, then it does nothing. If this is 190 // the first row of a new group, and no non-nulls have been found for the 191 // current group, then the output for the current group is set to null. 192 func _FIND_ANY_NOT_NULL(a *anyNotNull_TYPEAgg, nulls *coldata.Nulls, i int, _HAS_NULLS bool) { // */}} 193 // {{define "findAnyNotNull" -}} 194 195 if a.groups[i] { 196 // The `a.curIdx` check is necessary because for the first 197 // group in the result set there is no "current group." 198 if a.curIdx >= 0 { 199 // If this is a new group, check if any non-nulls have been found for the 200 // current group. 201 if !a.foundNonNullForCurrentGroup { 202 a.nulls.SetNull(a.curIdx) 203 } else { 204 // {{with .Global}} 205 execgen.SET(a.col, a.curIdx, a.curAgg) 206 // {{end}} 207 } 208 } 209 a.curIdx++ 210 a.foundNonNullForCurrentGroup = false 211 } 212 var isNull bool 213 // {{if .HasNulls}} 214 isNull = nulls.NullAt(i) 215 // {{else}} 216 isNull = false 217 // {{end}} 218 if !a.foundNonNullForCurrentGroup && !isNull { 219 // If we haven't seen any non-nulls for the current group yet, and the 220 // current value is non-null, then we can pick the current value to be the 221 // output. 222 // {{with .Global}} 223 val := execgen.UNSAFEGET(col, i) 224 execgen.COPYVAL(a.curAgg, val) 225 // {{end}} 226 a.foundNonNullForCurrentGroup = true 227 } 228 // {{end}} 229 230 // {{/* 231 } // */}}