1 | #include "duckdb/planner/binder.hpp" |
2 | #include "duckdb/planner/expression/bound_columnref_expression.hpp" |
3 | #include "duckdb/planner/expression/bound_reference_expression.hpp" |
4 | #include "duckdb/planner/operator/list.hpp" |
5 | #include "duckdb/planner/operator/logical_dummy_scan.hpp" |
6 | #include "duckdb/planner/operator/logical_limit.hpp" |
7 | #include "duckdb/planner/query_node/bound_select_node.hpp" |
8 | |
9 | namespace duckdb { |
10 | |
11 | unique_ptr<LogicalOperator> Binder::PlanFilter(unique_ptr<Expression> condition, unique_ptr<LogicalOperator> root) { |
12 | PlanSubqueries(expr&: condition, root); |
13 | auto filter = make_uniq<LogicalFilter>(args: std::move(condition)); |
14 | filter->AddChild(child: std::move(root)); |
15 | return std::move(filter); |
16 | } |
17 | |
18 | unique_ptr<LogicalOperator> Binder::CreatePlan(BoundSelectNode &statement) { |
19 | unique_ptr<LogicalOperator> root; |
20 | D_ASSERT(statement.from_table); |
21 | root = CreatePlan(ref&: *statement.from_table); |
22 | D_ASSERT(root); |
23 | |
24 | // plan the sample clause |
25 | if (statement.sample_options) { |
26 | root = make_uniq<LogicalSample>(args: std::move(statement.sample_options), args: std::move(root)); |
27 | } |
28 | |
29 | if (statement.where_clause) { |
30 | root = PlanFilter(condition: std::move(statement.where_clause), root: std::move(root)); |
31 | } |
32 | |
33 | if (!statement.aggregates.empty() || !statement.groups.group_expressions.empty()) { |
34 | if (!statement.groups.group_expressions.empty()) { |
35 | // visit the groups |
36 | for (auto &group : statement.groups.group_expressions) { |
37 | PlanSubqueries(expr&: group, root); |
38 | } |
39 | } |
40 | // now visit all aggregate expressions |
41 | for (auto &expr : statement.aggregates) { |
42 | PlanSubqueries(expr, root); |
43 | } |
44 | // finally create the aggregate node with the group_index and aggregate_index as obtained from the binder |
45 | auto aggregate = make_uniq<LogicalAggregate>(args&: statement.group_index, args&: statement.aggregate_index, |
46 | args: std::move(statement.aggregates)); |
47 | aggregate->groups = std::move(statement.groups.group_expressions); |
48 | aggregate->groupings_index = statement.groupings_index; |
49 | aggregate->grouping_sets = std::move(statement.groups.grouping_sets); |
50 | aggregate->grouping_functions = std::move(statement.grouping_functions); |
51 | |
52 | aggregate->AddChild(child: std::move(root)); |
53 | root = std::move(aggregate); |
54 | } else if (!statement.groups.grouping_sets.empty()) { |
55 | // edge case: we have grouping sets but no groups or aggregates |
56 | // this can only happen if we have e.g. select 1 from tbl group by (); |
57 | // just output a dummy scan |
58 | root = make_uniq_base<LogicalOperator, LogicalDummyScan>(args&: statement.group_index); |
59 | } |
60 | |
61 | if (statement.having) { |
62 | PlanSubqueries(expr&: statement.having, root); |
63 | auto having = make_uniq<LogicalFilter>(args: std::move(statement.having)); |
64 | |
65 | having->AddChild(child: std::move(root)); |
66 | root = std::move(having); |
67 | } |
68 | |
69 | if (!statement.windows.empty()) { |
70 | auto win = make_uniq<LogicalWindow>(args&: statement.window_index); |
71 | win->expressions = std::move(statement.windows); |
72 | // visit the window expressions |
73 | for (auto &expr : win->expressions) { |
74 | PlanSubqueries(expr, root); |
75 | } |
76 | D_ASSERT(!win->expressions.empty()); |
77 | win->AddChild(child: std::move(root)); |
78 | root = std::move(win); |
79 | } |
80 | |
81 | if (statement.qualify) { |
82 | PlanSubqueries(expr&: statement.qualify, root); |
83 | auto qualify = make_uniq<LogicalFilter>(args: std::move(statement.qualify)); |
84 | |
85 | qualify->AddChild(child: std::move(root)); |
86 | root = std::move(qualify); |
87 | } |
88 | |
89 | for (idx_t i = statement.unnests.size(); i > 0; i--) { |
90 | auto unnest_level = i - 1; |
91 | auto entry = statement.unnests.find(x: unnest_level); |
92 | if (entry == statement.unnests.end()) { |
93 | throw InternalException("unnests specified at level %d but none were found" , unnest_level); |
94 | } |
95 | auto &unnest_node = entry->second; |
96 | auto unnest = make_uniq<LogicalUnnest>(args&: unnest_node.index); |
97 | unnest->expressions = std::move(unnest_node.expressions); |
98 | // visit the unnest expressions |
99 | for (auto &expr : unnest->expressions) { |
100 | PlanSubqueries(expr, root); |
101 | } |
102 | D_ASSERT(!unnest->expressions.empty()); |
103 | unnest->AddChild(child: std::move(root)); |
104 | root = std::move(unnest); |
105 | } |
106 | |
107 | for (auto &expr : statement.select_list) { |
108 | PlanSubqueries(expr, root); |
109 | } |
110 | |
111 | auto proj = make_uniq<LogicalProjection>(args&: statement.projection_index, args: std::move(statement.select_list)); |
112 | auto &projection = *proj; |
113 | proj->AddChild(child: std::move(root)); |
114 | root = std::move(proj); |
115 | |
116 | // finish the plan by handling the elements of the QueryNode |
117 | root = VisitQueryNode(node&: statement, root: std::move(root)); |
118 | |
119 | // add a prune node if necessary |
120 | if (statement.need_prune) { |
121 | D_ASSERT(root); |
122 | vector<unique_ptr<Expression>> prune_expressions; |
123 | for (idx_t i = 0; i < statement.column_count; i++) { |
124 | prune_expressions.push_back(x: make_uniq<BoundColumnRefExpression>( |
125 | args&: projection.expressions[i]->return_type, args: ColumnBinding(statement.projection_index, i))); |
126 | } |
127 | auto prune = make_uniq<LogicalProjection>(args&: statement.prune_index, args: std::move(prune_expressions)); |
128 | prune->AddChild(child: std::move(root)); |
129 | root = std::move(prune); |
130 | } |
131 | return root; |
132 | } |
133 | |
134 | } // namespace duckdb |
135 | |