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