1 | #include "duckdb/execution/operator/scan/physical_expression_scan.hpp" |
2 | #include "duckdb/parallel/thread_context.hpp" |
3 | #include "duckdb/execution/expression_executor.hpp" |
4 | |
5 | namespace duckdb { |
6 | |
7 | class ExpressionScanState : public OperatorState { |
8 | public: |
9 | explicit ExpressionScanState(Allocator &allocator, const PhysicalExpressionScan &op) : expression_index(0) { |
10 | temp_chunk.Initialize(allocator, types: op.GetTypes()); |
11 | } |
12 | |
13 | //! The current position in the scan |
14 | idx_t expression_index; |
15 | //! Temporary chunk for evaluating expressions |
16 | DataChunk temp_chunk; |
17 | }; |
18 | |
19 | unique_ptr<OperatorState> PhysicalExpressionScan::GetOperatorState(ExecutionContext &context) const { |
20 | return make_uniq<ExpressionScanState>(args&: Allocator::Get(context&: context.client), args: *this); |
21 | } |
22 | |
23 | OperatorResultType PhysicalExpressionScan::Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, |
24 | GlobalOperatorState &gstate, OperatorState &state_p) const { |
25 | auto &state = state_p.Cast<ExpressionScanState>(); |
26 | |
27 | for (; chunk.size() + input.size() <= STANDARD_VECTOR_SIZE && state.expression_index < expressions.size(); |
28 | state.expression_index++) { |
29 | state.temp_chunk.Reset(); |
30 | EvaluateExpression(context&: context.client, expression_idx: state.expression_index, child_chunk: &input, result&: state.temp_chunk); |
31 | chunk.Append(other: state.temp_chunk); |
32 | } |
33 | if (state.expression_index < expressions.size()) { |
34 | return OperatorResultType::HAVE_MORE_OUTPUT; |
35 | } else { |
36 | state.expression_index = 0; |
37 | return OperatorResultType::NEED_MORE_INPUT; |
38 | } |
39 | } |
40 | |
41 | void PhysicalExpressionScan::EvaluateExpression(ClientContext &context, idx_t expression_idx, DataChunk *child_chunk, |
42 | DataChunk &result) const { |
43 | ExpressionExecutor executor(context, expressions[expression_idx]); |
44 | if (child_chunk) { |
45 | child_chunk->Verify(); |
46 | executor.Execute(input&: *child_chunk, result); |
47 | } else { |
48 | executor.Execute(result); |
49 | } |
50 | } |
51 | |
52 | bool PhysicalExpressionScan::IsFoldable() const { |
53 | for (auto &expr_list : expressions) { |
54 | for (auto &expr : expr_list) { |
55 | if (!expr->IsFoldable()) { |
56 | return false; |
57 | } |
58 | } |
59 | } |
60 | return true; |
61 | } |
62 | |
63 | } // namespace duckdb |
64 | |