1#include "duckdb/planner/binder.hpp"
2#include "duckdb/planner/operator/list.hpp"
3#include "duckdb/planner/query_node/bound_select_node.hpp"
4#include "duckdb/planner/operator/logical_expression_get.hpp"
5#include "duckdb/planner/expression/bound_columnref_expression.hpp"
6
7using namespace duckdb;
8using namespace std;
9
10unique_ptr<LogicalOperator> Binder::PlanFilter(unique_ptr<Expression> condition, unique_ptr<LogicalOperator> root) {
11 PlanSubqueries(&condition, &root);
12 auto filter = make_unique<LogicalFilter>(move(condition));
13 filter->AddChild(move(root));
14 return move(filter);
15}
16
17unique_ptr<LogicalOperator> Binder::CreatePlan(BoundSelectNode &statement) {
18 unique_ptr<LogicalOperator> root;
19 assert(statement.from_table);
20 root = CreatePlan(*statement.from_table);
21 assert(root);
22
23 if (statement.where_clause) {
24 root = PlanFilter(move(statement.where_clause), move(root));
25 }
26
27 if (statement.aggregates.size() > 0 || statement.groups.size() > 0) {
28 if (statement.groups.size() > 0) {
29 // visit the groups
30 for (idx_t i = 0; i < statement.groups.size(); i++) {
31 auto &group = statement.groups[i];
32 PlanSubqueries(&group, &root);
33 }
34 }
35 // now visit all aggregate expressions
36 for (auto &expr : statement.aggregates) {
37 PlanSubqueries(&expr, &root);
38 }
39 // finally create the aggregate node with the group_index and aggregate_index as obtained from the binder
40 auto aggregate =
41 make_unique<LogicalAggregate>(statement.group_index, statement.aggregate_index, move(statement.aggregates));
42 aggregate->groups = move(statement.groups);
43
44 aggregate->AddChild(move(root));
45 root = move(aggregate);
46 }
47
48 if (statement.having) {
49 PlanSubqueries(&statement.having, &root);
50 auto having = make_unique<LogicalFilter>(move(statement.having));
51
52 having->AddChild(move(root));
53 root = move(having);
54 }
55
56 if (statement.windows.size() > 0) {
57 auto win = make_unique<LogicalWindow>(statement.window_index);
58 win->expressions = move(statement.windows);
59 // visit the window expressions
60 for (auto &expr : win->expressions) {
61 PlanSubqueries(&expr, &root);
62 }
63 assert(win->expressions.size() > 0);
64 win->AddChild(move(root));
65 root = move(win);
66 }
67
68 if (statement.unnests.size() > 0) {
69 auto unnest = make_unique<LogicalUnnest>(statement.unnest_index);
70 unnest->expressions = move(statement.unnests);
71 // visit the window expressions
72 for (auto &expr : unnest->expressions) {
73 PlanSubqueries(&expr, &root);
74 }
75 assert(unnest->expressions.size() > 0);
76 unnest->AddChild(move(root));
77 root = move(unnest);
78 }
79
80 for (auto &expr : statement.select_list) {
81 PlanSubqueries(&expr, &root);
82 }
83
84 // create the projection
85 auto proj = make_unique<LogicalProjection>(statement.projection_index, move(statement.select_list));
86 auto &projection = *proj;
87 proj->AddChild(move(root));
88 root = move(proj);
89
90 // finish the plan by handling the elements of the QueryNode
91 root = VisitQueryNode(statement, move(root));
92
93 // add a prune node if necessary
94 if (statement.need_prune) {
95 assert(root);
96 vector<unique_ptr<Expression>> prune_expressions;
97 for (idx_t i = 0; i < statement.column_count; i++) {
98 prune_expressions.push_back(make_unique<BoundColumnRefExpression>(
99 projection.expressions[i]->return_type, ColumnBinding(statement.projection_index, i)));
100 }
101 auto prune = make_unique<LogicalProjection>(statement.prune_index, move(prune_expressions));
102 prune->AddChild(move(root));
103 root = move(prune);
104 }
105 return root;
106}
107