1#include "duckdb/execution/physical_plan_generator.hpp"
2
3#include "duckdb/catalog/catalog_entry/scalar_function_catalog_entry.hpp"
4#include "duckdb/common/types/column/column_data_collection.hpp"
5#include "duckdb/execution/column_binding_resolver.hpp"
6#include "duckdb/main/client_context.hpp"
7#include "duckdb/main/config.hpp"
8#include "duckdb/main/query_profiler.hpp"
9#include "duckdb/planner/expression/bound_function_expression.hpp"
10#include "duckdb/planner/operator/logical_extension_operator.hpp"
11#include "duckdb/planner/operator/list.hpp"
12
13namespace duckdb {
14
15class DependencyExtractor : public LogicalOperatorVisitor {
16public:
17 explicit DependencyExtractor(DependencyList &dependencies) : dependencies(dependencies) {
18 }
19
20protected:
21 unique_ptr<Expression> VisitReplace(BoundFunctionExpression &expr, unique_ptr<Expression> *expr_ptr) override {
22 // extract dependencies from the bound function expression
23 if (expr.function.dependency) {
24 expr.function.dependency(expr, dependencies);
25 }
26 return nullptr;
27 }
28
29private:
30 DependencyList &dependencies;
31};
32
33PhysicalPlanGenerator::PhysicalPlanGenerator(ClientContext &context) : context(context) {
34}
35
36PhysicalPlanGenerator::~PhysicalPlanGenerator() {
37}
38
39unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(unique_ptr<LogicalOperator> op) {
40 auto &profiler = QueryProfiler::Get(context);
41
42 // first resolve column references
43 profiler.StartPhase(phase: "column_binding");
44 ColumnBindingResolver resolver;
45 resolver.VisitOperator(op&: *op);
46 profiler.EndPhase();
47
48 // now resolve types of all the operators
49 profiler.StartPhase(phase: "resolve_types");
50 op->ResolveOperatorTypes();
51 profiler.EndPhase();
52
53 // extract dependencies from the logical plan
54 DependencyExtractor extractor(dependencies);
55 extractor.VisitOperator(op&: *op);
56
57 // then create the main physical plan
58 profiler.StartPhase(phase: "create_plan");
59 auto plan = CreatePlan(op&: *op);
60 profiler.EndPhase();
61
62 plan->Verify();
63 return plan;
64}
65
66unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalOperator &op) {
67 op.estimated_cardinality = op.EstimateCardinality(context);
68 unique_ptr<PhysicalOperator> plan = nullptr;
69
70 switch (op.type) {
71 case LogicalOperatorType::LOGICAL_GET:
72 plan = CreatePlan(op&: op.Cast<LogicalGet>());
73 break;
74 case LogicalOperatorType::LOGICAL_PROJECTION:
75 plan = CreatePlan(op&: op.Cast<LogicalProjection>());
76 break;
77 case LogicalOperatorType::LOGICAL_EMPTY_RESULT:
78 plan = CreatePlan(op&: op.Cast<LogicalEmptyResult>());
79 break;
80 case LogicalOperatorType::LOGICAL_FILTER:
81 plan = CreatePlan(op&: op.Cast<LogicalFilter>());
82 break;
83 case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY:
84 plan = CreatePlan(op&: op.Cast<LogicalAggregate>());
85 break;
86 case LogicalOperatorType::LOGICAL_WINDOW:
87 plan = CreatePlan(expr&: op.Cast<LogicalWindow>());
88 break;
89 case LogicalOperatorType::LOGICAL_UNNEST:
90 plan = CreatePlan(op&: op.Cast<LogicalUnnest>());
91 break;
92 case LogicalOperatorType::LOGICAL_LIMIT:
93 plan = CreatePlan(op&: op.Cast<LogicalLimit>());
94 break;
95 case LogicalOperatorType::LOGICAL_LIMIT_PERCENT:
96 plan = CreatePlan(op&: op.Cast<LogicalLimitPercent>());
97 break;
98 case LogicalOperatorType::LOGICAL_SAMPLE:
99 plan = CreatePlan(op&: op.Cast<LogicalSample>());
100 break;
101 case LogicalOperatorType::LOGICAL_ORDER_BY:
102 plan = CreatePlan(op&: op.Cast<LogicalOrder>());
103 break;
104 case LogicalOperatorType::LOGICAL_TOP_N:
105 plan = CreatePlan(op&: op.Cast<LogicalTopN>());
106 break;
107 case LogicalOperatorType::LOGICAL_COPY_TO_FILE:
108 plan = CreatePlan(op&: op.Cast<LogicalCopyToFile>());
109 break;
110 case LogicalOperatorType::LOGICAL_DUMMY_SCAN:
111 plan = CreatePlan(expr&: op.Cast<LogicalDummyScan>());
112 break;
113 case LogicalOperatorType::LOGICAL_ANY_JOIN:
114 plan = CreatePlan(op&: op.Cast<LogicalAnyJoin>());
115 break;
116 case LogicalOperatorType::LOGICAL_DELIM_JOIN:
117 plan = CreatePlan(op&: op.Cast<LogicalDelimJoin>());
118 break;
119 case LogicalOperatorType::LOGICAL_ASOF_JOIN:
120 plan = CreatePlan(op&: op.Cast<LogicalAsOfJoin>());
121 break;
122 case LogicalOperatorType::LOGICAL_COMPARISON_JOIN:
123 plan = CreatePlan(op&: op.Cast<LogicalComparisonJoin>());
124 break;
125 case LogicalOperatorType::LOGICAL_CROSS_PRODUCT:
126 plan = CreatePlan(op&: op.Cast<LogicalCrossProduct>());
127 break;
128 case LogicalOperatorType::LOGICAL_POSITIONAL_JOIN:
129 plan = CreatePlan(op&: op.Cast<LogicalPositionalJoin>());
130 break;
131 case LogicalOperatorType::LOGICAL_UNION:
132 case LogicalOperatorType::LOGICAL_EXCEPT:
133 case LogicalOperatorType::LOGICAL_INTERSECT:
134 plan = CreatePlan(op&: op.Cast<LogicalSetOperation>());
135 break;
136 case LogicalOperatorType::LOGICAL_INSERT:
137 plan = CreatePlan(op&: op.Cast<LogicalInsert>());
138 break;
139 case LogicalOperatorType::LOGICAL_DELETE:
140 plan = CreatePlan(op&: op.Cast<LogicalDelete>());
141 break;
142 case LogicalOperatorType::LOGICAL_CHUNK_GET:
143 plan = CreatePlan(op&: op.Cast<LogicalColumnDataGet>());
144 break;
145 case LogicalOperatorType::LOGICAL_DELIM_GET:
146 plan = CreatePlan(op&: op.Cast<LogicalDelimGet>());
147 break;
148 case LogicalOperatorType::LOGICAL_EXPRESSION_GET:
149 plan = CreatePlan(op&: op.Cast<LogicalExpressionGet>());
150 break;
151 case LogicalOperatorType::LOGICAL_UPDATE:
152 plan = CreatePlan(op&: op.Cast<LogicalUpdate>());
153 break;
154 case LogicalOperatorType::LOGICAL_CREATE_TABLE:
155 plan = CreatePlan(op&: op.Cast<LogicalCreateTable>());
156 break;
157 case LogicalOperatorType::LOGICAL_CREATE_INDEX:
158 plan = CreatePlan(op&: op.Cast<LogicalCreateIndex>());
159 break;
160 case LogicalOperatorType::LOGICAL_EXPLAIN:
161 plan = CreatePlan(op&: op.Cast<LogicalExplain>());
162 break;
163 case LogicalOperatorType::LOGICAL_SHOW:
164 plan = CreatePlan(op&: op.Cast<LogicalShow>());
165 break;
166 case LogicalOperatorType::LOGICAL_DISTINCT:
167 plan = CreatePlan(op&: op.Cast<LogicalDistinct>());
168 break;
169 case LogicalOperatorType::LOGICAL_PREPARE:
170 plan = CreatePlan(expr&: op.Cast<LogicalPrepare>());
171 break;
172 case LogicalOperatorType::LOGICAL_EXECUTE:
173 plan = CreatePlan(op&: op.Cast<LogicalExecute>());
174 break;
175 case LogicalOperatorType::LOGICAL_CREATE_VIEW:
176 case LogicalOperatorType::LOGICAL_CREATE_SEQUENCE:
177 case LogicalOperatorType::LOGICAL_CREATE_SCHEMA:
178 case LogicalOperatorType::LOGICAL_CREATE_MACRO:
179 case LogicalOperatorType::LOGICAL_CREATE_TYPE:
180 plan = CreatePlan(op&: op.Cast<LogicalCreate>());
181 break;
182 case LogicalOperatorType::LOGICAL_PRAGMA:
183 plan = CreatePlan(op&: op.Cast<LogicalPragma>());
184 break;
185 case LogicalOperatorType::LOGICAL_TRANSACTION:
186 case LogicalOperatorType::LOGICAL_ALTER:
187 case LogicalOperatorType::LOGICAL_DROP:
188 case LogicalOperatorType::LOGICAL_VACUUM:
189 case LogicalOperatorType::LOGICAL_LOAD:
190 case LogicalOperatorType::LOGICAL_ATTACH:
191 case LogicalOperatorType::LOGICAL_DETACH:
192 plan = CreatePlan(op&: op.Cast<LogicalSimple>());
193 break;
194 case LogicalOperatorType::LOGICAL_RECURSIVE_CTE:
195 plan = CreatePlan(op&: op.Cast<LogicalRecursiveCTE>());
196 break;
197 case LogicalOperatorType::LOGICAL_CTE_REF:
198 plan = CreatePlan(op&: op.Cast<LogicalCTERef>());
199 break;
200 case LogicalOperatorType::LOGICAL_EXPORT:
201 plan = CreatePlan(op&: op.Cast<LogicalExport>());
202 break;
203 case LogicalOperatorType::LOGICAL_SET:
204 plan = CreatePlan(op&: op.Cast<LogicalSet>());
205 break;
206 case LogicalOperatorType::LOGICAL_RESET:
207 plan = CreatePlan(op&: op.Cast<LogicalReset>());
208 break;
209 case LogicalOperatorType::LOGICAL_PIVOT:
210 plan = CreatePlan(op&: op.Cast<LogicalPivot>());
211 break;
212 case LogicalOperatorType::LOGICAL_EXTENSION_OPERATOR:
213 plan = op.Cast<LogicalExtensionOperator>().CreatePlan(context, generator&: *this);
214
215 if (!plan) {
216 throw InternalException("Missing PhysicalOperator for Extension Operator");
217 }
218 break;
219 case LogicalOperatorType::LOGICAL_JOIN:
220 case LogicalOperatorType::LOGICAL_INVALID: {
221 throw NotImplementedException("Unimplemented logical operator type!");
222 }
223 }
224 if (!plan) {
225 throw InternalException("Physical plan generator - no plan generated");
226 }
227
228 if (op.estimated_props) {
229 plan->estimated_cardinality = op.estimated_props->GetCardinality<idx_t>();
230 plan->estimated_props = op.estimated_props->Copy();
231 } else {
232 plan->estimated_props = make_uniq<EstimatedProperties>();
233 }
234
235 return plan;
236}
237
238} // namespace duckdb
239