1#include "duckdb/main/relation/projection_relation.hpp"
2#include "duckdb/main/client_context.hpp"
3#include "duckdb/parser/query_node/select_node.hpp"
4#include "duckdb/parser/tableref/subqueryref.hpp"
5
6namespace duckdb {
7
8ProjectionRelation::ProjectionRelation(shared_ptr<Relation> child_p,
9 vector<unique_ptr<ParsedExpression>> parsed_expressions, vector<string> aliases)
10 : Relation(child_p->context, RelationType::PROJECTION_RELATION), expressions(std::move(parsed_expressions)),
11 child(std::move(child_p)) {
12 if (!aliases.empty()) {
13 if (aliases.size() != expressions.size()) {
14 throw ParserException("Aliases list length must match expression list length!");
15 }
16 for (idx_t i = 0; i < aliases.size(); i++) {
17 expressions[i]->alias = aliases[i];
18 }
19 }
20 // bind the expressions
21 context.GetContext()->TryBindRelation(relation&: *this, result_columns&: this->columns);
22}
23
24unique_ptr<QueryNode> ProjectionRelation::GetQueryNode() {
25 auto child_ptr = child.get();
26 while (child_ptr->InheritsColumnBindings()) {
27 child_ptr = child_ptr->ChildRelation();
28 }
29 unique_ptr<QueryNode> result;
30 if (child_ptr->type == RelationType::JOIN_RELATION) {
31 // child node is a join: push projection into the child query node
32 result = child->GetQueryNode();
33 } else {
34 // child node is not a join: create a new select node and push the child as a table reference
35 auto select = make_uniq<SelectNode>();
36 select->from_table = child->GetTableRef();
37 result = std::move(select);
38 }
39 D_ASSERT(result->type == QueryNodeType::SELECT_NODE);
40 auto &select_node = result->Cast<SelectNode>();
41 select_node.aggregate_handling = AggregateHandling::NO_AGGREGATES_ALLOWED;
42 select_node.select_list.clear();
43 for (auto &expr : expressions) {
44 select_node.select_list.push_back(x: expr->Copy());
45 }
46 return result;
47}
48
49string ProjectionRelation::GetAlias() {
50 return child->GetAlias();
51}
52
53const vector<ColumnDefinition> &ProjectionRelation::Columns() {
54 return columns;
55}
56
57string ProjectionRelation::ToString(idx_t depth) {
58 string str = RenderWhitespace(depth) + "Projection [";
59 for (idx_t i = 0; i < expressions.size(); i++) {
60 if (i != 0) {
61 str += ", ";
62 }
63 str += expressions[i]->ToString() + " as " + expressions[i]->alias;
64 }
65 str += "]\n";
66 return str + child->ToString(depth: depth + 1);
67}
68
69} // namespace duckdb
70