| 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 |