1 | //===----------------------------------------------------------------------===// |
2 | // DuckDB |
3 | // |
4 | // duckdb/execution/expression_executor.hpp |
5 | // |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #pragma once |
10 | |
11 | #include "duckdb/common/unordered_map.hpp" |
12 | #include "duckdb/execution/expression_executor_state.hpp" |
13 | #include "duckdb/planner/bound_tokens.hpp" |
14 | #include "duckdb/planner/expression.hpp" |
15 | #include "duckdb/main/client_context.hpp" |
16 | |
17 | namespace duckdb { |
18 | class Allocator; |
19 | class ExecutionContext; |
20 | |
21 | //! ExpressionExecutor is responsible for executing a set of expressions and storing the result in a data chunk |
22 | class ExpressionExecutor { |
23 | friend class Index; |
24 | friend class CreateIndexLocalSinkState; |
25 | |
26 | public: |
27 | DUCKDB_API explicit ExpressionExecutor(ClientContext &context); |
28 | DUCKDB_API ExpressionExecutor(ClientContext &context, const Expression *expression); |
29 | DUCKDB_API ExpressionExecutor(ClientContext &context, const Expression &expression); |
30 | DUCKDB_API ExpressionExecutor(ClientContext &context, const vector<unique_ptr<Expression>> &expressions); |
31 | ExpressionExecutor(ExpressionExecutor &&) = delete; |
32 | |
33 | //! The expressions of the executor |
34 | vector<const Expression *> expressions; |
35 | //! The data chunk of the current physical operator, used to resolve |
36 | //! column references and determines the output cardinality |
37 | DataChunk *chunk = nullptr; |
38 | |
39 | public: |
40 | bool HasContext(); |
41 | ClientContext &GetContext(); |
42 | Allocator &GetAllocator(); |
43 | |
44 | //! Add an expression to the set of to-be-executed expressions of the executor |
45 | DUCKDB_API void AddExpression(const Expression &expr); |
46 | |
47 | //! Execute the set of expressions with the given input chunk and store the result in the output chunk |
48 | DUCKDB_API void Execute(DataChunk *input, DataChunk &result); |
49 | inline void Execute(DataChunk &input, DataChunk &result) { |
50 | Execute(input: &input, result); |
51 | } |
52 | inline void Execute(DataChunk &result) { |
53 | Execute(input: nullptr, result); |
54 | } |
55 | |
56 | //! Execute the ExpressionExecutor and put the result in the result vector; this should only be used for expression |
57 | //! executors with a single expression |
58 | DUCKDB_API void ExecuteExpression(DataChunk &input, Vector &result); |
59 | //! Execute the ExpressionExecutor and put the result in the result vector; this should only be used for expression |
60 | //! executors with a single expression |
61 | DUCKDB_API void ExecuteExpression(Vector &result); |
62 | //! Execute the ExpressionExecutor and generate a selection vector from all true values in the result; this should |
63 | //! only be used with a single boolean expression |
64 | DUCKDB_API idx_t SelectExpression(DataChunk &input, SelectionVector &sel); |
65 | |
66 | //! Execute the expression with index `expr_idx` and store the result in the result vector |
67 | DUCKDB_API void ExecuteExpression(idx_t expr_idx, Vector &result); |
68 | //! Evaluate a scalar expression and fold it into a single value |
69 | DUCKDB_API static Value EvaluateScalar(ClientContext &context, const Expression &expr, |
70 | bool allow_unfoldable = false); |
71 | //! Try to evaluate a scalar expression and fold it into a single value, returns false if an exception is thrown |
72 | DUCKDB_API static bool TryEvaluateScalar(ClientContext &context, const Expression &expr, Value &result); |
73 | |
74 | //! Initialize the state of a given expression |
75 | static unique_ptr<ExpressionState> InitializeState(const Expression &expr, ExpressionExecutorState &state); |
76 | |
77 | inline void SetChunk(DataChunk *chunk) { |
78 | this->chunk = chunk; |
79 | } |
80 | inline void SetChunk(DataChunk &chunk) { |
81 | SetChunk(&chunk); |
82 | } |
83 | |
84 | DUCKDB_API vector<unique_ptr<ExpressionExecutorState>> &GetStates(); |
85 | |
86 | protected: |
87 | void Initialize(const Expression &expr, ExpressionExecutorState &state); |
88 | |
89 | static unique_ptr<ExpressionState> InitializeState(const BoundReferenceExpression &expr, |
90 | ExpressionExecutorState &state); |
91 | static unique_ptr<ExpressionState> InitializeState(const BoundBetweenExpression &expr, |
92 | ExpressionExecutorState &state); |
93 | static unique_ptr<ExpressionState> InitializeState(const BoundCaseExpression &expr, ExpressionExecutorState &state); |
94 | static unique_ptr<ExpressionState> InitializeState(const BoundCastExpression &expr, ExpressionExecutorState &state); |
95 | static unique_ptr<ExpressionState> InitializeState(const BoundComparisonExpression &expr, |
96 | ExpressionExecutorState &state); |
97 | static unique_ptr<ExpressionState> InitializeState(const BoundConjunctionExpression &expr, |
98 | ExpressionExecutorState &state); |
99 | static unique_ptr<ExpressionState> InitializeState(const BoundConstantExpression &expr, |
100 | ExpressionExecutorState &state); |
101 | static unique_ptr<ExpressionState> InitializeState(const BoundFunctionExpression &expr, |
102 | ExpressionExecutorState &state); |
103 | static unique_ptr<ExpressionState> InitializeState(const BoundOperatorExpression &expr, |
104 | ExpressionExecutorState &state); |
105 | static unique_ptr<ExpressionState> InitializeState(const BoundParameterExpression &expr, |
106 | ExpressionExecutorState &state); |
107 | |
108 | void Execute(const Expression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, |
109 | Vector &result); |
110 | |
111 | void Execute(const BoundBetweenExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, |
112 | Vector &result); |
113 | void Execute(const BoundCaseExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, |
114 | Vector &result); |
115 | void Execute(const BoundCastExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, |
116 | Vector &result); |
117 | |
118 | void Execute(const BoundComparisonExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, |
119 | Vector &result); |
120 | void Execute(const BoundConjunctionExpression &expr, ExpressionState *state, const SelectionVector *sel, |
121 | idx_t count, Vector &result); |
122 | void Execute(const BoundConstantExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, |
123 | Vector &result); |
124 | void Execute(const BoundFunctionExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, |
125 | Vector &result); |
126 | void Execute(const BoundOperatorExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, |
127 | Vector &result); |
128 | void Execute(const BoundParameterExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, |
129 | Vector &result); |
130 | void Execute(const BoundReferenceExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, |
131 | Vector &result); |
132 | |
133 | //! Execute the (boolean-returning) expression and generate a selection vector with all entries that are "true" in |
134 | //! the result |
135 | idx_t Select(const Expression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, |
136 | SelectionVector *true_sel, SelectionVector *false_sel); |
137 | idx_t DefaultSelect(const Expression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, |
138 | SelectionVector *true_sel, SelectionVector *false_sel); |
139 | |
140 | idx_t Select(const BoundBetweenExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, |
141 | SelectionVector *true_sel, SelectionVector *false_sel); |
142 | idx_t Select(const BoundComparisonExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, |
143 | SelectionVector *true_sel, SelectionVector *false_sel); |
144 | idx_t Select(const BoundConjunctionExpression &expr, ExpressionState *state, const SelectionVector *sel, |
145 | idx_t count, SelectionVector *true_sel, SelectionVector *false_sel); |
146 | |
147 | //! Verify that the output of a step in the ExpressionExecutor is correct |
148 | void Verify(const Expression &expr, Vector &result, idx_t count); |
149 | |
150 | void FillSwitch(Vector &vector, Vector &result, const SelectionVector &sel, sel_t count); |
151 | |
152 | private: |
153 | //! Client context |
154 | optional_ptr<ClientContext> context; |
155 | //! The states of the expression executor; this holds any intermediates and temporary states of expressions |
156 | vector<unique_ptr<ExpressionExecutorState>> states; |
157 | |
158 | private: |
159 | // it is possible to create an expression executor without a ClientContext - but it should be avoided |
160 | DUCKDB_API ExpressionExecutor(); |
161 | DUCKDB_API ExpressionExecutor(const vector<unique_ptr<Expression>> &exprs); |
162 | }; |
163 | } // namespace duckdb |
164 | |