1#include "duckdb/planner/logical_operator.hpp"
2
3#include "duckdb/common/field_writer.hpp"
4#include "duckdb/common/printer.hpp"
5#include "duckdb/common/serializer/buffered_deserializer.hpp"
6#include "duckdb/common/string_util.hpp"
7#include "duckdb/common/tree_renderer.hpp"
8#include "duckdb/parser/parser.hpp"
9#include "duckdb/planner/operator/list.hpp"
10#include "duckdb/planner/operator/logical_extension_operator.hpp"
11
12namespace duckdb {
13
14const uint64_t PLAN_SERIALIZATION_VERSION = 1;
15
16LogicalOperator::LogicalOperator(LogicalOperatorType type)
17 : type(type), estimated_cardinality(0), has_estimated_cardinality(false) {
18}
19
20LogicalOperator::LogicalOperator(LogicalOperatorType type, vector<unique_ptr<Expression>> expressions)
21 : type(type), expressions(std::move(expressions)), estimated_cardinality(0), has_estimated_cardinality(false) {
22}
23
24LogicalOperator::~LogicalOperator() {
25}
26
27vector<ColumnBinding> LogicalOperator::GetColumnBindings() {
28 return {ColumnBinding(0, 0)};
29}
30
31string LogicalOperator::GetName() const {
32 return LogicalOperatorToString(type);
33}
34
35string LogicalOperator::ParamsToString() const {
36 string result;
37 for (idx_t i = 0; i < expressions.size(); i++) {
38 if (i > 0) {
39 result += "\n";
40 }
41 result += expressions[i]->GetName();
42 }
43 return result;
44}
45
46void LogicalOperator::ResolveOperatorTypes() {
47
48 types.clear();
49 // first resolve child types
50 for (auto &child : children) {
51 child->ResolveOperatorTypes();
52 }
53 // now resolve the types for this operator
54 ResolveTypes();
55 D_ASSERT(types.size() == GetColumnBindings().size());
56}
57
58vector<ColumnBinding> LogicalOperator::GenerateColumnBindings(idx_t table_idx, idx_t column_count) {
59 vector<ColumnBinding> result;
60 result.reserve(n: column_count);
61 for (idx_t i = 0; i < column_count; i++) {
62 result.emplace_back(args&: table_idx, args&: i);
63 }
64 return result;
65}
66
67vector<LogicalType> LogicalOperator::MapTypes(const vector<LogicalType> &types, const vector<idx_t> &projection_map) {
68 if (projection_map.empty()) {
69 return types;
70 } else {
71 vector<LogicalType> result_types;
72 result_types.reserve(n: projection_map.size());
73 for (auto index : projection_map) {
74 result_types.push_back(x: types[index]);
75 }
76 return result_types;
77 }
78}
79
80vector<ColumnBinding> LogicalOperator::MapBindings(const vector<ColumnBinding> &bindings,
81 const vector<idx_t> &projection_map) {
82 if (projection_map.empty()) {
83 return bindings;
84 } else {
85 vector<ColumnBinding> result_bindings;
86 result_bindings.reserve(n: projection_map.size());
87 for (auto index : projection_map) {
88 D_ASSERT(index < bindings.size());
89 result_bindings.push_back(x: bindings[index]);
90 }
91 return result_bindings;
92 }
93}
94
95string LogicalOperator::ToString() const {
96 TreeRenderer renderer;
97 return renderer.ToString(op: *this);
98}
99
100void LogicalOperator::Verify(ClientContext &context) {
101#ifdef DEBUG
102 // verify expressions
103 for (idx_t expr_idx = 0; expr_idx < expressions.size(); expr_idx++) {
104 auto str = expressions[expr_idx]->ToString();
105 // verify that we can (correctly) copy this expression
106 auto copy = expressions[expr_idx]->Copy();
107 auto original_hash = expressions[expr_idx]->Hash();
108 auto copy_hash = copy->Hash();
109 // copy should be identical to original
110 D_ASSERT(expressions[expr_idx]->ToString() == copy->ToString());
111 D_ASSERT(original_hash == copy_hash);
112 D_ASSERT(Expression::Equals(expressions[expr_idx], copy));
113
114 for (idx_t other_idx = 0; other_idx < expr_idx; other_idx++) {
115 // comparison with other expressions
116 auto other_hash = expressions[other_idx]->Hash();
117 bool expr_equal = Expression::Equals(expressions[expr_idx], expressions[other_idx]);
118 if (original_hash != other_hash) {
119 // if the hashes are not equal the expressions should not be equal either
120 D_ASSERT(!expr_equal);
121 }
122 }
123 D_ASSERT(!str.empty());
124
125 // verify that serialization + deserialization round-trips correctly
126 if (expressions[expr_idx]->HasParameter()) {
127 continue;
128 }
129 BufferedSerializer serializer;
130 // We are serializing a query plan
131 serializer.is_query_plan = true;
132 try {
133 expressions[expr_idx]->Serialize(serializer);
134 } catch (NotImplementedException &ex) {
135 // ignore for now (FIXME)
136 return;
137 }
138
139 auto data = serializer.GetData();
140 auto deserializer = BufferedContextDeserializer(context, data.data.get(), data.size);
141
142 PlanDeserializationState state(context);
143 auto deserialized_expression = Expression::Deserialize(deserializer, state);
144 // FIXME: expressions might not be equal yet because of statistics propagation
145 continue;
146 D_ASSERT(Expression::Equals(expressions[expr_idx], deserialized_expression));
147 D_ASSERT(expressions[expr_idx]->Hash() == deserialized_expression->Hash());
148 }
149 D_ASSERT(!ToString().empty());
150 for (auto &child : children) {
151 child->Verify(context);
152 }
153#endif
154}
155
156void LogicalOperator::AddChild(unique_ptr<LogicalOperator> child) {
157 D_ASSERT(child);
158 children.push_back(x: std::move(child));
159}
160
161idx_t LogicalOperator::EstimateCardinality(ClientContext &context) {
162 // simple estimator, just take the max of the children
163 if (has_estimated_cardinality) {
164 return estimated_cardinality;
165 }
166 idx_t max_cardinality = 0;
167 for (auto &child : children) {
168 max_cardinality = MaxValue(a: child->EstimateCardinality(context), b: max_cardinality);
169 }
170 has_estimated_cardinality = true;
171 estimated_cardinality = max_cardinality;
172 return estimated_cardinality;
173}
174
175void LogicalOperator::Print() {
176 Printer::Print(str: ToString());
177}
178
179void LogicalOperator::Serialize(Serializer &serializer) const {
180 FieldWriter writer(serializer);
181 writer.WriteField<LogicalOperatorType>(element: type);
182 writer.WriteSerializableList(elements: children);
183
184 Serialize(writer);
185 writer.Finalize();
186}
187
188unique_ptr<LogicalOperator> LogicalOperator::Deserialize(Deserializer &deserializer, PlanDeserializationState &gstate) {
189 unique_ptr<LogicalOperator> result;
190
191 FieldReader reader(deserializer);
192 auto type = reader.ReadRequired<LogicalOperatorType>();
193 auto children = reader.ReadRequiredSerializableList<LogicalOperator>(args&: gstate);
194
195 LogicalDeserializationState state(gstate, type, children);
196 switch (type) {
197 case LogicalOperatorType::LOGICAL_PROJECTION:
198 result = LogicalProjection::Deserialize(state, reader);
199 break;
200 case LogicalOperatorType::LOGICAL_FILTER:
201 result = LogicalFilter::Deserialize(state, reader);
202 break;
203 case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY:
204 result = LogicalAggregate::Deserialize(state, reader);
205 break;
206 case LogicalOperatorType::LOGICAL_WINDOW:
207 result = LogicalWindow::Deserialize(state, reader);
208 break;
209 case LogicalOperatorType::LOGICAL_UNNEST:
210 result = LogicalUnnest::Deserialize(state, reader);
211 break;
212 case LogicalOperatorType::LOGICAL_LIMIT:
213 result = LogicalLimit::Deserialize(state, reader);
214 break;
215 case LogicalOperatorType::LOGICAL_ORDER_BY:
216 result = LogicalOrder::Deserialize(state, reader);
217 break;
218 case LogicalOperatorType::LOGICAL_TOP_N:
219 result = LogicalTopN::Deserialize(state, reader);
220 break;
221 case LogicalOperatorType::LOGICAL_COPY_TO_FILE:
222 result = LogicalCopyToFile::Deserialize(state, reader);
223 break;
224 case LogicalOperatorType::LOGICAL_DISTINCT:
225 result = LogicalDistinct::Deserialize(state, reader);
226 break;
227 case LogicalOperatorType::LOGICAL_SAMPLE:
228 result = LogicalSample::Deserialize(state, reader);
229 break;
230 case LogicalOperatorType::LOGICAL_LIMIT_PERCENT:
231 result = LogicalLimitPercent::Deserialize(state, reader);
232 break;
233 case LogicalOperatorType::LOGICAL_GET:
234 result = LogicalGet::Deserialize(state, reader);
235 break;
236 case LogicalOperatorType::LOGICAL_CHUNK_GET:
237 result = LogicalColumnDataGet::Deserialize(state, reader);
238 break;
239 case LogicalOperatorType::LOGICAL_DELIM_GET:
240 result = LogicalDelimGet::Deserialize(state, reader);
241 break;
242 case LogicalOperatorType::LOGICAL_EXPRESSION_GET:
243 result = LogicalExpressionGet::Deserialize(state, reader);
244 break;
245 case LogicalOperatorType::LOGICAL_DUMMY_SCAN:
246 result = LogicalDummyScan::Deserialize(state, reader);
247 break;
248 case LogicalOperatorType::LOGICAL_EMPTY_RESULT:
249 result = LogicalEmptyResult::Deserialize(state, reader);
250 break;
251 case LogicalOperatorType::LOGICAL_CTE_REF:
252 result = LogicalCTERef::Deserialize(state, reader);
253 break;
254 case LogicalOperatorType::LOGICAL_JOIN:
255 throw InternalException("LogicalJoin deserialize not supported");
256 case LogicalOperatorType::LOGICAL_DELIM_JOIN:
257 result = LogicalDelimJoin::Deserialize(state, reader);
258 break;
259 case LogicalOperatorType::LOGICAL_ASOF_JOIN:
260 result = LogicalAsOfJoin::Deserialize(state, reader);
261 break;
262 case LogicalOperatorType::LOGICAL_COMPARISON_JOIN:
263 result = LogicalComparisonJoin::Deserialize(state, reader);
264 break;
265 case LogicalOperatorType::LOGICAL_ANY_JOIN:
266 result = LogicalAnyJoin::Deserialize(state, reader);
267 break;
268 case LogicalOperatorType::LOGICAL_CROSS_PRODUCT:
269 result = LogicalCrossProduct::Deserialize(state, reader);
270 break;
271 case LogicalOperatorType::LOGICAL_POSITIONAL_JOIN:
272 result = LogicalPositionalJoin::Deserialize(state, reader);
273 break;
274 case LogicalOperatorType::LOGICAL_UNION:
275 result = LogicalSetOperation::Deserialize(state, reader);
276 break;
277 case LogicalOperatorType::LOGICAL_EXCEPT:
278 result = LogicalSetOperation::Deserialize(state, reader);
279 break;
280 case LogicalOperatorType::LOGICAL_INTERSECT:
281 result = LogicalSetOperation::Deserialize(state, reader);
282 break;
283 case LogicalOperatorType::LOGICAL_RECURSIVE_CTE:
284 result = LogicalRecursiveCTE::Deserialize(state, reader);
285 break;
286 case LogicalOperatorType::LOGICAL_INSERT:
287 result = LogicalInsert::Deserialize(state, reader);
288 break;
289 case LogicalOperatorType::LOGICAL_DELETE:
290 result = LogicalDelete::Deserialize(state, reader);
291 break;
292 case LogicalOperatorType::LOGICAL_UPDATE:
293 result = LogicalUpdate::Deserialize(state, reader);
294 break;
295 case LogicalOperatorType::LOGICAL_CREATE_TABLE:
296 result = LogicalCreateTable::Deserialize(state, reader);
297 break;
298 case LogicalOperatorType::LOGICAL_CREATE_INDEX:
299 result = LogicalCreateIndex::Deserialize(state, reader);
300 break;
301 case LogicalOperatorType::LOGICAL_CREATE_SEQUENCE:
302 result = LogicalCreate::Deserialize(state, reader);
303 break;
304 case LogicalOperatorType::LOGICAL_CREATE_VIEW:
305 result = LogicalCreate::Deserialize(state, reader);
306 break;
307 case LogicalOperatorType::LOGICAL_CREATE_SCHEMA:
308 result = LogicalCreate::Deserialize(state, reader);
309 break;
310 case LogicalOperatorType::LOGICAL_CREATE_MACRO:
311 result = LogicalCreate::Deserialize(state, reader);
312 break;
313 case LogicalOperatorType::LOGICAL_PRAGMA:
314 result = LogicalPragma::Deserialize(state, reader);
315 break;
316 case LogicalOperatorType::LOGICAL_CREATE_TYPE:
317 result = LogicalCreate::Deserialize(state, reader);
318 break;
319 case LogicalOperatorType::LOGICAL_EXPLAIN:
320 result = LogicalExplain::Deserialize(state, reader);
321 break;
322 case LogicalOperatorType::LOGICAL_SHOW:
323 result = LogicalShow::Deserialize(state, reader);
324 break;
325 case LogicalOperatorType::LOGICAL_PREPARE:
326 result = LogicalPrepare::Deserialize(state, reader);
327 break;
328 case LogicalOperatorType::LOGICAL_EXECUTE:
329 result = LogicalExecute::Deserialize(state, reader);
330 break;
331 case LogicalOperatorType::LOGICAL_EXPORT:
332 result = LogicalExport::Deserialize(state, reader);
333 break;
334 case LogicalOperatorType::LOGICAL_SET:
335 result = LogicalSet::Deserialize(state, reader);
336 break;
337 case LogicalOperatorType::LOGICAL_RESET:
338 result = LogicalReset::Deserialize(state, reader);
339 break;
340 case LogicalOperatorType::LOGICAL_ALTER:
341 case LogicalOperatorType::LOGICAL_VACUUM:
342 case LogicalOperatorType::LOGICAL_LOAD:
343 case LogicalOperatorType::LOGICAL_ATTACH:
344 case LogicalOperatorType::LOGICAL_TRANSACTION:
345 case LogicalOperatorType::LOGICAL_DROP:
346 case LogicalOperatorType::LOGICAL_DETACH:
347 result = LogicalSimple::Deserialize(state, reader);
348 break;
349 case LogicalOperatorType::LOGICAL_EXTENSION_OPERATOR:
350 result = LogicalExtensionOperator::Deserialize(state, reader);
351 break;
352 case LogicalOperatorType::LOGICAL_PIVOT:
353 result = LogicalPivot::Deserialize(state, reader);
354 break;
355 case LogicalOperatorType::LOGICAL_INVALID:
356 /* no default here to trigger a warning if we forget to implement deserialize for a new operator */
357 throw SerializationException("Invalid type for operator deserialization");
358 }
359
360 reader.Finalize();
361 result->children = std::move(children);
362
363 return result;
364}
365
366vector<idx_t> LogicalOperator::GetTableIndex() const {
367 return vector<idx_t> {};
368}
369
370unique_ptr<LogicalOperator> LogicalOperator::Copy(ClientContext &context) const {
371 BufferedSerializer logical_op_serializer;
372 try {
373 this->Serialize(serializer&: logical_op_serializer);
374 } catch (NotImplementedException &ex) {
375 throw NotImplementedException("Logical Operator Copy requires the logical operator and all of its children to "
376 "be serializable: " +
377 std::string(ex.what()));
378 }
379 auto data = logical_op_serializer.GetData();
380 auto logical_op_deserializer = BufferedContextDeserializer(context, data.data.get(), data.size);
381 PlanDeserializationState state(context);
382 auto op_copy = LogicalOperator::Deserialize(deserializer&: logical_op_deserializer, gstate&: state);
383 return op_copy;
384}
385
386} // namespace duckdb
387