forked from pingcap/tidb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathevaluator.go
135 lines (120 loc) · 4.2 KB
/
evaluator.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
// Copyright 2018 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package expression
import (
"github.com/pingcap/tidb/sessionctx"
"github.com/pingcap/tidb/util/chunk"
)
type columnEvaluator struct {
inputIdxToOutputIdxes map[int][]int
}
// run evaluates "Column" expressions.
// NOTE: It should be called after all the other expressions are evaluated
//
// since it will change the content of the input Chunk.
func (e *columnEvaluator) run(ctx sessionctx.Context, input, output *chunk.Chunk) error {
for inputIdx, outputIdxes := range e.inputIdxToOutputIdxes {
if err := output.SwapColumn(outputIdxes[0], input, inputIdx); err != nil {
return err
}
for i, length := 1, len(outputIdxes); i < length; i++ {
output.MakeRef(outputIdxes[0], outputIdxes[i])
}
}
return nil
}
type defaultEvaluator struct {
outputIdxes []int
exprs []Expression
vectorizable bool
}
func (e *defaultEvaluator) run(ctx sessionctx.Context, input, output *chunk.Chunk) error {
iter := chunk.NewIterator4Chunk(input)
if e.vectorizable {
for i := range e.outputIdxes {
if ctx.GetSessionVars().EnableVectorizedExpression && e.exprs[i].Vectorized() {
if err := evalOneVec(ctx, e.exprs[i], input, output, e.outputIdxes[i]); err != nil {
return err
}
continue
}
err := evalOneColumn(ctx, e.exprs[i], iter, output, e.outputIdxes[i])
if err != nil {
return err
}
}
return nil
}
for row := iter.Begin(); row != iter.End(); row = iter.Next() {
for i := range e.outputIdxes {
err := evalOneCell(ctx, e.exprs[i], row, output, e.outputIdxes[i])
if err != nil {
return err
}
}
}
return nil
}
// EvaluatorSuite is responsible for the evaluation of a list of expressions.
// It separates them to "column" and "other" expressions and evaluates "other"
// expressions before "column" expressions.
type EvaluatorSuite struct {
*columnEvaluator // Evaluator for column expressions.
*defaultEvaluator // Evaluator for other expressions.
}
// NewEvaluatorSuite creates an EvaluatorSuite to evaluate all the exprs.
// avoidColumnEvaluator can be removed after column pool is supported.
func NewEvaluatorSuite(exprs []Expression, avoidColumnEvaluator bool) *EvaluatorSuite {
e := &EvaluatorSuite{}
for i := 0; i < len(exprs); i++ {
if col, isCol := exprs[i].(*Column); isCol && !avoidColumnEvaluator {
if e.columnEvaluator == nil {
e.columnEvaluator = &columnEvaluator{inputIdxToOutputIdxes: make(map[int][]int)}
}
inputIdx, outputIdx := col.Index, i
e.columnEvaluator.inputIdxToOutputIdxes[inputIdx] = append(e.columnEvaluator.inputIdxToOutputIdxes[inputIdx], outputIdx)
continue
}
if e.defaultEvaluator == nil {
e.defaultEvaluator = &defaultEvaluator{
outputIdxes: make([]int, 0, len(exprs)),
exprs: make([]Expression, 0, len(exprs)),
}
}
e.defaultEvaluator.exprs = append(e.defaultEvaluator.exprs, exprs[i])
e.defaultEvaluator.outputIdxes = append(e.defaultEvaluator.outputIdxes, i)
}
if e.defaultEvaluator != nil {
e.defaultEvaluator.vectorizable = Vectorizable(e.defaultEvaluator.exprs)
}
return e
}
// Vectorizable checks whether this EvaluatorSuite can use vectorizd execution mode.
func (e *EvaluatorSuite) Vectorizable() bool {
return e.defaultEvaluator == nil || e.defaultEvaluator.vectorizable
}
// Run evaluates all the expressions hold by this EvaluatorSuite.
// NOTE: "defaultEvaluator" must be evaluated before "columnEvaluator".
func (e *EvaluatorSuite) Run(ctx sessionctx.Context, input, output *chunk.Chunk) error {
if e.defaultEvaluator != nil {
err := e.defaultEvaluator.run(ctx, input, output)
if err != nil {
return err
}
}
if e.columnEvaluator != nil {
return e.columnEvaluator.run(ctx, input, output)
}
return nil
}