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