github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/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  //go:build execgen_template
    13  // +build execgen_template
    14  
    15  //
    16  // This file is the execgen template for vec.eg.go. It's formatted in a
    17  // special way, so it's both valid Go and a valid text/template input. This
    18  // permits editing this file with editor support.
    19  //
    20  // */}}
    21  
    22  package coldata
    23  
    24  import (
    25  	"fmt"
    26  
    27  	"github.com/cockroachdb/apd/v3"
    28  	"github.com/cockroachdb/cockroachdb-parser/pkg/col/typeconv"
    29  	"github.com/cockroachdb/cockroachdb-parser/pkg/sql/colexec/execgen"
    30  	"github.com/cockroachdb/cockroachdb-parser/pkg/sql/colexecerror"
    31  	"github.com/cockroachdb/cockroachdb-parser/pkg/sql/types"
    32  	"github.com/cockroachdb/cockroachdb-parser/pkg/util/duration"
    33  	"github.com/cockroachdb/cockroachdb-parser/pkg/util/json"
    34  	"github.com/cockroachdb/errors"
    35  )
    36  
    37  // Workaround for bazel auto-generated code. goimports does not automatically
    38  // pick up the right packages when run within the bazel sandbox.
    39  var (
    40  	_ = typeconv.DatumVecCanonicalTypeFamily
    41  	_ apd.Context
    42  	_ duration.Duration
    43  	_ json.JSON
    44  	_ = colexecerror.InternalError
    45  	_ = errors.AssertionFailedf
    46  )
    47  
    48  // {{/*
    49  
    50  // _GOTYPESLICE is the template variable.
    51  type _GOTYPESLICE interface{}
    52  
    53  // _CANONICAL_TYPE_FAMILY is the template variable.
    54  const _CANONICAL_TYPE_FAMILY = types.UnknownFamily
    55  
    56  // _TYPE_WIDTH is the template variable.
    57  const _TYPE_WIDTH = 0
    58  
    59  // */}}
    60  
    61  // TypedVecs represents a slice of Vecs that have been converted into the typed
    62  // columns. The idea is that every Vec is stored both in Vecs slice as well as
    63  // in the typed slice, in order. Components that know the type of the vector
    64  // they are working with can then access the typed column directly, avoiding
    65  // expensive type casts.
    66  type TypedVecs struct {
    67  	Vecs  []Vec
    68  	Nulls []*Nulls
    69  
    70  	// Fields below need to be accessed by an index mapped via ColsMap.
    71  	// {{range .}}
    72  	// {{range .WidthOverloads}}
    73  	_TYPECols []_GOTYPESLICE
    74  	// {{end}}
    75  	// {{end}}
    76  	// ColsMap contains the positions of the corresponding vectors in the slice
    77  	// for the same types. For example, if we have a batch with
    78  	//   types = [Int64, Int64, Bool, Bytes, Bool, Int64],
    79  	// then ColsMap will be
    80  	//                      [0, 1, 0, 0, 1, 2]
    81  	//                       ^  ^  ^  ^  ^  ^
    82  	//                       |  |  |  |  |  |
    83  	//                       |  |  |  |  |  3rd among all Int64's
    84  	//                       |  |  |  |  2nd among all Bool's
    85  	//                       |  |  |  1st among all Bytes's
    86  	//                       |  |  1st among all Bool's
    87  	//                       |  2nd among all Int64's
    88  	//                       1st among all Int64's
    89  	ColsMap []int
    90  }
    91  
    92  // SetBatch updates TypedVecs to represent all vectors from batch.
    93  func (v *TypedVecs) SetBatch(batch Batch) {
    94  	v.Vecs = batch.ColVecs()
    95  	if cap(v.Nulls) < len(v.Vecs) {
    96  		v.Nulls = make([]*Nulls, len(v.Vecs))
    97  		v.ColsMap = make([]int, len(v.Vecs))
    98  	} else {
    99  		v.Nulls = v.Nulls[:len(v.Vecs)]
   100  		v.ColsMap = v.ColsMap[:len(v.Vecs)]
   101  	}
   102  	// {{range .}}
   103  	// {{range .WidthOverloads}}
   104  	v._TYPECols = v._TYPECols[:0]
   105  	// {{end}}
   106  	// {{end}}
   107  	for i, vec := range v.Vecs {
   108  		v.Nulls[i] = vec.Nulls()
   109  		switch vec.CanonicalTypeFamily() {
   110  		// {{range .}}
   111  		case _CANONICAL_TYPE_FAMILY:
   112  			switch vec.Type().Width() {
   113  			// {{range .WidthOverloads}}
   114  			case _TYPE_WIDTH:
   115  				v.ColsMap[i] = len(v._TYPECols)
   116  				v._TYPECols = append(v._TYPECols, vec.TemplateType())
   117  				// {{end}}
   118  			}
   119  		// {{end}}
   120  		default:
   121  			colexecerror.InternalError(errors.AssertionFailedf("unhandled type %s", vec.Type()))
   122  		}
   123  	}
   124  }
   125  
   126  // Reset performs a deep reset of v while keeping the references to the slices.
   127  func (v *TypedVecs) Reset() {
   128  	v.Vecs = nil
   129  	for i := range v.Nulls {
   130  		v.Nulls[i] = nil
   131  	}
   132  	// {{range .}}
   133  	// {{range .WidthOverloads}}
   134  	for i := range v._TYPECols {
   135  		v._TYPECols[i] = nil
   136  	}
   137  	// {{end}}
   138  	// {{end}}
   139  }
   140  
   141  func (m *memColumn) Append(args SliceArgs) {
   142  	switch m.CanonicalTypeFamily() {
   143  	// {{range .}}
   144  	case _CANONICAL_TYPE_FAMILY:
   145  		switch m.t.Width() {
   146  		// {{range .WidthOverloads}}
   147  		case _TYPE_WIDTH:
   148  			fromCol := args.Src.TemplateType()
   149  			toCol := m.TemplateType()
   150  			// NOTE: it is unfortunate that we always append whole slice without paying
   151  			// attention to whether the values are NULL. However, if we do start paying
   152  			// attention, the performance suffers dramatically, so we choose to copy
   153  			// over "actual" as well as "garbage" values.
   154  			if args.Sel == nil {
   155  				execgen.APPENDSLICE(toCol, fromCol, args.DestIdx, args.SrcStartIdx, args.SrcEndIdx)
   156  			} else {
   157  				sel := args.Sel[args.SrcStartIdx:args.SrcEndIdx]
   158  				// {{if .IsBytesLike }}
   159  				toCol.appendSliceWithSel(fromCol, args.DestIdx, sel)
   160  				// {{else}}
   161  				// {{/* Here Window means slicing which allows us to use APPENDVAL below. */}}
   162  				toCol = toCol.Window(0, args.DestIdx)
   163  				for _, selIdx := range sel {
   164  					val := fromCol.Get(selIdx)
   165  					execgen.APPENDVAL(toCol, val)
   166  				}
   167  				// {{end}}
   168  			}
   169  			m.nulls.set(args)
   170  			m.col = toCol
   171  			// {{end}}
   172  		}
   173  		// {{end}}
   174  	default:
   175  		panic(fmt.Sprintf("unhandled type %s", m.t))
   176  	}
   177  }
   178  
   179  func (m *memColumn) Copy(args SliceArgs) {
   180  	if args.SrcStartIdx == args.SrcEndIdx {
   181  		// Nothing to copy, so return early.
   182  		return
   183  	}
   184  	if m.Nulls().MaybeHasNulls() {
   185  		// We're about to overwrite this entire range, so unset all the nulls.
   186  		m.Nulls().UnsetNullRange(args.DestIdx, args.DestIdx+(args.SrcEndIdx-args.SrcStartIdx))
   187  	}
   188  
   189  	switch m.CanonicalTypeFamily() {
   190  	// {{range .}}
   191  	case _CANONICAL_TYPE_FAMILY:
   192  		switch m.t.Width() {
   193  		// {{range .WidthOverloads}}
   194  		case _TYPE_WIDTH:
   195  			fromCol := args.Src.TemplateType()
   196  			toCol := m.TemplateType()
   197  			if args.Sel != nil {
   198  				sel := args.Sel[args.SrcStartIdx:args.SrcEndIdx]
   199  				n := len(sel)
   200  				// {{if .Sliceable}}
   201  				toCol = toCol[args.DestIdx:]
   202  				_ = toCol[n-1]
   203  				// {{end}}
   204  				if args.Src.MaybeHasNulls() {
   205  					nulls := args.Src.Nulls()
   206  					for i := 0; i < n; i++ {
   207  						//gcassert:bce
   208  						selIdx := sel[i]
   209  						if nulls.NullAt(selIdx) {
   210  							m.nulls.SetNull(i + args.DestIdx)
   211  						} else {
   212  							// {{if .IsBytesLike}}
   213  							toCol.Copy(fromCol, i+args.DestIdx, selIdx)
   214  							// {{else}}
   215  							v := fromCol.Get(selIdx)
   216  							// {{if .Sliceable}}
   217  							// {{/*
   218  							//     For the sliceable types, we sliced toCol to start at
   219  							//     args.DestIdx, so we use index i directly.
   220  							// */}}
   221  							//gcassert:bce
   222  							toCol.Set(i, v)
   223  							// {{else}}
   224  							// {{/*
   225  							//     For the non-sliceable types, toCol vector is the original
   226  							//     one (i.e. without an adjustment), so we need to add
   227  							//     args.DestIdx to set the element at the correct index.
   228  							// */}}
   229  							toCol.Set(i+args.DestIdx, v)
   230  							// {{end}}
   231  							// {{end}}
   232  						}
   233  					}
   234  					return
   235  				}
   236  				// No Nulls.
   237  				for i := 0; i < n; i++ {
   238  					//gcassert:bce
   239  					selIdx := sel[i]
   240  					// {{if .IsBytesLike}}
   241  					toCol.Copy(fromCol, i+args.DestIdx, selIdx)
   242  					// {{else}}
   243  					v := fromCol.Get(selIdx)
   244  					// {{if .Sliceable}}
   245  					// {{/*
   246  					//     For the sliceable types, we sliced toCol to start at
   247  					//     args.DestIdx, so we use index i directly.
   248  					// */}}
   249  					//gcassert:bce
   250  					toCol.Set(i, v)
   251  					// {{else}}
   252  					// {{/*
   253  					//     For the non-sliceable types, toCol vector is the original one
   254  					//     (i.e. without an adjustment), so we need to add args.DestIdx to
   255  					//     set the element at the correct index.
   256  					// */}}
   257  					toCol.Set(i+args.DestIdx, v)
   258  					// {{end}}
   259  					// {{end}}
   260  				}
   261  				return
   262  			}
   263  			// No Sel.
   264  			toCol.CopySlice(fromCol, args.DestIdx, args.SrcStartIdx, args.SrcEndIdx)
   265  			m.nulls.set(args)
   266  			// {{end}}
   267  		}
   268  		// {{end}}
   269  	default:
   270  		panic(fmt.Sprintf("unhandled type %s", m.t))
   271  	}
   272  }
   273  
   274  // {{/*
   275  func _COPY_WITH_REORDERED_SOURCE(_SRC_HAS_NULLS bool) { // */}}
   276  	// {{define "copyWithReorderedSource" -}}
   277  	for i := 0; i < n; i++ {
   278  		//gcassert:bce
   279  		destIdx := sel[i]
   280  		srcIdx := order[destIdx]
   281  		// {{if .SrcHasNulls}}
   282  		if nulls.NullAt(srcIdx) {
   283  			m.nulls.SetNull(destIdx)
   284  		} else
   285  		// {{end}}
   286  		{
   287  			// {{if .Global.IsBytesLike}}
   288  			toCol.Copy(fromCol, destIdx, srcIdx)
   289  			// {{else}}
   290  			v := fromCol.Get(srcIdx)
   291  			toCol.Set(destIdx, v)
   292  			// {{end}}
   293  		}
   294  	}
   295  	// {{end}}
   296  	// {{/*
   297  }
   298  
   299  // */}}
   300  
   301  func (m *memColumn) CopyWithReorderedSource(src Vec, sel, order []int) {
   302  	if len(sel) == 0 {
   303  		return
   304  	}
   305  	if m.nulls.MaybeHasNulls() {
   306  		m.nulls.UnsetNulls()
   307  	}
   308  	switch m.CanonicalTypeFamily() {
   309  	// {{range .}}
   310  	case _CANONICAL_TYPE_FAMILY:
   311  		switch m.t.Width() {
   312  		// {{range .WidthOverloads}}
   313  		case _TYPE_WIDTH:
   314  			fromCol := src.TemplateType()
   315  			toCol := m.TemplateType()
   316  			n := len(sel)
   317  			_ = sel[n-1]
   318  			if src.MaybeHasNulls() {
   319  				nulls := src.Nulls()
   320  				_COPY_WITH_REORDERED_SOURCE(true)
   321  			} else {
   322  				_COPY_WITH_REORDERED_SOURCE(false)
   323  			}
   324  			// {{end}}
   325  		}
   326  		// {{end}}
   327  	default:
   328  		panic(fmt.Sprintf("unhandled type %s", m.t))
   329  	}
   330  }
   331  
   332  func (m *memColumn) Window(start int, end int) Vec {
   333  	switch m.CanonicalTypeFamily() {
   334  	// {{range .}}
   335  	case _CANONICAL_TYPE_FAMILY:
   336  		switch m.t.Width() {
   337  		// {{range .WidthOverloads}}
   338  		case _TYPE_WIDTH:
   339  			col := m.TemplateType()
   340  			return &memColumn{
   341  				t:                   m.t,
   342  				canonicalTypeFamily: m.canonicalTypeFamily,
   343  				col:                 col.Window(start, end),
   344  				nulls:               m.nulls.Slice(start, end),
   345  			}
   346  			// {{end}}
   347  		}
   348  		// {{end}}
   349  	}
   350  	panic(fmt.Sprintf("unhandled type %s", m.t))
   351  }
   352  
   353  // SetValueAt is an inefficient helper to set the value in a Vec when the type
   354  // is unknown.
   355  func SetValueAt(v Vec, elem interface{}, rowIdx int) {
   356  	switch t := v.Type(); v.CanonicalTypeFamily() {
   357  	// {{range .}}
   358  	case _CANONICAL_TYPE_FAMILY:
   359  		switch t.Width() {
   360  		// {{range .WidthOverloads}}
   361  		case _TYPE_WIDTH:
   362  			target := v.TemplateType()
   363  			newVal := elem.(_GOTYPE)
   364  			target.Set(rowIdx, newVal)
   365  			// {{end}}
   366  		}
   367  		// {{end}}
   368  	default:
   369  		panic(fmt.Sprintf("unhandled type %s", t))
   370  	}
   371  }
   372  
   373  // GetValueAt is an inefficient helper to get the value in a Vec when the type
   374  // is unknown.
   375  func GetValueAt(v Vec, rowIdx int) interface{} {
   376  	if v.Nulls().NullAt(rowIdx) {
   377  		return nil
   378  	}
   379  	t := v.Type()
   380  	switch v.CanonicalTypeFamily() {
   381  	// {{range .}}
   382  	case _CANONICAL_TYPE_FAMILY:
   383  		switch t.Width() {
   384  		// {{range .WidthOverloads}}
   385  		case _TYPE_WIDTH:
   386  			target := v.TemplateType()
   387  			return target.Get(rowIdx)
   388  			// {{end}}
   389  		}
   390  		// {{end}}
   391  	}
   392  	panic(fmt.Sprintf("unhandled type %s", t))
   393  }