github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/col/coldata/vec_tmpl.go (about)

     1  // Copyright 2018 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.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 coldata
    21  
    22  import (
    23  	"fmt"
    24  
    25  	"github.com/cockroachdb/cockroach/pkg/sql/colexec/execgen"
    26  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    27  )
    28  
    29  // {{/*
    30  
    31  // _GOTYPESLICE is the template variable.
    32  type _GOTYPESLICE interface{}
    33  
    34  // _CANONICAL_TYPE_FAMILY is the template variable.
    35  const _CANONICAL_TYPE_FAMILY = types.UnknownFamily
    36  
    37  // _TYPE_WIDTH is the template variable.
    38  const _TYPE_WIDTH = 0
    39  
    40  // */}}
    41  
    42  func (m *memColumn) Append(args SliceArgs) {
    43  	switch m.CanonicalTypeFamily() {
    44  	// {{range .}}
    45  	case _CANONICAL_TYPE_FAMILY:
    46  		switch m.t.Width() {
    47  		// {{range .WidthOverloads}}
    48  		case _TYPE_WIDTH:
    49  			fromCol := args.Src.TemplateType()
    50  			toCol := m.TemplateType()
    51  			// NOTE: it is unfortunate that we always append whole slice without paying
    52  			// attention to whether the values are NULL. However, if we do start paying
    53  			// attention, the performance suffers dramatically, so we choose to copy
    54  			// over "actual" as well as "garbage" values.
    55  			if args.Sel == nil {
    56  				execgen.APPENDSLICE(toCol, fromCol, args.DestIdx, args.SrcStartIdx, args.SrcEndIdx)
    57  			} else {
    58  				sel := args.Sel[args.SrcStartIdx:args.SrcEndIdx]
    59  				// {{if eq .VecMethod "Bytes"}}
    60  				// We need to truncate toCol before appending to it, so in case of Bytes,
    61  				// we append an empty slice.
    62  				execgen.APPENDSLICE(toCol, toCol, args.DestIdx, 0, 0)
    63  				// We will be getting all values below to be appended, regardless of
    64  				// whether the value is NULL. It is possible that Bytes' invariant of
    65  				// non-decreasing offsets on the source is currently not maintained, so
    66  				// we explicitly enforce it.
    67  				maxIdx := 0
    68  				for _, selIdx := range sel {
    69  					if selIdx > maxIdx {
    70  						maxIdx = selIdx
    71  					}
    72  				}
    73  				fromCol.UpdateOffsetsToBeNonDecreasing(maxIdx + 1)
    74  				// {{else}}
    75  				toCol = execgen.SLICE(toCol, 0, args.DestIdx)
    76  				// {{end}}
    77  				for _, selIdx := range sel {
    78  					val := execgen.UNSAFEGET(fromCol, selIdx)
    79  					execgen.APPENDVAL(toCol, val)
    80  				}
    81  			}
    82  			m.nulls.set(args)
    83  			m.col = toCol
    84  			// {{end}}
    85  		}
    86  		// {{end}}
    87  	default:
    88  		panic(fmt.Sprintf("unhandled type %s", m.t))
    89  	}
    90  }
    91  
    92  // {{/*
    93  func _COPY_WITH_SEL(
    94  	m *memColumn, args CopySliceArgs, fromCol, toCol _GOTYPESLICE, sel interface{}, _SEL_ON_DEST bool,
    95  ) { // */}}
    96  	// {{define "copyWithSel" -}}
    97  	if args.Src.MaybeHasNulls() {
    98  		nulls := args.Src.Nulls()
    99  		for i, selIdx := range sel[args.SrcStartIdx:args.SrcEndIdx] {
   100  			if nulls.NullAt(selIdx) {
   101  				// {{if .SelOnDest}}
   102  				// Remove an unused warning in some cases.
   103  				_ = i
   104  				m.nulls.SetNull(selIdx)
   105  				// {{else}}
   106  				m.nulls.SetNull(i + args.DestIdx)
   107  				// {{end}}
   108  			} else {
   109  				// {{with .Global}}
   110  				v := execgen.UNSAFEGET(fromCol, selIdx)
   111  				// {{end}}
   112  				// {{if .SelOnDest}}
   113  				m.nulls.UnsetNull(selIdx)
   114  				// {{with .Global}}
   115  				execgen.SET(toCol, selIdx, v)
   116  				// {{end}}
   117  				// {{else}}
   118  				// {{with .Global}}
   119  				execgen.SET(toCol, i+args.DestIdx, v)
   120  				// {{end}}
   121  				// {{end}}
   122  			}
   123  		}
   124  		return
   125  	}
   126  	// No Nulls.
   127  	for i := range sel[args.SrcStartIdx:args.SrcEndIdx] {
   128  		selIdx := sel[args.SrcStartIdx+i]
   129  		// {{with .Global}}
   130  		v := execgen.UNSAFEGET(fromCol, selIdx)
   131  		// {{end}}
   132  		// {{if .SelOnDest}}
   133  		// {{with .Global}}
   134  		execgen.SET(toCol, selIdx, v)
   135  		// {{end}}
   136  		// {{else}}
   137  		// {{with .Global}}
   138  		execgen.SET(toCol, i+args.DestIdx, v)
   139  		// {{end}}
   140  		// {{end}}
   141  	}
   142  	// {{end}}
   143  	// {{/*
   144  }
   145  
   146  // */}}
   147  
   148  func (m *memColumn) Copy(args CopySliceArgs) {
   149  	if !args.SelOnDest {
   150  		// We're about to overwrite this entire range, so unset all the nulls.
   151  		m.Nulls().UnsetNullRange(args.DestIdx, args.DestIdx+(args.SrcEndIdx-args.SrcStartIdx))
   152  	}
   153  	// } else {
   154  	// SelOnDest indicates that we're applying the input selection vector as a lens
   155  	// into the output vector as well. We'll set the non-nulls by hand below.
   156  	// }
   157  
   158  	switch m.CanonicalTypeFamily() {
   159  	// {{range .}}
   160  	case _CANONICAL_TYPE_FAMILY:
   161  		switch m.t.Width() {
   162  		// {{range .WidthOverloads}}
   163  		case _TYPE_WIDTH:
   164  			fromCol := args.Src.TemplateType()
   165  			toCol := m.TemplateType()
   166  			if args.Sel != nil {
   167  				sel := args.Sel
   168  				if args.SelOnDest {
   169  					_COPY_WITH_SEL(m, args, sel, toCol, fromCol, true)
   170  				} else {
   171  					_COPY_WITH_SEL(m, args, sel, toCol, fromCol, false)
   172  				}
   173  				return
   174  			}
   175  			// No Sel.
   176  			execgen.COPYSLICE(toCol, fromCol, args.DestIdx, args.SrcStartIdx, args.SrcEndIdx)
   177  			m.nulls.set(args.SliceArgs)
   178  			// {{end}}
   179  		}
   180  		// {{end}}
   181  	default:
   182  		panic(fmt.Sprintf("unhandled type %s", m.t))
   183  	}
   184  }
   185  
   186  func (m *memColumn) Window(start int, end int) Vec {
   187  	switch m.CanonicalTypeFamily() {
   188  	// {{range .}}
   189  	case _CANONICAL_TYPE_FAMILY:
   190  		switch m.t.Width() {
   191  		// {{range .WidthOverloads}}
   192  		case _TYPE_WIDTH:
   193  			col := m.TemplateType()
   194  			return &memColumn{
   195  				t:                   m.t,
   196  				canonicalTypeFamily: m.canonicalTypeFamily,
   197  				col:                 execgen.WINDOW(col, start, end),
   198  				nulls:               m.nulls.Slice(start, end),
   199  			}
   200  			// {{end}}
   201  		}
   202  		// {{end}}
   203  	}
   204  	panic(fmt.Sprintf("unhandled type %s", m.t))
   205  }
   206  
   207  // SetValueAt is an inefficient helper to set the value in a Vec when the type
   208  // is unknown.
   209  func SetValueAt(v Vec, elem interface{}, rowIdx int) {
   210  	switch t := v.Type(); v.CanonicalTypeFamily() {
   211  	// {{range .}}
   212  	case _CANONICAL_TYPE_FAMILY:
   213  		switch t.Width() {
   214  		// {{range .WidthOverloads}}
   215  		case _TYPE_WIDTH:
   216  			target := v.TemplateType()
   217  			newVal := elem.(_GOTYPE)
   218  			execgen.SET(target, rowIdx, newVal)
   219  			// {{end}}
   220  		}
   221  		// {{end}}
   222  	default:
   223  		panic(fmt.Sprintf("unhandled type %s", t))
   224  	}
   225  }
   226  
   227  // GetValueAt is an inefficient helper to get the value in a Vec when the type
   228  // is unknown.
   229  func GetValueAt(v Vec, rowIdx int) interface{} {
   230  	t := v.Type()
   231  	switch v.CanonicalTypeFamily() {
   232  	// {{range .}}
   233  	case _CANONICAL_TYPE_FAMILY:
   234  		switch t.Width() {
   235  		// {{range .WidthOverloads}}
   236  		case _TYPE_WIDTH:
   237  			target := v.TemplateType()
   238  			return execgen.UNSAFEGET(target, rowIdx)
   239  			// {{end}}
   240  		}
   241  		// {{end}}
   242  	}
   243  	panic(fmt.Sprintf("unhandled type %s", t))
   244  }