1#include "duckdb/parser/expression/constant_expression.hpp"
2#include "duckdb/parser/expression_map.hpp"
3#include "duckdb/parser/query_node/select_node.hpp"
4#include "duckdb/parser/query_node/recursive_cte_node.hpp"
5#include "duckdb/planner/binder.hpp"
6#include "duckdb/planner/query_node/bound_recursive_cte_node.hpp"
7#include "duckdb/planner/query_node/bound_select_node.hpp"
8
9using namespace duckdb;
10using namespace std;
11
12unique_ptr<BoundQueryNode> Binder::BindNode(RecursiveCTENode &statement) {
13 auto result = make_unique<BoundRecursiveCTENode>();
14
15 // first recursively visit the recursive CTE operations
16 // the left side is visited first and is added to the BindContext of the right side
17 assert(statement.left);
18 assert(statement.right);
19
20 result->ctename = statement.ctename;
21 result->union_all = statement.union_all;
22 result->setop_index = GenerateTableIndex();
23
24 result->left_binder = make_unique<Binder>(context, this);
25 result->left = result->left_binder->BindNode(*statement.left);
26
27 // This allows the right side to reference the CTE recursively
28 bind_context.AddGenericBinding(result->setop_index, statement.ctename, result->left->names, result->left->types);
29
30 result->right_binder = make_unique<Binder>(context, this);
31
32 // Add bindings of left side to temporary CTE bindings context
33 result->right_binder->bind_context.AddCTEBinding(result->setop_index, statement.ctename, result->left->names,
34 result->left->types);
35 result->right = result->right_binder->BindNode(*statement.right);
36
37 // Check if there are aggregates present in the recursive term
38 switch (result->right->type) {
39 case QueryNodeType::SELECT_NODE:
40 if (!((BoundSelectNode *)result->right.get())->aggregates.empty()) {
41 throw Exception("Aggregate functions are not allowed in a recursive query's recursive term");
42 }
43 break;
44 default:
45 break;
46 }
47
48 result->names = result->left->names;
49
50 // move the correlated expressions from the child binders to this binder
51 MoveCorrelatedExpressions(*result->left_binder);
52 MoveCorrelatedExpressions(*result->right_binder);
53
54 // now both sides have been bound we can resolve types
55 if (result->left->types.size() != result->right->types.size()) {
56 throw Exception("Set operations can only apply to expressions with the "
57 "same number of result columns");
58 }
59
60 // figure out the types of the recursive CTE result by picking the max of both
61 for (idx_t i = 0; i < result->left->types.size(); i++) {
62 auto result_type = MaxSQLType(result->left->types[i], result->right->types[i]);
63 result->types.push_back(result_type);
64 }
65 if (statement.modifiers.size() > 0) {
66 throw Exception("FIXME: bind modifiers in recursive CTE");
67 }
68
69 return move(result);
70}
71