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
5namespace duckdb {
6
7class ExpressionScanState : public OperatorState {
8public:
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
19unique_ptr<OperatorState> PhysicalExpressionScan::GetOperatorState(ExecutionContext &context) const {
20 return make_uniq<ExpressionScanState>(args&: Allocator::Get(context&: context.client), args: *this);
21}
22
23OperatorResultType 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
41void 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
52bool 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