github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/colexec/vec_comparators_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 vec_comparators.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  	"fmt"
    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/colexecerror"
    29  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    30  )
    31  
    32  // Remove unused warning.
    33  var _ = execgen.UNSAFEGET
    34  
    35  // {{/*
    36  
    37  // Declarations to make the template compile properly.
    38  
    39  // _GOTYPESLICE is the template variable.
    40  type _GOTYPESLICE interface{}
    41  
    42  // _CANONICAL_TYPE_FAMILY is the template variable.
    43  const _CANONICAL_TYPE_FAMILY = types.UnknownFamily
    44  
    45  // _TYPE_WIDTH is the template variable.
    46  const _TYPE_WIDTH = 0
    47  
    48  // _COMPARE is the template equality function for assigning the first input
    49  // to the result of comparing second and third inputs.
    50  func _COMPARE(_, _, _, _, _ string) bool {
    51  	colexecerror.InternalError("")
    52  }
    53  
    54  // */}}
    55  
    56  // vecComparator is a helper for the ordered synchronizer. It stores multiple
    57  // column vectors of a single type and facilitates comparing values between
    58  // them.
    59  type vecComparator interface {
    60  	// compare compares values from two vectors. vecIdx is the index of the vector
    61  	// and valIdx is the index of the value in that vector to compare. Returns -1,
    62  	// 0, or 1.
    63  	compare(vecIdx1, vecIdx2 int, valIdx1, valIdx2 int) int
    64  
    65  	// set sets the value of the vector at dstVecIdx at index dstValIdx to the value
    66  	// at the vector at srcVecIdx at index srcValIdx.
    67  	// NOTE: whenever set is used, the caller is responsible for updating the
    68  	// memory accounts.
    69  	set(srcVecIdx, dstVecIdx int, srcValIdx, dstValIdx int)
    70  
    71  	// setVec updates the vector at idx.
    72  	setVec(idx int, vec coldata.Vec)
    73  }
    74  
    75  // {{range .}}
    76  // {{range .WidthOverloads}}
    77  type _TYPEVecComparator struct {
    78  	vecs  []_GOTYPESLICE
    79  	nulls []*coldata.Nulls
    80  }
    81  
    82  func (c *_TYPEVecComparator) compare(vecIdx1, vecIdx2 int, valIdx1, valIdx2 int) int {
    83  	n1 := c.nulls[vecIdx1].MaybeHasNulls() && c.nulls[vecIdx1].NullAt(valIdx1)
    84  	n2 := c.nulls[vecIdx2].MaybeHasNulls() && c.nulls[vecIdx2].NullAt(valIdx2)
    85  	if n1 && n2 {
    86  		return 0
    87  	} else if n1 {
    88  		return -1
    89  	} else if n2 {
    90  		return 1
    91  	}
    92  	left := execgen.UNSAFEGET(c.vecs[vecIdx1], valIdx1)
    93  	right := execgen.UNSAFEGET(c.vecs[vecIdx2], valIdx2)
    94  	var cmp int
    95  	_COMPARE(cmp, left, right, c.vecs[vecIdx1], c.vecs[vecIdx2])
    96  	return cmp
    97  }
    98  
    99  func (c *_TYPEVecComparator) setVec(idx int, vec coldata.Vec) {
   100  	c.vecs[idx] = vec._TYPE()
   101  	c.nulls[idx] = vec.Nulls()
   102  }
   103  
   104  func (c *_TYPEVecComparator) set(srcVecIdx, dstVecIdx int, srcIdx, dstIdx int) {
   105  	if c.nulls[srcVecIdx].MaybeHasNulls() && c.nulls[srcVecIdx].NullAt(srcIdx) {
   106  		c.nulls[dstVecIdx].SetNull(dstIdx)
   107  	} else {
   108  		c.nulls[dstVecIdx].UnsetNull(dstIdx)
   109  		// {{if eq .VecMethod "Bytes"}}
   110  		// Since flat Bytes cannot be set at arbitrary indices (data needs to be
   111  		// moved around), we use CopySlice to accept the performance hit.
   112  		// Specifically, this is a performance hit because we are overwriting the
   113  		// variable number of bytes in `dstVecIdx`, so we will have to either shift
   114  		// the bytes after that element left or right, depending on how long the
   115  		// source bytes slice is. Refer to the CopySlice comment for an example.
   116  		execgen.COPYSLICE(c.vecs[dstVecIdx], c.vecs[srcVecIdx], dstIdx, srcIdx, srcIdx+1)
   117  		// {{else}}
   118  		v := execgen.UNSAFEGET(c.vecs[srcVecIdx], srcIdx)
   119  		execgen.SET(c.vecs[dstVecIdx], dstIdx, v)
   120  		// {{end}}
   121  	}
   122  }
   123  
   124  // {{end}}
   125  // {{end}}
   126  
   127  func GetVecComparator(t *types.T, numVecs int) vecComparator {
   128  	switch typeconv.TypeFamilyToCanonicalTypeFamily(t.Family()) {
   129  	// {{range .}}
   130  	case _CANONICAL_TYPE_FAMILY:
   131  		switch t.Width() {
   132  		// {{range .WidthOverloads}}
   133  		case _TYPE_WIDTH:
   134  			return &_TYPEVecComparator{
   135  				vecs:  make([]_GOTYPESLICE, numVecs),
   136  				nulls: make([]*coldata.Nulls, numVecs),
   137  			}
   138  			// {{end}}
   139  		}
   140  		// {{end}}
   141  	}
   142  	colexecerror.InternalError(fmt.Sprintf("unhandled type %s", t))
   143  	// This code is unreachable, but the compiler cannot infer that.
   144  	return nil
   145  }