github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/colexec/proj_non_const_ops_tmpl.go (about) 1 // Copyright 2019 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 proj_non_const_ops.eg.go. It's 15 // formatted in a special way, so it's both valid Go and a valid text/template 16 // input. This permits editing this file with editor support. 17 // 18 // */}} 19 20 package colexec 21 22 import ( 23 "context" 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/colexecbase" 29 "github.com/cockroachdb/cockroach/pkg/sql/colexecbase/colexecerror" 30 "github.com/cockroachdb/cockroach/pkg/sql/colmem" 31 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 32 "github.com/cockroachdb/cockroach/pkg/sql/types" 33 "github.com/cockroachdb/errors" 34 ) 35 36 // Remove unused warning. 37 var _ = execgen.UNSAFEGET 38 39 // {{/* 40 // Declarations to make the template compile properly. 41 42 // _LEFT_CANONICAL_TYPE_FAMILY is the template variable. 43 const _LEFT_CANONICAL_TYPE_FAMILY = types.UnknownFamily 44 45 // _LEFT_TYPE_WIDTH is the template variable. 46 const _LEFT_TYPE_WIDTH = 0 47 48 // _RIGHT_CANONICAL_TYPE_FAMILY is the template variable. 49 const _RIGHT_CANONICAL_TYPE_FAMILY = types.UnknownFamily 50 51 // _RIGHT_TYPE_WIDTH is the template variable. 52 const _RIGHT_TYPE_WIDTH = 0 53 54 // _ASSIGN is the template function for assigning the first input to the result 55 // of computation an operation on the second and the third inputs. 56 func _ASSIGN(_, _, _, _, _, _ interface{}) { 57 colexecerror.InternalError("") 58 } 59 60 // _L_UNSAFEGET is the template function that will be replaced by 61 // "execgen.UNSAFEGET" which uses _L_TYP. 62 func _L_UNSAFEGET(_, _ interface{}) interface{} { 63 colexecerror.InternalError("") 64 } 65 66 // _R_UNSAFEGET is the template function that will be replaced by 67 // "execgen.UNSAFEGET" which uses _R_TYP. 68 func _R_UNSAFEGET(_, _ interface{}) interface{} { 69 colexecerror.InternalError("") 70 } 71 72 // _RETURN_UNSAFEGET is the template function that will be replaced by 73 // "execgen.UNSAFEGET" which uses _RET_TYP. 74 func _RETURN_UNSAFEGET(_, _ interface{}) interface{} { 75 colexecerror.InternalError("") 76 } 77 78 // */}} 79 80 // projConstOpBase contains all of the fields for projections with a constant, 81 // except for the constant itself. 82 // NOTE: this struct should be declared in proj_const_ops_tmpl.go, but if we do 83 // so, it'll be redeclared because we execute that template twice. To go 84 // around the problem we specify it here. 85 type projConstOpBase struct { 86 OneInputNode 87 allocator *colmem.Allocator 88 colIdx int 89 outputIdx int 90 overloadHelper overloadHelper 91 } 92 93 // projOpBase contains all of the fields for non-constant projections. 94 type projOpBase struct { 95 OneInputNode 96 allocator *colmem.Allocator 97 col1Idx int 98 col2Idx int 99 outputIdx int 100 overloadHelper overloadHelper 101 } 102 103 // {{define "projOp"}} 104 105 type _OP_NAME struct { 106 projOpBase 107 } 108 109 func (p _OP_NAME) Next(ctx context.Context) coldata.Batch { 110 // In order to inline the templated code of overloads, we need to have a 111 // `_overloadHelper` local variable of type `overloadHelper`. 112 _overloadHelper := p.overloadHelper 113 // However, the scratch is not used in all of the projection operators, so 114 // we add this to go around "unused" error. 115 _ = _overloadHelper 116 batch := p.input.Next(ctx) 117 n := batch.Length() 118 if n == 0 { 119 return coldata.ZeroBatch 120 } 121 projVec := batch.ColVec(p.outputIdx) 122 if projVec.MaybeHasNulls() { 123 // We need to make sure that there are no left over null values in the 124 // output vector. 125 projVec.Nulls().UnsetNulls() 126 } 127 projCol := projVec._RET_TYP() 128 vec1 := batch.ColVec(p.col1Idx) 129 vec2 := batch.ColVec(p.col2Idx) 130 col1 := vec1._L_TYP() 131 col2 := vec2._R_TYP() 132 if vec1.Nulls().MaybeHasNulls() || vec2.Nulls().MaybeHasNulls() { 133 _SET_PROJECTION(true) 134 } else { 135 _SET_PROJECTION(false) 136 } 137 138 // Although we didn't change the length of the batch, it is necessary to set 139 // the length anyway (this helps maintaining the invariant of flat bytes). 140 batch.SetLength(n) 141 return batch 142 } 143 144 func (p _OP_NAME) Init() { 145 p.input.Init() 146 } 147 148 // {{end}} 149 150 // {{/* 151 func _SET_PROJECTION(_HAS_NULLS bool) { 152 // */}} 153 // {{define "setProjection" -}} 154 // {{$hasNulls := $.HasNulls}} 155 // {{with $.Overload}} 156 // {{if _HAS_NULLS}} 157 col1Nulls := vec1.Nulls() 158 col2Nulls := vec2.Nulls() 159 // {{end}} 160 if sel := batch.Selection(); sel != nil { 161 sel = sel[:n] 162 for _, i := range sel { 163 _SET_SINGLE_TUPLE_PROJECTION(_HAS_NULLS) 164 } 165 } else { 166 // {{if not (eq .Left.VecMethod "Bytes")}} 167 // {{/* Slice is a noop for Bytes type, so colLen below might contain an 168 // incorrect value. In order to keep bounds check elimination for all other 169 // types, we simply omit this code snippet for Bytes. */}} 170 col1 = execgen.SLICE(col1, 0, n) 171 colLen := execgen.LEN(col1) 172 _ = _RETURN_UNSAFEGET(projCol, colLen-1) 173 _ = _R_UNSAFEGET(col2, colLen-1) 174 // {{end}} 175 for execgen.RANGE(i, col1, 0, n) { 176 _SET_SINGLE_TUPLE_PROJECTION(_HAS_NULLS) 177 } 178 } 179 // {{if _HAS_NULLS}} 180 projVec.SetNulls(col1Nulls.Or(col2Nulls)) 181 // {{end}} 182 // {{end}} 183 // {{end}} 184 // {{/* 185 } 186 187 // */}} 188 189 // {{/* 190 func _SET_SINGLE_TUPLE_PROJECTION(_HAS_NULLS bool) { // */}} 191 // {{define "setSingleTupleProjection" -}} 192 // {{$hasNulls := $.HasNulls}} 193 // {{with $.Overload}} 194 // {{if _HAS_NULLS}} 195 if !col1Nulls.NullAt(i) && !col2Nulls.NullAt(i) { 196 // We only want to perform the projection operation if both values are not 197 // null. 198 // {{end}} 199 arg1 := _L_UNSAFEGET(col1, i) 200 arg2 := _R_UNSAFEGET(col2, i) 201 _ASSIGN(projCol[i], arg1, arg2, projCol, col1, col2) 202 // {{if _HAS_NULLS}} 203 } 204 // {{end}} 205 // {{end}} 206 // {{end}} 207 // {{/* 208 } 209 210 // */}} 211 212 // {{range .BinOps}} 213 // {{range .LeftFamilies}} 214 // {{range .LeftWidths}} 215 // {{range .RightFamilies}} 216 // {{range .RightWidths}} 217 218 // {{template "projOp" .}} 219 220 // {{end}} 221 // {{end}} 222 // {{end}} 223 // {{end}} 224 // {{end}} 225 226 // {{range .CmpOps}} 227 // {{range .LeftFamilies}} 228 // {{range .LeftWidths}} 229 // {{range .RightFamilies}} 230 // {{range .RightWidths}} 231 232 // {{template "projOp" .}} 233 234 // {{end}} 235 // {{end}} 236 // {{end}} 237 // {{end}} 238 // {{end}} 239 240 // GetProjectionOperator returns the appropriate projection operator for the 241 // given left and right column types and operation. 242 func GetProjectionOperator( 243 allocator *colmem.Allocator, 244 leftType *types.T, 245 rightType *types.T, 246 outputType *types.T, 247 op tree.Operator, 248 input colexecbase.Operator, 249 col1Idx int, 250 col2Idx int, 251 outputIdx int, 252 overloadHelper overloadHelper, 253 ) (colexecbase.Operator, error) { 254 input = newVectorTypeEnforcer(allocator, input, outputType, outputIdx) 255 projOpBase := projOpBase{ 256 OneInputNode: NewOneInputNode(input), 257 allocator: allocator, 258 col1Idx: col1Idx, 259 col2Idx: col2Idx, 260 outputIdx: outputIdx, 261 overloadHelper: overloadHelper, 262 } 263 264 switch op.(type) { 265 case tree.BinaryOperator: 266 switch op { 267 // {{range .BinOps}} 268 case tree._NAME: 269 switch typeconv.TypeFamilyToCanonicalTypeFamily(leftType.Family()) { 270 // {{range .LeftFamilies}} 271 case _LEFT_CANONICAL_TYPE_FAMILY: 272 switch leftType.Width() { 273 // {{range .LeftWidths}} 274 case _LEFT_TYPE_WIDTH: 275 switch typeconv.TypeFamilyToCanonicalTypeFamily(rightType.Family()) { 276 // {{range .RightFamilies}} 277 case _RIGHT_CANONICAL_TYPE_FAMILY: 278 switch rightType.Width() { 279 // {{range .RightWidths}} 280 case _RIGHT_TYPE_WIDTH: 281 return &_OP_NAME{projOpBase: projOpBase}, nil 282 // {{end}} 283 } 284 // {{end}} 285 } 286 // {{end}} 287 } 288 // {{end}} 289 } 290 // {{end}} 291 } 292 case tree.ComparisonOperator: 293 switch op { 294 // {{range .CmpOps}} 295 case tree._NAME: 296 switch typeconv.TypeFamilyToCanonicalTypeFamily(leftType.Family()) { 297 // {{range .LeftFamilies}} 298 case _LEFT_CANONICAL_TYPE_FAMILY: 299 switch leftType.Width() { 300 // {{range .LeftWidths}} 301 case _LEFT_TYPE_WIDTH: 302 switch typeconv.TypeFamilyToCanonicalTypeFamily(rightType.Family()) { 303 // {{range .RightFamilies}} 304 case _RIGHT_CANONICAL_TYPE_FAMILY: 305 switch rightType.Width() { 306 // {{range .RightWidths}} 307 case _RIGHT_TYPE_WIDTH: 308 return &_OP_NAME{projOpBase: projOpBase}, nil 309 // {{end}} 310 } 311 // {{end}} 312 } 313 // {{end}} 314 } 315 // {{end}} 316 } 317 // {{end}} 318 } 319 } 320 return nil, errors.Errorf("couldn't find overload for %s %s %s", leftType.Name(), op, rightType.Name()) 321 }