github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/colexec/select_in_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 select_in.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 "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 warnings. 37 var ( 38 _ = execgen.UNSAFEGET 39 _ = colexecerror.InternalError 40 ) 41 42 // {{/* 43 44 type _GOTYPESLICE interface{} 45 type _GOTYPE interface{} 46 type _TYPE interface{} 47 48 // _CANONICAL_TYPE_FAMILY is the template variable. 49 const _CANONICAL_TYPE_FAMILY = types.UnknownFamily 50 51 // _TYPE_WIDTH is the template variable. 52 const _TYPE_WIDTH = 0 53 54 func _ASSIGN_EQ(_, _, _, _, _, _ interface{}) int { 55 colexecerror.InternalError("") 56 } 57 58 // */}} 59 60 // Enum used to represent comparison results. 61 type comparisonResult int 62 63 const ( 64 siTrue comparisonResult = iota 65 siFalse 66 siNull 67 ) 68 69 func GetInProjectionOperator( 70 allocator *colmem.Allocator, 71 t *types.T, 72 input colexecbase.Operator, 73 colIdx int, 74 resultIdx int, 75 datumTuple *tree.DTuple, 76 negate bool, 77 ) (colexecbase.Operator, error) { 78 input = newVectorTypeEnforcer(allocator, input, types.Bool, resultIdx) 79 var err error 80 switch typeconv.TypeFamilyToCanonicalTypeFamily(t.Family()) { 81 // {{range .}} 82 case _CANONICAL_TYPE_FAMILY: 83 switch t.Width() { 84 // {{range .WidthOverloads}} 85 case _TYPE_WIDTH: 86 obj := &projectInOp_TYPE{ 87 OneInputNode: NewOneInputNode(input), 88 allocator: allocator, 89 colIdx: colIdx, 90 outputIdx: resultIdx, 91 negate: negate, 92 } 93 obj.filterRow, obj.hasNulls, err = fillDatumRow_TYPE(t, datumTuple) 94 if err != nil { 95 return nil, err 96 } 97 return obj, nil 98 // {{end}} 99 } 100 // {{end}} 101 } 102 return nil, errors.Errorf("unhandled type: %s", t.Name()) 103 } 104 105 func GetInOperator( 106 t *types.T, input colexecbase.Operator, colIdx int, datumTuple *tree.DTuple, negate bool, 107 ) (colexecbase.Operator, error) { 108 var err error 109 switch typeconv.TypeFamilyToCanonicalTypeFamily(t.Family()) { 110 // {{range .}} 111 case _CANONICAL_TYPE_FAMILY: 112 switch t.Width() { 113 // {{range .WidthOverloads}} 114 case _TYPE_WIDTH: 115 obj := &selectInOp_TYPE{ 116 OneInputNode: NewOneInputNode(input), 117 colIdx: colIdx, 118 negate: negate, 119 } 120 obj.filterRow, obj.hasNulls, err = fillDatumRow_TYPE(t, datumTuple) 121 if err != nil { 122 return nil, err 123 } 124 return obj, nil 125 // {{end}} 126 } 127 // {{end}} 128 } 129 return nil, errors.Errorf("unhandled type: %s", t.Name()) 130 } 131 132 // {{range .}} 133 // {{range .WidthOverloads}} 134 135 type selectInOp_TYPE struct { 136 OneInputNode 137 colIdx int 138 filterRow []_GOTYPE 139 hasNulls bool 140 negate bool 141 } 142 143 var _ colexecbase.Operator = &selectInOp_TYPE{} 144 145 type projectInOp_TYPE struct { 146 OneInputNode 147 allocator *colmem.Allocator 148 colIdx int 149 outputIdx int 150 filterRow []_GOTYPE 151 hasNulls bool 152 negate bool 153 } 154 155 var _ colexecbase.Operator = &projectInOp_TYPE{} 156 157 func fillDatumRow_TYPE(t *types.T, datumTuple *tree.DTuple) ([]_GOTYPE, bool, error) { 158 conv := getDatumToPhysicalFn(t) 159 var result []_GOTYPE 160 hasNulls := false 161 for _, d := range datumTuple.D { 162 if d == tree.DNull { 163 hasNulls = true 164 } else { 165 convRaw, err := conv(d) 166 if err != nil { 167 return nil, false, err 168 } 169 converted := convRaw.(_GOTYPE) 170 result = append(result, converted) 171 } 172 } 173 return result, hasNulls, nil 174 } 175 176 func cmpIn_TYPE( 177 targetElem _GOTYPE, targetCol _GOTYPESLICE, filterRow []_GOTYPE, hasNulls bool, 178 ) comparisonResult { 179 for i := range filterRow { 180 var cmp bool 181 _ASSIGN_EQ(cmp, targetElem, filterRow[i], _, targetCol, _) 182 if cmp { 183 return siTrue 184 } 185 } 186 if hasNulls { 187 return siNull 188 } else { 189 return siFalse 190 } 191 } 192 193 func (si *selectInOp_TYPE) Init() { 194 si.input.Init() 195 } 196 197 func (pi *projectInOp_TYPE) Init() { 198 pi.input.Init() 199 } 200 201 func (si *selectInOp_TYPE) Next(ctx context.Context) coldata.Batch { 202 for { 203 batch := si.input.Next(ctx) 204 if batch.Length() == 0 { 205 return coldata.ZeroBatch 206 } 207 208 vec := batch.ColVec(si.colIdx) 209 col := vec.TemplateType() 210 var idx int 211 n := batch.Length() 212 213 compVal := siTrue 214 if si.negate { 215 compVal = siFalse 216 } 217 218 if vec.MaybeHasNulls() { 219 nulls := vec.Nulls() 220 if sel := batch.Selection(); sel != nil { 221 sel = sel[:n] 222 for _, i := range sel { 223 v := execgen.UNSAFEGET(col, i) 224 if !nulls.NullAt(i) && cmpIn_TYPE(v, col, si.filterRow, si.hasNulls) == compVal { 225 sel[idx] = i 226 idx++ 227 } 228 } 229 } else { 230 batch.SetSelection(true) 231 sel := batch.Selection() 232 col = execgen.SLICE(col, 0, n) 233 for execgen.RANGE(i, col, 0, n) { 234 v := execgen.UNSAFEGET(col, i) 235 if !nulls.NullAt(i) && cmpIn_TYPE(v, col, si.filterRow, si.hasNulls) == compVal { 236 sel[idx] = i 237 idx++ 238 } 239 } 240 } 241 } else { 242 if sel := batch.Selection(); sel != nil { 243 sel = sel[:n] 244 for _, i := range sel { 245 v := execgen.UNSAFEGET(col, i) 246 if cmpIn_TYPE(v, col, si.filterRow, si.hasNulls) == compVal { 247 sel[idx] = i 248 idx++ 249 } 250 } 251 } else { 252 batch.SetSelection(true) 253 sel := batch.Selection() 254 col = execgen.SLICE(col, 0, n) 255 for execgen.RANGE(i, col, 0, n) { 256 v := execgen.UNSAFEGET(col, i) 257 if cmpIn_TYPE(v, col, si.filterRow, si.hasNulls) == compVal { 258 sel[idx] = i 259 idx++ 260 } 261 } 262 } 263 } 264 265 if idx > 0 { 266 batch.SetLength(idx) 267 return batch 268 } 269 } 270 } 271 272 func (pi *projectInOp_TYPE) Next(ctx context.Context) coldata.Batch { 273 batch := pi.input.Next(ctx) 274 if batch.Length() == 0 { 275 return coldata.ZeroBatch 276 } 277 278 vec := batch.ColVec(pi.colIdx) 279 col := vec.TemplateType() 280 281 projVec := batch.ColVec(pi.outputIdx) 282 projCol := projVec.Bool() 283 projNulls := projVec.Nulls() 284 if projVec.MaybeHasNulls() { 285 // We need to make sure that there are no left over null values in the 286 // output vector. 287 projNulls.UnsetNulls() 288 } 289 290 n := batch.Length() 291 292 cmpVal := siTrue 293 if pi.negate { 294 cmpVal = siFalse 295 } 296 297 if vec.MaybeHasNulls() { 298 nulls := vec.Nulls() 299 if sel := batch.Selection(); sel != nil { 300 sel = sel[:n] 301 for _, i := range sel { 302 if nulls.NullAt(i) { 303 projNulls.SetNull(i) 304 } else { 305 v := execgen.UNSAFEGET(col, i) 306 cmpRes := cmpIn_TYPE(v, col, pi.filterRow, pi.hasNulls) 307 if cmpRes == siNull { 308 projNulls.SetNull(i) 309 } else { 310 projCol[i] = cmpRes == cmpVal 311 } 312 } 313 } 314 } else { 315 col = execgen.SLICE(col, 0, n) 316 for execgen.RANGE(i, col, 0, n) { 317 if nulls.NullAt(i) { 318 projNulls.SetNull(i) 319 } else { 320 v := execgen.UNSAFEGET(col, i) 321 cmpRes := cmpIn_TYPE(v, col, pi.filterRow, pi.hasNulls) 322 if cmpRes == siNull { 323 projNulls.SetNull(i) 324 } else { 325 projCol[i] = cmpRes == cmpVal 326 } 327 } 328 } 329 } 330 } else { 331 if sel := batch.Selection(); sel != nil { 332 sel = sel[:n] 333 for _, i := range sel { 334 v := execgen.UNSAFEGET(col, i) 335 cmpRes := cmpIn_TYPE(v, col, pi.filterRow, pi.hasNulls) 336 if cmpRes == siNull { 337 projNulls.SetNull(i) 338 } else { 339 projCol[i] = cmpRes == cmpVal 340 } 341 } 342 } else { 343 col = execgen.SLICE(col, 0, n) 344 for execgen.RANGE(i, col, 0, n) { 345 v := execgen.UNSAFEGET(col, i) 346 cmpRes := cmpIn_TYPE(v, col, pi.filterRow, pi.hasNulls) 347 if cmpRes == siNull { 348 projNulls.SetNull(i) 349 } else { 350 projCol[i] = cmpRes == cmpVal 351 } 352 } 353 } 354 } 355 return batch 356 } 357 358 // {{end}} 359 // {{end}}