1#include "duckdb/execution/operator/projection/physical_projection.hpp"
2#include "duckdb/execution/physical_plan_generator.hpp"
3#include "duckdb/planner/operator/logical_projection.hpp"
4#include "duckdb/planner/expression/bound_reference_expression.hpp"
5
6namespace duckdb {
7
8unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalProjection &op) {
9 D_ASSERT(op.children.size() == 1);
10 auto plan = CreatePlan(op&: *op.children[0]);
11
12#ifdef DEBUG
13 for (auto &expr : op.expressions) {
14 D_ASSERT(!expr->IsWindow());
15 D_ASSERT(!expr->IsAggregate());
16 }
17#endif
18 if (plan->types.size() == op.types.size()) {
19 // check if this projection can be omitted entirely
20 // this happens if a projection simply emits the columns in the same order
21 // e.g. PROJECTION(#0, #1, #2, #3, ...)
22 bool omit_projection = true;
23 for (idx_t i = 0; i < op.types.size(); i++) {
24 if (op.expressions[i]->type == ExpressionType::BOUND_REF) {
25 auto &bound_ref = op.expressions[i]->Cast<BoundReferenceExpression>();
26 if (bound_ref.index == i) {
27 continue;
28 }
29 }
30 omit_projection = false;
31 break;
32 }
33 if (omit_projection) {
34 // the projection only directly projects the child' columns: omit it entirely
35 return plan;
36 }
37 }
38
39 auto projection = make_uniq<PhysicalProjection>(args&: op.types, args: std::move(op.expressions), args&: op.estimated_cardinality);
40 projection->children.push_back(x: std::move(plan));
41 return std::move(projection);
42}
43
44} // namespace duckdb
45