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