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