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 | |
9 | using namespace duckdb; |
10 | using namespace std; |
11 | |
12 | unique_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 |