| 1 | //===----------------------------------------------------------------------===// | 
| 2 | //                         DuckDB | 
| 3 | // | 
| 4 | // duckdb/planner/bind_context.hpp | 
| 5 | // | 
| 6 | // | 
| 7 | //===----------------------------------------------------------------------===// | 
| 8 |  | 
| 9 | #pragma once | 
| 10 |  | 
| 11 | #include "duckdb/catalog/catalog.hpp" | 
| 12 | #include "duckdb/common/case_insensitive_map.hpp" | 
| 13 | #include "duckdb/common/reference_map.hpp" | 
| 14 | #include "duckdb/parser/expression/columnref_expression.hpp" | 
| 15 | #include "duckdb/parser/parsed_expression.hpp" | 
| 16 | #include "duckdb/parser/qualified_name_set.hpp" | 
| 17 | #include "duckdb/planner/expression.hpp" | 
| 18 | #include "duckdb/planner/expression_binder.hpp" | 
| 19 | #include "duckdb/planner/table_binding.hpp" | 
| 20 |  | 
| 21 | namespace duckdb { | 
| 22 | class Binder; | 
| 23 | class LogicalGet; | 
| 24 | class BoundQueryNode; | 
| 25 |  | 
| 26 | class StarExpression; | 
| 27 |  | 
| 28 | class TableCatalogEntry; | 
| 29 | class TableFunctionCatalogEntry; | 
| 30 |  | 
| 31 | struct UsingColumnSet { | 
| 32 | 	string primary_binding; | 
| 33 | 	unordered_set<string> bindings; | 
| 34 | }; | 
| 35 |  | 
| 36 | //! The BindContext object keeps track of all the tables and columns that are | 
| 37 | //! encountered during the binding process. | 
| 38 | class BindContext { | 
| 39 | public: | 
| 40 | 	//! Keep track of recursive CTE references | 
| 41 | 	case_insensitive_map_t<std::shared_ptr<idx_t>> cte_references; | 
| 42 |  | 
| 43 | public: | 
| 44 | 	//! Given a column name, find the matching table it belongs to. Throws an | 
| 45 | 	//! exception if no table has a column of the given name. | 
| 46 | 	string GetMatchingBinding(const string &column_name); | 
| 47 | 	//! Like GetMatchingBinding, but instead of throwing an error if multiple tables have the same binding it will | 
| 48 | 	//! return a list of all the matching ones | 
| 49 | 	unordered_set<string> GetMatchingBindings(const string &column_name); | 
| 50 | 	//! Like GetMatchingBindings, but returns the top 3 most similar bindings (in levenshtein distance) instead of the | 
| 51 | 	//! matching ones | 
| 52 | 	vector<string> GetSimilarBindings(const string &column_name); | 
| 53 |  | 
| 54 | 	optional_ptr<Binding> GetCTEBinding(const string &ctename); | 
| 55 | 	//! Binds a column expression to the base table. Returns the bound expression | 
| 56 | 	//! or throws an exception if the column could not be bound. | 
| 57 | 	BindResult BindColumn(ColumnRefExpression &colref, idx_t depth); | 
| 58 | 	string BindColumn(PositionalReferenceExpression &ref, string &table_name, string &column_name); | 
| 59 | 	unique_ptr<ColumnRefExpression> PositionToColumn(PositionalReferenceExpression &ref); | 
| 60 |  | 
| 61 | 	unique_ptr<ParsedExpression> ExpandGeneratedColumn(const string &table_name, const string &column_name); | 
| 62 |  | 
| 63 | 	unique_ptr<ParsedExpression> CreateColumnReference(const string &table_name, const string &column_name); | 
| 64 | 	unique_ptr<ParsedExpression> CreateColumnReference(const string &schema_name, const string &table_name, | 
| 65 | 	                                                   const string &column_name); | 
| 66 | 	unique_ptr<ParsedExpression> CreateColumnReference(const string &catalog_name, const string &schema_name, | 
| 67 | 	                                                   const string &table_name, const string &column_name); | 
| 68 |  | 
| 69 | 	//! Generate column expressions for all columns that are present in the | 
| 70 | 	//! referenced tables. This is used to resolve the * expression in a | 
| 71 | 	//! selection list. | 
| 72 | 	void GenerateAllColumnExpressions(StarExpression &expr, vector<unique_ptr<ParsedExpression>> &new_select_list); | 
| 73 | 	//! Check if the given (binding, column_name) is in the exclusion/replacement lists. | 
| 74 | 	//! Returns true if it is in one of these lists, and should therefore be skipped. | 
| 75 | 	bool CheckExclusionList(StarExpression &expr, const string &column_name, | 
| 76 | 	                        vector<unique_ptr<ParsedExpression>> &new_select_list, | 
| 77 | 	                        case_insensitive_set_t &excluded_columns); | 
| 78 |  | 
| 79 | 	const vector<reference<Binding>> &GetBindingsList() { | 
| 80 | 		return bindings_list; | 
| 81 | 	} | 
| 82 |  | 
| 83 | 	void GetTypesAndNames(vector<string> &result_names, vector<LogicalType> &result_types); | 
| 84 |  | 
| 85 | 	//! Adds a base table with the given alias to the BindContext. | 
| 86 | 	void AddBaseTable(idx_t index, const string &alias, const vector<string> &names, const vector<LogicalType> &types, | 
| 87 | 	                  vector<column_t> &bound_column_ids, StandardEntry *entry, bool add_row_id = true); | 
| 88 | 	//! Adds a call to a table function with the given alias to the BindContext. | 
| 89 | 	void AddTableFunction(idx_t index, const string &alias, const vector<string> &names, | 
| 90 | 	                      const vector<LogicalType> &types, vector<column_t> &bound_column_ids, StandardEntry *entry); | 
| 91 | 	//! Adds a table view with a given alias to the BindContext. | 
| 92 | 	void AddView(idx_t index, const string &alias, SubqueryRef &ref, BoundQueryNode &subquery, ViewCatalogEntry *view); | 
| 93 | 	//! Adds a subquery with a given alias to the BindContext. | 
| 94 | 	void AddSubquery(idx_t index, const string &alias, SubqueryRef &ref, BoundQueryNode &subquery); | 
| 95 | 	//! Adds a subquery with a given alias to the BindContext. | 
| 96 | 	void AddSubquery(idx_t index, const string &alias, TableFunctionRef &ref, BoundQueryNode &subquery); | 
| 97 | 	//! Adds a binding to a catalog entry with a given alias to the BindContext. | 
| 98 | 	void AddEntryBinding(idx_t index, const string &alias, const vector<string> &names, | 
| 99 | 	                     const vector<LogicalType> &types, StandardEntry &entry); | 
| 100 | 	//! Adds a base table with the given alias to the BindContext. | 
| 101 | 	void AddGenericBinding(idx_t index, const string &alias, const vector<string> &names, | 
| 102 | 	                       const vector<LogicalType> &types); | 
| 103 |  | 
| 104 | 	//! Adds a base table with the given alias to the CTE BindContext. | 
| 105 | 	//! We need this to correctly bind recursive CTEs with multiple references. | 
| 106 | 	void AddCTEBinding(idx_t index, const string &alias, const vector<string> &names, const vector<LogicalType> &types); | 
| 107 |  | 
| 108 | 	//! Add an implicit join condition (e.g. USING (x)) | 
| 109 | 	void AddUsingBinding(const string &column_name, UsingColumnSet &set); | 
| 110 |  | 
| 111 | 	void AddUsingBindingSet(unique_ptr<UsingColumnSet> set); | 
| 112 |  | 
| 113 | 	//! Returns any using column set for the given column name, or nullptr if there is none. On conflict (multiple using | 
| 114 | 	//! column sets with the same name) throw an exception. | 
| 115 | 	optional_ptr<UsingColumnSet> GetUsingBinding(const string &column_name); | 
| 116 | 	//! Returns any using column set for the given column name, or nullptr if there is none | 
| 117 | 	optional_ptr<UsingColumnSet> GetUsingBinding(const string &column_name, const string &binding_name); | 
| 118 | 	//! Erase a using binding from the set of using bindings | 
| 119 | 	void RemoveUsingBinding(const string &column_name, UsingColumnSet &set); | 
| 120 | 	//! Transfer a using binding from one bind context to this bind context | 
| 121 | 	void TransferUsingBinding(BindContext ¤t_context, optional_ptr<UsingColumnSet> current_set, | 
| 122 | 	                          UsingColumnSet &new_set, const string &binding, const string &using_column); | 
| 123 |  | 
| 124 | 	//! Fetch the actual column name from the given binding, or throws if none exists | 
| 125 | 	//! This can be different from "column_name" because of case insensitivity | 
| 126 | 	//! (e.g. "column_name" might return "COLUMN_NAME") | 
| 127 | 	string GetActualColumnName(const string &binding, const string &column_name); | 
| 128 |  | 
| 129 | 	case_insensitive_map_t<std::shared_ptr<Binding>> GetCTEBindings() { | 
| 130 | 		return cte_bindings; | 
| 131 | 	} | 
| 132 | 	void SetCTEBindings(case_insensitive_map_t<std::shared_ptr<Binding>> bindings) { | 
| 133 | 		cte_bindings = bindings; | 
| 134 | 	} | 
| 135 |  | 
| 136 | 	//! Alias a set of column names for the specified table, using the original names if there are not enough aliases | 
| 137 | 	//! specified. | 
| 138 | 	static vector<string> AliasColumnNames(const string &table_name, const vector<string> &names, | 
| 139 | 	                                       const vector<string> &column_aliases); | 
| 140 |  | 
| 141 | 	//! Add all the bindings from a BindContext to this BindContext. The other BindContext is destroyed in the process. | 
| 142 | 	void AddContext(BindContext other); | 
| 143 | 	//! For semi and anti joins we remove the binding context of the right table after binding the condition. | 
| 144 | 	void RemoveContext(vector<reference<Binding>> &other_bindings_list); | 
| 145 |  | 
| 146 | 	//! Gets a binding of the specified name. Returns a nullptr and sets the out_error if the binding could not be | 
| 147 | 	//! found. | 
| 148 | 	optional_ptr<Binding> GetBinding(const string &name, string &out_error); | 
| 149 |  | 
| 150 | private: | 
| 151 | 	void AddBinding(const string &alias, unique_ptr<Binding> binding); | 
| 152 |  | 
| 153 | private: | 
| 154 | 	//! The set of bindings | 
| 155 | 	case_insensitive_map_t<unique_ptr<Binding>> bindings; | 
| 156 | 	//! The list of bindings in insertion order | 
| 157 | 	vector<reference<Binding>> bindings_list; | 
| 158 | 	//! The set of columns used in USING join conditions | 
| 159 | 	case_insensitive_map_t<reference_set_t<UsingColumnSet>> using_columns; | 
| 160 | 	//! Using column sets | 
| 161 | 	vector<unique_ptr<UsingColumnSet>> using_column_sets; | 
| 162 |  | 
| 163 | 	//! The set of CTE bindings | 
| 164 | 	case_insensitive_map_t<std::shared_ptr<Binding>> cte_bindings; | 
| 165 | }; | 
| 166 | } // namespace duckdb | 
| 167 |  |