1#include "duckdb/common/types/column/column_data_collection.hpp"
2#include "duckdb/execution/operator/scan/physical_column_data_scan.hpp"
3#include "duckdb/execution/operator/set/physical_recursive_cte.hpp"
4#include "duckdb/execution/physical_plan_generator.hpp"
5#include "duckdb/planner/expression/bound_reference_expression.hpp"
6#include "duckdb/planner/operator/logical_cteref.hpp"
7#include "duckdb/planner/operator/logical_recursive_cte.hpp"
8
9namespace duckdb {
10
11unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalRecursiveCTE &op) {
12 D_ASSERT(op.children.size() == 2);
13
14 // Create the working_table that the PhysicalRecursiveCTE will use for evaluation.
15 auto working_table = std::make_shared<ColumnDataCollection>(args&: context, args&: op.types);
16
17 // Add the ColumnDataCollection to the context of this PhysicalPlanGenerator
18 recursive_cte_tables[op.table_index] = working_table;
19
20 auto left = CreatePlan(op&: *op.children[0]);
21 auto right = CreatePlan(op&: *op.children[1]);
22
23 auto cte = make_uniq<PhysicalRecursiveCTE>(args&: op.types, args&: op.union_all, args: std::move(left), args: std::move(right),
24 args&: op.estimated_cardinality);
25 cte->working_table = working_table;
26
27 return std::move(cte);
28}
29
30unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalCTERef &op) {
31 D_ASSERT(op.children.empty());
32
33 auto chunk_scan =
34 make_uniq<PhysicalColumnDataScan>(args&: op.types, args: PhysicalOperatorType::RECURSIVE_CTE_SCAN, args&: op.estimated_cardinality);
35
36 // CreatePlan of a LogicalRecursiveCTE must have happened before.
37 auto cte = recursive_cte_tables.find(x: op.cte_index);
38 if (cte == recursive_cte_tables.end()) {
39 throw InvalidInputException("Referenced recursive CTE does not exist.");
40 }
41 chunk_scan->collection = cte->second.get();
42 return std::move(chunk_scan);
43}
44
45} // namespace duckdb
46