1//===----------------------------------------------------------------------===//
2// DuckDB
3//
4// duckdb/planner/binder.hpp
5//
6//
7//===----------------------------------------------------------------------===//
8
9#pragma once
10
11#include "duckdb/common/case_insensitive_map.hpp"
12#include "duckdb/common/enums/join_type.hpp"
13#include "duckdb/common/enums/statement_type.hpp"
14#include "duckdb/common/unordered_map.hpp"
15#include "duckdb/parser/column_definition.hpp"
16#include "duckdb/parser/query_node.hpp"
17#include "duckdb/parser/result_modifier.hpp"
18#include "duckdb/parser/tokens.hpp"
19#include "duckdb/planner/bind_context.hpp"
20#include "duckdb/planner/bound_statement.hpp"
21#include "duckdb/planner/bound_tokens.hpp"
22#include "duckdb/planner/expression/bound_columnref_expression.hpp"
23#include "duckdb/planner/logical_operator.hpp"
24#include "duckdb/common/reference_map.hpp"
25
26namespace duckdb {
27class BoundResultModifier;
28class BoundSelectNode;
29class ClientContext;
30class ExpressionBinder;
31class LimitModifier;
32class OrderBinder;
33class TableCatalogEntry;
34class ViewCatalogEntry;
35class TableMacroCatalogEntry;
36class UpdateSetInfo;
37class LogicalProjection;
38
39class ColumnList;
40class ExternalDependency;
41class TableFunction;
42class TableStorageInfo;
43
44struct CreateInfo;
45struct BoundCreateTableInfo;
46struct BoundCreateFunctionInfo;
47struct CommonTableExpressionInfo;
48struct BoundParameterMap;
49
50enum class BindingMode : uint8_t { STANDARD_BINDING, EXTRACT_NAMES };
51
52struct CorrelatedColumnInfo {
53 ColumnBinding binding;
54 LogicalType type;
55 string name;
56 idx_t depth;
57
58 CorrelatedColumnInfo(ColumnBinding binding, LogicalType type_p, string name_p, idx_t depth)
59 : binding(binding), type(std::move(type_p)), name(std::move(name_p)), depth(depth) {
60 }
61 explicit CorrelatedColumnInfo(BoundColumnRefExpression &expr)
62 : CorrelatedColumnInfo(expr.binding, expr.return_type, expr.GetName(), expr.depth) {
63 }
64
65 bool operator==(const CorrelatedColumnInfo &rhs) const {
66 return binding == rhs.binding;
67 }
68};
69
70//! Bind the parsed query tree to the actual columns present in the catalog.
71/*!
72 The binder is responsible for binding tables and columns to actual physical
73 tables and columns in the catalog. In the process, it also resolves types of
74 all expressions.
75*/
76class Binder : public std::enable_shared_from_this<Binder> {
77 friend class ExpressionBinder;
78 friend class RecursiveSubqueryPlanner;
79
80public:
81 DUCKDB_API static shared_ptr<Binder> CreateBinder(ClientContext &context, optional_ptr<Binder> parent = nullptr,
82 bool inherit_ctes = true);
83
84 //! The client context
85 ClientContext &context;
86 //! A mapping of names to common table expressions
87 case_insensitive_map_t<reference<CommonTableExpressionInfo>> CTE_bindings; // NOLINT
88 //! The CTEs that have already been bound
89 reference_set_t<CommonTableExpressionInfo> bound_ctes;
90 //! The bind context
91 BindContext bind_context;
92 //! The set of correlated columns bound by this binder (FIXME: this should probably be an unordered_set and not a
93 //! vector)
94 vector<CorrelatedColumnInfo> correlated_columns;
95 //! The set of parameter expressions bound by this binder
96 optional_ptr<BoundParameterMap> parameters;
97 //! Statement properties
98 StatementProperties properties;
99 //! The alias for the currently processing subquery, if it exists
100 string alias;
101 //! Macro parameter bindings (if any)
102 optional_ptr<DummyBinding> macro_binding;
103 //! The intermediate lambda bindings to bind nested lambdas (if any)
104 optional_ptr<vector<DummyBinding>> lambda_bindings;
105
106public:
107 DUCKDB_API BoundStatement Bind(SQLStatement &statement);
108 DUCKDB_API BoundStatement Bind(QueryNode &node);
109
110 unique_ptr<BoundCreateTableInfo> BindCreateTableInfo(unique_ptr<CreateInfo> info);
111 unique_ptr<BoundCreateTableInfo> BindCreateTableInfo(unique_ptr<CreateInfo> info, SchemaCatalogEntry &schema);
112
113 vector<unique_ptr<Expression>> BindCreateIndexExpressions(TableCatalogEntry &table, CreateIndexInfo &info);
114
115 void BindCreateViewInfo(CreateViewInfo &base);
116 SchemaCatalogEntry &BindSchema(CreateInfo &info);
117 SchemaCatalogEntry &BindCreateFunctionInfo(CreateInfo &info);
118
119 //! Check usage, and cast named parameters to their types
120 static void BindNamedParameters(named_parameter_type_map_t &types, named_parameter_map_t &values,
121 QueryErrorContext &error_context, string &func_name);
122
123 unique_ptr<BoundTableRef> Bind(TableRef &ref);
124 unique_ptr<LogicalOperator> CreatePlan(BoundTableRef &ref);
125
126 //! Generates an unused index for a table
127 idx_t GenerateTableIndex();
128
129 //! Add a common table expression to the binder
130 void AddCTE(const string &name, CommonTableExpressionInfo &cte);
131 //! Find a common table expression by name; returns nullptr if none exists
132 optional_ptr<CommonTableExpressionInfo> FindCTE(const string &name, bool skip = false);
133
134 bool CTEIsAlreadyBound(CommonTableExpressionInfo &cte);
135
136 //! Add the view to the set of currently bound views - used for detecting recursive view definitions
137 void AddBoundView(ViewCatalogEntry &view);
138
139 void PushExpressionBinder(ExpressionBinder &binder);
140 void PopExpressionBinder();
141 void SetActiveBinder(ExpressionBinder &binder);
142 ExpressionBinder &GetActiveBinder();
143 bool HasActiveBinder();
144
145 vector<reference<ExpressionBinder>> &GetActiveBinders();
146
147 void MergeCorrelatedColumns(vector<CorrelatedColumnInfo> &other);
148 //! Add a correlated column to this binder (if it does not exist)
149 void AddCorrelatedColumn(const CorrelatedColumnInfo &info);
150
151 string FormatError(ParsedExpression &expr_context, const string &message);
152 string FormatError(TableRef &ref_context, const string &message);
153
154 string FormatErrorRecursive(idx_t query_location, const string &message, vector<ExceptionFormatValue> &values);
155 template <class T, typename... ARGS>
156 string FormatErrorRecursive(idx_t query_location, const string &msg, vector<ExceptionFormatValue> &values, T param,
157 ARGS... params) {
158 values.push_back(ExceptionFormatValue::CreateFormatValue<T>(param));
159 return FormatErrorRecursive(query_location, msg, values, params...);
160 }
161
162 template <typename... ARGS>
163 string FormatError(idx_t query_location, const string &msg, ARGS... params) {
164 vector<ExceptionFormatValue> values;
165 return FormatErrorRecursive(query_location, msg, values, params...);
166 }
167
168 unique_ptr<LogicalOperator> BindUpdateSet(LogicalOperator &op, unique_ptr<LogicalOperator> root,
169 UpdateSetInfo &set_info, TableCatalogEntry &table,
170 vector<PhysicalIndex> &columns);
171 void BindDoUpdateSetExpressions(const string &table_alias, LogicalInsert &insert, UpdateSetInfo &set_info,
172 TableCatalogEntry &table, TableStorageInfo &storage_info);
173 void BindOnConflictClause(LogicalInsert &insert, TableCatalogEntry &table, InsertStatement &stmt);
174
175 static void BindSchemaOrCatalog(ClientContext &context, string &catalog, string &schema);
176 static void BindLogicalType(ClientContext &context, LogicalType &type, optional_ptr<Catalog> catalog = nullptr,
177 const string &schema = INVALID_SCHEMA);
178
179 bool HasMatchingBinding(const string &table_name, const string &column_name, string &error_message);
180 bool HasMatchingBinding(const string &schema_name, const string &table_name, const string &column_name,
181 string &error_message);
182 bool HasMatchingBinding(const string &catalog_name, const string &schema_name, const string &table_name,
183 const string &column_name, string &error_message);
184
185 void SetBindingMode(BindingMode mode);
186 BindingMode GetBindingMode();
187 void AddTableName(string table_name);
188 const unordered_set<string> &GetTableNames();
189 optional_ptr<SQLStatement> GetRootStatement() {
190 return root_statement;
191 }
192
193 void SetCanContainNulls(bool can_contain_nulls);
194
195private:
196 //! The parent binder (if any)
197 shared_ptr<Binder> parent;
198 //! The vector of active binders
199 vector<reference<ExpressionBinder>> active_binders;
200 //! The count of bound_tables
201 idx_t bound_tables;
202 //! Whether or not the binder has any unplanned subqueries that still need to be planned
203 bool has_unplanned_subqueries = false;
204 //! Whether or not subqueries should be planned already
205 bool plan_subquery = true;
206 //! Whether CTEs should reference the parent binder (if it exists)
207 bool inherit_ctes = true;
208 //! Whether or not the binder can contain NULLs as the root of expressions
209 bool can_contain_nulls = false;
210 //! The root statement of the query that is currently being parsed
211 optional_ptr<SQLStatement> root_statement;
212 //! Binding mode
213 BindingMode mode = BindingMode::STANDARD_BINDING;
214 //! Table names extracted for BindingMode::EXTRACT_NAMES
215 unordered_set<string> table_names;
216 //! The set of bound views
217 reference_set_t<ViewCatalogEntry> bound_views;
218
219private:
220 //! Bind the expressions of generated columns to check for errors
221 void BindGeneratedColumns(BoundCreateTableInfo &info);
222 //! Bind the default values of the columns of a table
223 void BindDefaultValues(const ColumnList &columns, vector<unique_ptr<Expression>> &bound_defaults);
224 //! Bind a limit value (LIMIT or OFFSET)
225 unique_ptr<Expression> BindDelimiter(ClientContext &context, OrderBinder &order_binder,
226 unique_ptr<ParsedExpression> delimiter, const LogicalType &type,
227 Value &delimiter_value);
228
229 //! Move correlated expressions from the child binder to this binder
230 void MoveCorrelatedExpressions(Binder &other);
231
232 BoundStatement Bind(SelectStatement &stmt);
233 BoundStatement Bind(InsertStatement &stmt);
234 BoundStatement Bind(CopyStatement &stmt);
235 BoundStatement Bind(DeleteStatement &stmt);
236 BoundStatement Bind(UpdateStatement &stmt);
237 BoundStatement Bind(CreateStatement &stmt);
238 BoundStatement Bind(DropStatement &stmt);
239 BoundStatement Bind(AlterStatement &stmt);
240 BoundStatement Bind(PrepareStatement &stmt);
241 BoundStatement Bind(ExecuteStatement &stmt);
242 BoundStatement Bind(TransactionStatement &stmt);
243 BoundStatement Bind(PragmaStatement &stmt);
244 BoundStatement Bind(ExplainStatement &stmt);
245 BoundStatement Bind(VacuumStatement &stmt);
246 BoundStatement Bind(RelationStatement &stmt);
247 BoundStatement Bind(ShowStatement &stmt);
248 BoundStatement Bind(CallStatement &stmt);
249 BoundStatement Bind(ExportStatement &stmt);
250 BoundStatement Bind(ExtensionStatement &stmt);
251 BoundStatement Bind(SetStatement &stmt);
252 BoundStatement Bind(SetVariableStatement &stmt);
253 BoundStatement Bind(ResetVariableStatement &stmt);
254 BoundStatement Bind(LoadStatement &stmt);
255 BoundStatement Bind(LogicalPlanStatement &stmt);
256 BoundStatement Bind(AttachStatement &stmt);
257 BoundStatement Bind(DetachStatement &stmt);
258
259 BoundStatement BindReturning(vector<unique_ptr<ParsedExpression>> returning_list, TableCatalogEntry &table,
260 const string &alias, idx_t update_table_index,
261 unique_ptr<LogicalOperator> child_operator, BoundStatement result);
262
263 unique_ptr<QueryNode> BindTableMacro(FunctionExpression &function, TableMacroCatalogEntry &macro_func, idx_t depth);
264
265 unique_ptr<BoundQueryNode> BindNode(SelectNode &node);
266 unique_ptr<BoundQueryNode> BindNode(SetOperationNode &node);
267 unique_ptr<BoundQueryNode> BindNode(RecursiveCTENode &node);
268 unique_ptr<BoundQueryNode> BindNode(QueryNode &node);
269
270 unique_ptr<LogicalOperator> VisitQueryNode(BoundQueryNode &node, unique_ptr<LogicalOperator> root);
271 unique_ptr<LogicalOperator> CreatePlan(BoundRecursiveCTENode &node);
272 unique_ptr<LogicalOperator> CreatePlan(BoundSelectNode &statement);
273 unique_ptr<LogicalOperator> CreatePlan(BoundSetOperationNode &node);
274 unique_ptr<LogicalOperator> CreatePlan(BoundQueryNode &node);
275
276 unique_ptr<BoundTableRef> Bind(BaseTableRef &ref);
277 unique_ptr<BoundTableRef> Bind(JoinRef &ref);
278 unique_ptr<BoundTableRef> Bind(SubqueryRef &ref, optional_ptr<CommonTableExpressionInfo> cte = nullptr);
279 unique_ptr<BoundTableRef> Bind(TableFunctionRef &ref);
280 unique_ptr<BoundTableRef> Bind(EmptyTableRef &ref);
281 unique_ptr<BoundTableRef> Bind(ExpressionListRef &ref);
282 unique_ptr<BoundTableRef> Bind(PivotRef &expr);
283
284 unique_ptr<SelectNode> BindPivot(PivotRef &expr, vector<unique_ptr<ParsedExpression>> all_columns);
285 unique_ptr<SelectNode> BindUnpivot(Binder &child_binder, PivotRef &expr,
286 vector<unique_ptr<ParsedExpression>> all_columns,
287 unique_ptr<ParsedExpression> &where_clause);
288 unique_ptr<BoundTableRef> BindBoundPivot(PivotRef &expr);
289
290 bool BindTableFunctionParameters(TableFunctionCatalogEntry &table_function,
291 vector<unique_ptr<ParsedExpression>> &expressions, vector<LogicalType> &arguments,
292 vector<Value> &parameters, named_parameter_map_t &named_parameters,
293 unique_ptr<BoundSubqueryRef> &subquery, string &error);
294 bool BindTableInTableOutFunction(vector<unique_ptr<ParsedExpression>> &expressions,
295 unique_ptr<BoundSubqueryRef> &subquery, string &error);
296 unique_ptr<LogicalOperator> BindTableFunction(TableFunction &function, vector<Value> parameters);
297 unique_ptr<LogicalOperator>
298 BindTableFunctionInternal(TableFunction &table_function, const string &function_name, vector<Value> parameters,
299 named_parameter_map_t named_parameters, vector<LogicalType> input_table_types,
300 vector<string> input_table_names, const vector<string> &column_name_alias,
301 unique_ptr<ExternalDependency> external_dependency);
302
303 unique_ptr<LogicalOperator> CreatePlan(BoundBaseTableRef &ref);
304 unique_ptr<LogicalOperator> CreatePlan(BoundJoinRef &ref);
305 unique_ptr<LogicalOperator> CreatePlan(BoundSubqueryRef &ref);
306 unique_ptr<LogicalOperator> CreatePlan(BoundTableFunction &ref);
307 unique_ptr<LogicalOperator> CreatePlan(BoundEmptyTableRef &ref);
308 unique_ptr<LogicalOperator> CreatePlan(BoundExpressionListRef &ref);
309 unique_ptr<LogicalOperator> CreatePlan(BoundCTERef &ref);
310 unique_ptr<LogicalOperator> CreatePlan(BoundPivotRef &ref);
311
312 BoundStatement BindCopyTo(CopyStatement &stmt);
313 BoundStatement BindCopyFrom(CopyStatement &stmt);
314
315 void BindModifiers(OrderBinder &order_binder, QueryNode &statement, BoundQueryNode &result);
316 void BindModifierTypes(BoundQueryNode &result, const vector<LogicalType> &sql_types, idx_t projection_index);
317
318 BoundStatement BindSummarize(ShowStatement &stmt);
319 unique_ptr<BoundResultModifier> BindLimit(OrderBinder &order_binder, LimitModifier &limit_mod);
320 unique_ptr<BoundResultModifier> BindLimitPercent(OrderBinder &order_binder, LimitPercentModifier &limit_mod);
321 unique_ptr<Expression> BindOrderExpression(OrderBinder &order_binder, unique_ptr<ParsedExpression> expr);
322
323 unique_ptr<LogicalOperator> PlanFilter(unique_ptr<Expression> condition, unique_ptr<LogicalOperator> root);
324
325 void PlanSubqueries(unique_ptr<Expression> &expr, unique_ptr<LogicalOperator> &root);
326 unique_ptr<Expression> PlanSubquery(BoundSubqueryExpression &expr, unique_ptr<LogicalOperator> &root);
327 unique_ptr<LogicalOperator> PlanLateralJoin(unique_ptr<LogicalOperator> left, unique_ptr<LogicalOperator> right,
328 vector<CorrelatedColumnInfo> &correlated_columns,
329 JoinType join_type = JoinType::INNER,
330 unique_ptr<Expression> condition = nullptr);
331
332 unique_ptr<LogicalOperator> CastLogicalOperatorToTypes(vector<LogicalType> &source_types,
333 vector<LogicalType> &target_types,
334 unique_ptr<LogicalOperator> op);
335
336 string FindBinding(const string &using_column, const string &join_side);
337 bool TryFindBinding(const string &using_column, const string &join_side, string &result);
338
339 void AddUsingBindingSet(unique_ptr<UsingColumnSet> set);
340 string RetrieveUsingBinding(Binder &current_binder, optional_ptr<UsingColumnSet> current_set,
341 const string &column_name, const string &join_side);
342
343 void AddCTEMap(CommonTableExpressionMap &cte_map);
344
345 void ExpandStarExpressions(vector<unique_ptr<ParsedExpression>> &select_list,
346 vector<unique_ptr<ParsedExpression>> &new_select_list);
347 void ExpandStarExpression(unique_ptr<ParsedExpression> expr, vector<unique_ptr<ParsedExpression>> &new_select_list);
348 bool FindStarExpression(unique_ptr<ParsedExpression> &expr, StarExpression **star, bool is_root, bool in_columns);
349 void ReplaceStarExpression(unique_ptr<ParsedExpression> &expr, unique_ptr<ParsedExpression> &replacement);
350 void BindWhereStarExpression(unique_ptr<ParsedExpression> &expr);
351
352 //! If only a schema name is provided (e.g. "a.b") then figure out if "a" is a schema or a catalog name
353 void BindSchemaOrCatalog(string &catalog_name, string &schema_name);
354 SchemaCatalogEntry &BindCreateSchema(CreateInfo &info);
355
356 unique_ptr<BoundQueryNode> BindSelectNode(SelectNode &statement, unique_ptr<BoundTableRef> from_table);
357
358public:
359 // This should really be a private constructor, but make_shared does not allow it...
360 // If you are thinking about calling this, you should probably call Binder::CreateBinder
361 Binder(bool i_know_what_i_am_doing, ClientContext &context, shared_ptr<Binder> parent, bool inherit_ctes);
362};
363
364} // namespace duckdb
365