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  }