-
Notifications
You must be signed in to change notification settings - Fork 3.8k
/
proj_const_ops_tmpl.go
343 lines (313 loc) · 9.61 KB
/
proj_const_ops_tmpl.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
// Copyright 2019 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
// {{/*
// +build execgen_template
//
// This file is the execgen template for proj_const_{left,right}_ops.eg.go.
// It's formatted in a special way, so it's both valid Go and a valid
// text/template input. This permits editing this file with editor support.
//
// */}}
package colexec
import (
"context"
"github.com/cockroachdb/cockroach/pkg/col/coldata"
"github.com/cockroachdb/cockroach/pkg/col/coldataext"
"github.com/cockroachdb/cockroach/pkg/col/typeconv"
"github.com/cockroachdb/cockroach/pkg/sql/colconv"
"github.com/cockroachdb/cockroach/pkg/sql/colexec/execgen"
"github.com/cockroachdb/cockroach/pkg/sql/colexecbase"
"github.com/cockroachdb/cockroach/pkg/sql/colexecbase/colexecerror"
"github.com/cockroachdb/cockroach/pkg/sql/colmem"
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
"github.com/cockroachdb/cockroach/pkg/sql/types"
"github.com/cockroachdb/errors"
)
// {{/*
// Declarations to make the template compile properly.
// _LEFT_CANONICAL_TYPE_FAMILY is the template variable.
const _LEFT_CANONICAL_TYPE_FAMILY = types.UnknownFamily
// _LEFT_TYPE_WIDTH is the template variable.
const _LEFT_TYPE_WIDTH = 0
// _RIGHT_CANONICAL_TYPE_FAMILY is the template variable.
const _RIGHT_CANONICAL_TYPE_FAMILY = types.UnknownFamily
// _RIGHT_TYPE_WIDTH is the template variable.
const _RIGHT_TYPE_WIDTH = 0
// _NON_CONST_GOTYPESLICE is a template Go type slice variable.
type _NON_CONST_GOTYPESLICE interface{}
// _ASSIGN is the template function for assigning the first input to the result
// of computation an operation on the second and the third inputs.
func _ASSIGN(_, _, _, _, _, _ interface{}) {
colexecerror.InternalError(errors.AssertionFailedf(""))
}
// */}}
// {{define "projConstOp"}}
type _OP_CONST_NAME struct {
projConstOpBase
// {{if _IS_CONST_LEFT}}
constArg _L_GO_TYPE
// {{else}}
constArg _R_GO_TYPE
// {{end}}
}
func (p _OP_CONST_NAME) Next(ctx context.Context) coldata.Batch {
// In order to inline the templated code of overloads, we need to have a
// `_overloadHelper` local variable of type `overloadHelper`.
_overloadHelper := p.overloadHelper
// However, the scratch is not used in all of the projection operators, so
// we add this to go around "unused" error.
_ = _overloadHelper
batch := p.input.Next(ctx)
n := batch.Length()
if n == 0 {
return coldata.ZeroBatch
}
vec := batch.ColVec(p.colIdx)
var col _NON_CONST_GOTYPESLICE
// {{if _IS_CONST_LEFT}}
col = vec._R_TYP()
// {{else}}
col = vec._L_TYP()
// {{end}}
projVec := batch.ColVec(p.outputIdx)
if projVec.MaybeHasNulls() {
// We need to make sure that there are no left over null values in the
// output vector.
projVec.Nulls().UnsetNulls()
}
projCol := projVec._RET_TYP()
_outNulls := projVec.Nulls()
if vec.Nulls().MaybeHasNulls() {
_SET_PROJECTION(true)
} else {
_SET_PROJECTION(false)
}
// Although we didn't change the length of the batch, it is necessary to set
// the length anyway (this helps maintaining the invariant of flat bytes).
batch.SetLength(n)
return batch
}
func (p _OP_CONST_NAME) Init() {
p.input.Init()
}
// {{end}}
// {{/*
func _SET_PROJECTION(_HAS_NULLS bool) {
// */}}
// {{define "setProjection" -}}
// {{$hasNulls := $.HasNulls}}
// {{with $.Overload}}
// {{if _HAS_NULLS}}
colNulls := vec.Nulls()
// {{end}}
if sel := batch.Selection(); sel != nil {
sel = sel[:n]
for _, i := range sel {
_SET_SINGLE_TUPLE_PROJECTION(_HAS_NULLS)
}
} else {
col = execgen.SLICE(col, 0, n)
_ = projCol.Get(n - 1)
for i := 0; i < n; i++ {
_SET_SINGLE_TUPLE_PROJECTION(_HAS_NULLS)
}
}
// {{if _HAS_NULLS}}
projVec.SetNulls(_outNulls.Or(colNulls))
// {{end}}
// {{end}}
// {{end}}
// {{/*
}
// */}}
// {{/*
func _SET_SINGLE_TUPLE_PROJECTION(_HAS_NULLS bool) { // */}}
// {{define "setSingleTupleProjection" -}}
// {{$hasNulls := $.HasNulls}}
// {{with $.Overload}}
// {{if _HAS_NULLS}}
if !colNulls.NullAt(i) {
// We only want to perform the projection operation if the value is not null.
// {{end}}
arg := col.Get(i)
// {{if _IS_CONST_LEFT}}
_ASSIGN(projCol[i], p.constArg, arg, projCol, _, col)
// {{else}}
_ASSIGN(projCol[i], arg, p.constArg, projCol, col, _)
// {{end}}
// {{if _HAS_NULLS}}
}
// {{end}}
// {{end}}
// {{end}}
// {{/*
}
// */}}
// {{range .BinOps}}
// {{range .LeftFamilies}}
// {{range .LeftWidths}}
// {{range .RightFamilies}}
// {{range .RightWidths}}
// {{template "projConstOp" .}}
// {{end}}
// {{end}}
// {{end}}
// {{end}}
// {{end}}
// {{range .CmpOps}}
// {{range .LeftFamilies}}
// {{range .LeftWidths}}
// {{range .RightFamilies}}
// {{range .RightWidths}}
// {{if not _IS_CONST_LEFT}}
// {{/*
// Comparison operators are always normalized so that the constant is on
// the right side, so we skip generating the code when the constant is on
// the left.
// */}}
// {{template "projConstOp" .}}
// {{end}}
// {{end}}
// {{end}}
// {{end}}
// {{end}}
// {{end}}
// GetProjection_CONST_SIDEConstOperator returns the appropriate constant
// projection operator for the given left and right column types and operation.
func GetProjection_CONST_SIDEConstOperator(
allocator *colmem.Allocator,
inputTypes []*types.T,
constType *types.T,
outputType *types.T,
op tree.Operator,
input colexecbase.Operator,
colIdx int,
constArg tree.Datum,
outputIdx int,
evalCtx *tree.EvalContext,
binFn tree.TwoArgFn,
cmpExpr *tree.ComparisonExpr,
) (colexecbase.Operator, error) {
input = newVectorTypeEnforcer(allocator, input, outputType, outputIdx)
projConstOpBase := projConstOpBase{
OneInputNode: NewOneInputNode(input),
allocator: allocator,
colIdx: colIdx,
outputIdx: outputIdx,
overloadHelper: overloadHelper{binFn: binFn, evalCtx: evalCtx},
}
c := GetDatumToPhysicalFn(constType)(constArg)
// {{if _IS_CONST_LEFT}}
leftType, rightType := constType, inputTypes[colIdx]
// {{else}}
leftType, rightType := inputTypes[colIdx], constType
// {{end}}
switch op.(type) {
case tree.BinaryOperator:
switch op {
// {{range .BinOps}}
case tree._NAME:
switch typeconv.TypeFamilyToCanonicalTypeFamily(leftType.Family()) {
// {{range .LeftFamilies}}
// {{$leftFamilyStr := .LeftCanonicalFamilyStr}}
case _LEFT_CANONICAL_TYPE_FAMILY:
switch leftType.Width() {
// {{range .LeftWidths}}
case _LEFT_TYPE_WIDTH:
switch typeconv.TypeFamilyToCanonicalTypeFamily(rightType.Family()) {
// {{range .RightFamilies}}
case _RIGHT_CANONICAL_TYPE_FAMILY:
switch rightType.Width() {
// {{range .RightWidths}}
case _RIGHT_TYPE_WIDTH:
return &_OP_CONST_NAME{
projConstOpBase: projConstOpBase,
// {{if _IS_CONST_LEFT}}
// {{if eq $leftFamilyStr "typeconv.DatumVecCanonicalTypeFamily"}}
// {{/*
// Binary operations are evaluated using coldataext.Datum.BinFn
// method which requires that we have *coldataext.Datum on the
// left, so we create that at the operator construction time to
// avoid runtime conversion. Note that when the constant is on
// the right side, then the left element necessarily comes from
// the vector and will be of the desired type, so no additional
// work is needed.
// */}}
constArg: &coldataext.Datum{Datum: c.(tree.Datum)},
// {{else}}
constArg: c.(_L_GO_TYPE),
// {{end}}
// {{else}}
constArg: c.(_R_GO_TYPE),
// {{end}}
}, nil
// {{end}}
}
// {{end}}
}
// {{end}}
}
// {{end}}
}
// {{end}}
}
// {{if not _IS_CONST_LEFT}}
// {{/*
// Comparison operators are always normalized so that the constant is on
// the right side, so we skip generating the code when the constant is on
// the left.
// */}}
case tree.ComparisonOperator:
if leftType.Family() != types.TupleFamily && rightType.Family() != types.TupleFamily {
// Tuple comparison has special null-handling semantics, so we will
// fallback to the default comparison operator if either of the
// input vectors is of a tuple type.
switch op {
// {{range .CmpOps}}
case tree._NAME:
switch typeconv.TypeFamilyToCanonicalTypeFamily(leftType.Family()) {
// {{range .LeftFamilies}}
// {{$leftFamilyStr := .LeftCanonicalFamilyStr}}
case _LEFT_CANONICAL_TYPE_FAMILY:
switch leftType.Width() {
// {{range .LeftWidths}}
case _LEFT_TYPE_WIDTH:
switch typeconv.TypeFamilyToCanonicalTypeFamily(rightType.Family()) {
// {{range .RightFamilies}}
case _RIGHT_CANONICAL_TYPE_FAMILY:
switch rightType.Width() {
// {{range .RightWidths}}
case _RIGHT_TYPE_WIDTH:
return &_OP_CONST_NAME{
projConstOpBase: projConstOpBase,
constArg: c.(_R_GO_TYPE),
}, nil
// {{end}}
}
// {{end}}
}
// {{end}}
}
// {{end}}
}
// {{end}}
}
}
return &defaultCmp_CONST_SIDEConstProjOp{
projConstOpBase: projConstOpBase,
adapter: newComparisonExprAdapter(cmpExpr, evalCtx),
constArg: constArg,
toDatumConverter: colconv.NewVecToDatumConverter(len(inputTypes), []int{colIdx}),
datumToVecConverter: GetDatumToPhysicalFn(outputType),
}, nil
// {{end}}
}
return nil, errors.Errorf("couldn't find overload for %s %s %s", leftType.Name(), op, rightType.Name())
}