github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/col/coldataext/datum_vec.go (about) 1 // Copyright 2020 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 package coldataext 12 13 import ( 14 "fmt" 15 16 "github.com/cockroachdb/cockroach/pkg/col/coldata" 17 "github.com/cockroachdb/cockroach/pkg/sql/colexecbase/colexecerror" 18 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 19 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 20 "github.com/cockroachdb/cockroach/pkg/sql/types" 21 "github.com/cockroachdb/cockroach/pkg/util/encoding" 22 ) 23 24 // Datum wraps a tree.Datum. This is the struct that datumVec.Get() returns. 25 type Datum struct { 26 tree.Datum 27 } 28 29 var _ coldata.Datum = &Datum{} 30 var _ tree.Datum = &Datum{} 31 32 // datumVec is a vector of tree.Datums of the same type. 33 type datumVec struct { 34 // t is the type of the tree.Datums that datumVec stores. 35 t *types.T 36 // data is the underlying data stored in datumVec. 37 data []tree.Datum 38 // evalCtx is required for most of the methods of tree.Datum interface. 39 evalCtx *tree.EvalContext 40 41 scratch []byte 42 da sqlbase.DatumAlloc 43 } 44 45 var _ coldata.DatumVec = &datumVec{} 46 47 // newDatumVec returns a datumVec struct with capacity of n. 48 func newDatumVec(t *types.T, n int, evalCtx *tree.EvalContext) coldata.DatumVec { 49 return &datumVec{ 50 t: t, 51 data: make([]tree.Datum, n), 52 evalCtx: evalCtx, 53 } 54 } 55 56 // BinFn evaluates the provided binary function between the receiver and other. 57 // dVec is the datumVec that stores either d or other (it doesn't matter which 58 // one because it is used only to supply the eval context). 59 func (d *Datum) BinFn(binFn *tree.BinOp, dVec, other interface{}) (tree.Datum, error) { 60 return binFn.Fn(dVec.(*datumVec).evalCtx, d.Datum, maybeUnwrapDatum(other)) 61 } 62 63 // CompareDatum returns the comparison between d and other. The other is 64 // assumed to be tree.Datum. dVec is the datumVec that stores either d or other 65 // (it doesn't matter which one because it is used only to supply the eval 66 // context). 67 // Note that the method is named differently from "Compare" so that we do not 68 // overload tree.Datum.Compare method. 69 func (d *Datum) CompareDatum(dVec, other interface{}) int { 70 return d.Datum.Compare(dVec.(*datumVec).evalCtx, maybeUnwrapDatum(other)) 71 } 72 73 // Hash returns the hash of the datum as a byte slice. 74 func (d *Datum) Hash(da *sqlbase.DatumAlloc) []byte { 75 ed := sqlbase.EncDatum{Datum: maybeUnwrapDatum(d)} 76 b, err := ed.Fingerprint(d.ResolvedType(), da, nil /* appendTo */) 77 if err != nil { 78 colexecerror.InternalError(err) 79 } 80 return b 81 } 82 83 // Get implements coldata.DatumVec interface. 84 func (dv *datumVec) Get(i int) coldata.Datum { 85 dv.maybeSetDNull(i) 86 return &Datum{Datum: dv.data[i]} 87 } 88 89 // Set implements coldata.DatumVec interface. 90 func (dv *datumVec) Set(i int, v coldata.Datum) { 91 datum := maybeUnwrapDatum(v) 92 dv.assertValidDatum(datum) 93 dv.data[i] = datum 94 } 95 96 // Slice implements coldata.DatumVec interface. 97 func (dv *datumVec) Slice(start, end int) coldata.DatumVec { 98 return &datumVec{ 99 t: dv.t, 100 data: dv.data[start:end], 101 evalCtx: dv.evalCtx, 102 } 103 } 104 105 // CopySlice implements coldata.DatumVec interface. 106 func (dv *datumVec) CopySlice(src coldata.DatumVec, destIdx, srcStartIdx, srcEndIdx int) { 107 castSrc := src.(*datumVec) 108 dv.assertSameTypeFamily(castSrc.t) 109 copy(dv.data[destIdx:], castSrc.data[srcStartIdx:srcEndIdx]) 110 } 111 112 // AppendSlice implements coldata.DatumVec interface. 113 func (dv *datumVec) AppendSlice(src coldata.DatumVec, destIdx, srcStartIdx, srcEndIdx int) { 114 castSrc := src.(*datumVec) 115 dv.assertSameTypeFamily(castSrc.t) 116 dv.data = append(dv.data[:destIdx], castSrc.data[srcStartIdx:srcEndIdx]...) 117 } 118 119 // AppendVal implements coldata.DatumVec interface. 120 func (dv *datumVec) AppendVal(v coldata.Datum) { 121 datum := maybeUnwrapDatum(v) 122 dv.assertValidDatum(datum) 123 dv.data = append(dv.data, datum) 124 } 125 126 // SetLength implements coldata.DatumVec interface. 127 func (dv *datumVec) SetLength(l int) { 128 dv.data = dv.data[:l] 129 } 130 131 // Len implements coldata.DatumVec interface. 132 func (dv *datumVec) Len() int { 133 return len(dv.data) 134 } 135 136 // Cap implements coldata.DatumVec interface. 137 func (dv *datumVec) Cap() int { 138 return cap(dv.data) 139 } 140 141 // MarshalAt implements coldata.DatumVec interface. 142 func (dv *datumVec) MarshalAt(i int) ([]byte, error) { 143 dv.maybeSetDNull(i) 144 return sqlbase.EncodeTableValue( 145 nil /* appendTo */, sqlbase.ColumnID(encoding.NoColumnID), dv.data[i], dv.scratch, 146 ) 147 } 148 149 // UnmarshalTo implements coldata.DatumVec interface. 150 // index i. 151 func (dv *datumVec) UnmarshalTo(i int, b []byte) error { 152 var err error 153 dv.data[i], _, err = sqlbase.DecodeTableValue(&dv.da, dv.t, b) 154 return err 155 } 156 157 // assertValidDatum asserts that the given datum is valid to be stored in this 158 // datumVec. 159 func (dv *datumVec) assertValidDatum(datum tree.Datum) { 160 if datum != tree.DNull { 161 dv.assertSameTypeFamily(datum.ResolvedType()) 162 } 163 } 164 165 // assertSameTypeFamily asserts that the provided type is of the same type 166 // family as the datums this datumVec stores. 167 func (dv *datumVec) assertSameTypeFamily(t *types.T) { 168 if dv.t.Family() != t.Family() { 169 colexecerror.InternalError( 170 fmt.Sprintf("cannot use value of type %+v on a datumVec of type %+v", t, dv.t), 171 ) 172 } 173 } 174 175 // maybeSetDNull checks whether the datum at index i is nil, and if so, sets it 176 // to DNull. This is needed because we store whether a value is NULL in a 177 // separate Nulls vector, but we also might be accessing the garbage value from 178 // the vectors in certain code paths (for example, in Vec.Append). 179 func (dv *datumVec) maybeSetDNull(i int) { 180 if dv.data[i] == nil { 181 dv.data[i] = tree.DNull 182 } 183 } 184 185 // maybeUnwrapDatum possibly unwraps tree.Datum from inside of Datum. It also 186 // checks whether v is nil and returns tree.DNull if it is. 187 func maybeUnwrapDatum(v coldata.Datum) tree.Datum { 188 if v == nil { 189 return tree.DNull 190 } 191 if datum, ok := v.(*Datum); ok { 192 return datum.Datum 193 } else if datum, ok := v.(tree.Datum); ok { 194 return datum 195 } 196 colexecerror.InternalError(fmt.Sprintf("unexpected value: %v", v)) 197 // This code is unreachable, but the compiler cannot infer that. 198 return nil 199 }