| 1 | #include "duckdb/parser/tableref/joinref.hpp" |
| 2 | #include "duckdb/planner/binder.hpp" |
| 3 | #include "duckdb/planner/expression_binder/where_binder.hpp" |
| 4 | #include "duckdb/planner/tableref/bound_joinref.hpp" |
| 5 | #include "duckdb/parser/expression/columnref_expression.hpp" |
| 6 | #include "duckdb/parser/expression/comparison_expression.hpp" |
| 7 | #include "duckdb/parser/expression/conjunction_expression.hpp" |
| 8 | |
| 9 | using namespace duckdb; |
| 10 | using namespace std; |
| 11 | |
| 12 | unique_ptr<BoundTableRef> Binder::Bind(JoinRef &ref) { |
| 13 | auto result = make_unique<BoundJoinRef>(); |
| 14 | result->type = ref.type; |
| 15 | if (ref.using_columns.size() > 0) { |
| 16 | // USING columns |
| 17 | assert(!result->condition); |
| 18 | vector<string> left_join_bindings; |
| 19 | vector<unordered_set<string>> matching_left_bindings; |
| 20 | |
| 21 | result->left = Bind(*ref.left); |
| 22 | for (auto &using_column : ref.using_columns) { |
| 23 | // for each using column, get the matching binding |
| 24 | auto left_bindings = bind_context.GetMatchingBindings(using_column); |
| 25 | if (left_bindings.size() == 0) { |
| 26 | throw BinderException("Column \"%s\" does not exist on left side of join!" , using_column.c_str()); |
| 27 | } |
| 28 | // find the join binding |
| 29 | string left_binding; |
| 30 | for (auto &binding : left_bindings) { |
| 31 | if (!bind_context.BindingIsHidden(binding, using_column)) { |
| 32 | if (!left_binding.empty()) { |
| 33 | string error = "Column name \"" + using_column + |
| 34 | "\" is ambiguous: it exists more than once on left side of join.\nCandidates:" ; |
| 35 | for (auto &binding : left_bindings) { |
| 36 | error += "\n\t" + binding + "." + using_column; |
| 37 | } |
| 38 | throw BinderException(error); |
| 39 | } else { |
| 40 | left_binding = binding; |
| 41 | } |
| 42 | } |
| 43 | } |
| 44 | left_join_bindings.push_back(left_binding); |
| 45 | matching_left_bindings.push_back(move(left_bindings)); |
| 46 | } |
| 47 | result->right = Bind(*ref.right); |
| 48 | for (idx_t i = 0; i < ref.using_columns.size(); i++) { |
| 49 | auto &using_column = ref.using_columns[i]; |
| 50 | auto &left_bindings = matching_left_bindings[i]; |
| 51 | auto left_binding = left_join_bindings[i]; |
| 52 | |
| 53 | auto all_bindings = bind_context.GetMatchingBindings(using_column); |
| 54 | string right_binding; |
| 55 | for (auto &binding : all_bindings) { |
| 56 | if (left_bindings.find(binding) == left_bindings.end()) { |
| 57 | assert(right_binding.empty()); |
| 58 | right_binding = binding; |
| 59 | } |
| 60 | } |
| 61 | if (right_binding.empty()) { |
| 62 | throw BinderException("Column \"%s\" does not exist on right side of join!" , using_column.c_str()); |
| 63 | } |
| 64 | assert(!left_binding.empty()); |
| 65 | auto left_expr = make_unique<ColumnRefExpression>(using_column, left_binding); |
| 66 | auto right_expr = make_unique<ColumnRefExpression>(using_column, right_binding); |
| 67 | bind_context.hidden_columns.insert(right_expr->table_name + "." + right_expr->column_name); |
| 68 | auto comp_expr = |
| 69 | make_unique<ComparisonExpression>(ExpressionType::COMPARE_EQUAL, move(left_expr), move(right_expr)); |
| 70 | if (!ref.condition) { |
| 71 | ref.condition = move(comp_expr); |
| 72 | } else { |
| 73 | ref.condition = make_unique<ConjunctionExpression>(ExpressionType::CONJUNCTION_AND, move(ref.condition), |
| 74 | move(comp_expr)); |
| 75 | } |
| 76 | } |
| 77 | } else { |
| 78 | result->left = Bind(*ref.left); |
| 79 | result->right = Bind(*ref.right); |
| 80 | } |
| 81 | if (ref.condition) { |
| 82 | WhereBinder binder(*this, context); |
| 83 | result->condition = binder.Bind(ref.condition); |
| 84 | } |
| 85 | return move(result); |
| 86 | } |
| 87 | |