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