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
17namespace duckdb {
18class Allocator;
19class ExecutionContext;
20
21//! ExpressionExecutor is responsible for executing a set of expressions and storing the result in a data chunk
22class ExpressionExecutor {
23 friend class Index;
24 friend class CreateIndexLocalSinkState;
25
26public:
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
39public:
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
86protected:
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
152private:
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
158private:
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