1 | #include "duckdb/planner/bind_context.hpp" |
2 | |
3 | #include "duckdb/parser/expression/columnref_expression.hpp" |
4 | #include "duckdb/parser/tableref/subqueryref.hpp" |
5 | #include "duckdb/planner/expression/bound_columnref_expression.hpp" |
6 | #include "duckdb/planner/bound_query_node.hpp" |
7 | |
8 | #include "duckdb/common/string_util.hpp" |
9 | |
10 | #include <algorithm> |
11 | |
12 | using namespace duckdb; |
13 | using namespace std; |
14 | |
15 | string BindContext::GetMatchingBinding(const string &column_name) { |
16 | string result; |
17 | for (auto &kv : bindings) { |
18 | auto binding = kv.second.get(); |
19 | if (binding->HasMatchingBinding(column_name)) { |
20 | // check if the binding is ignored |
21 | if (BindingIsHidden(kv.first, column_name)) { |
22 | continue; |
23 | } |
24 | |
25 | if (!result.empty()) { |
26 | throw BinderException("Ambiguous reference to column name \"%s\" (use: \"%s.%s\" " |
27 | "or \"%s.%s\")" , |
28 | column_name.c_str(), result.c_str(), column_name.c_str(), kv.first.c_str(), |
29 | column_name.c_str()); |
30 | } |
31 | result = kv.first; |
32 | } |
33 | } |
34 | return result; |
35 | } |
36 | |
37 | bool BindContext::BindingIsHidden(const string &binding_name, const string &column_name) { |
38 | string total_binding = binding_name + "." + column_name; |
39 | return hidden_columns.find(total_binding) != hidden_columns.end(); |
40 | } |
41 | |
42 | unordered_set<string> BindContext::GetMatchingBindings(const string &column_name) { |
43 | unordered_set<string> result; |
44 | for (auto &kv : bindings) { |
45 | auto binding = kv.second.get(); |
46 | if (binding->HasMatchingBinding(column_name)) { |
47 | result.insert(kv.first); |
48 | } |
49 | } |
50 | return result; |
51 | } |
52 | |
53 | Binding *BindContext::GetCTEBinding(const string &ctename) { |
54 | auto match = cte_bindings.find(ctename); |
55 | if (match == cte_bindings.end()) { |
56 | return nullptr; |
57 | } |
58 | return match->second.get(); |
59 | } |
60 | |
61 | BindResult BindContext::BindColumn(ColumnRefExpression &colref, idx_t depth) { |
62 | if (colref.table_name.empty()) { |
63 | return BindResult(StringUtil::Format("Could not bind alias \"%s\"!" , colref.column_name.c_str())); |
64 | } |
65 | |
66 | auto match = bindings.find(colref.table_name); |
67 | if (match == bindings.end()) { |
68 | // alias not found in this BindContext |
69 | return BindResult(StringUtil::Format("Referenced table \"%s\" not found!" , colref.table_name.c_str())); |
70 | } |
71 | auto binding = match->second.get(); |
72 | return binding->Bind(colref, depth); |
73 | } |
74 | |
75 | void BindContext::GenerateAllColumnExpressions(vector<unique_ptr<ParsedExpression>> &new_select_list, |
76 | string relation_name) { |
77 | if (bindings_list.size() == 0) { |
78 | throw BinderException("SELECT * expression without FROM clause!" ); |
79 | } |
80 | if (relation_name == "" ) { // SELECT * case |
81 | // we have to bind the tables and subqueries in order of table_index |
82 | for (auto &entry : bindings_list) { |
83 | auto binding = entry.second; |
84 | binding->GenerateAllColumnExpressions(*this, new_select_list); |
85 | } |
86 | } else { // SELECT tbl.* case |
87 | auto match = bindings.find(relation_name); |
88 | if (match == bindings.end()) { |
89 | // alias not found in this BindContext |
90 | throw BinderException("SELECT table.* expression but can't find table" ); |
91 | } |
92 | auto binding = match->second.get(); |
93 | binding->GenerateAllColumnExpressions(*this, new_select_list); |
94 | } |
95 | } |
96 | |
97 | void BindContext::AddBinding(const string &alias, unique_ptr<Binding> binding) { |
98 | if (bindings.find(alias) != bindings.end()) { |
99 | throw BinderException("Duplicate alias \"%s\" in query!" , alias.c_str()); |
100 | } |
101 | bindings_list.push_back(make_pair(alias, binding.get())); |
102 | bindings[alias] = move(binding); |
103 | } |
104 | |
105 | void BindContext::AddBaseTable(idx_t index, const string &alias, TableCatalogEntry &table, LogicalGet &get) { |
106 | AddBinding(alias, make_unique<TableBinding>(alias, table, get, index)); |
107 | } |
108 | |
109 | void BindContext::AddSubquery(idx_t index, const string &alias, SubqueryRef &ref, BoundQueryNode &subquery) { |
110 | vector<string> names; |
111 | if (ref.column_name_alias.size() > subquery.names.size()) { |
112 | throw BinderException("table \"%s\" has %lld columns available but %lld columns specified" , alias.c_str(), |
113 | (int64_t)subquery.names.size(), (int64_t)ref.column_name_alias.size()); |
114 | } |
115 | // use any provided aliases from the subquery |
116 | for (idx_t i = 0; i < ref.column_name_alias.size(); i++) { |
117 | names.push_back(ref.column_name_alias[i]); |
118 | } |
119 | // if not enough aliases were provided, use the default names for remaining columns |
120 | for (idx_t i = ref.column_name_alias.size(); i < subquery.names.size(); i++) { |
121 | names.push_back(subquery.names[i]); |
122 | } |
123 | AddGenericBinding(index, alias, names, subquery.types); |
124 | } |
125 | |
126 | void BindContext::AddGenericBinding(idx_t index, const string &alias, vector<string> names, vector<SQLType> types) { |
127 | AddBinding(alias, make_unique<GenericBinding>(alias, move(types), move(names), index)); |
128 | } |
129 | |
130 | void BindContext::AddCTEBinding(idx_t index, const string &alias, vector<string> names, vector<SQLType> types) { |
131 | auto binding = make_shared<GenericBinding>(alias, move(types), move(names), index); |
132 | |
133 | if (cte_bindings.find(alias) != cte_bindings.end()) { |
134 | throw BinderException("Duplicate alias \"%s\" in query!" , alias.c_str()); |
135 | } |
136 | cte_bindings[alias] = move(binding); |
137 | cte_references[alias] = std::make_shared<idx_t>(0); |
138 | } |
139 | |