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