| 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 | |