1#include "duckdb/planner/binder.hpp"
2
3#include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp"
4#include "duckdb/catalog/catalog_entry/view_catalog_entry.hpp"
5#include "duckdb/main/config.hpp"
6#include "duckdb/parser/parsed_expression_iterator.hpp"
7#include "duckdb/parser/query_node/select_node.hpp"
8#include "duckdb/parser/statement/list.hpp"
9#include "duckdb/parser/tableref/list.hpp"
10#include "duckdb/parser/tableref/table_function_ref.hpp"
11#include "duckdb/planner/bound_query_node.hpp"
12#include "duckdb/planner/tableref/list.hpp"
13#include "duckdb/planner/query_node/list.hpp"
14#include "duckdb/planner/expression.hpp"
15#include "duckdb/planner/expression_binder/returning_binder.hpp"
16#include "duckdb/planner/operator/logical_projection.hpp"
17#include "duckdb/planner/operator/logical_sample.hpp"
18#include "duckdb/parser/query_node/list.hpp"
19
20#include <algorithm>
21
22namespace duckdb {
23
24shared_ptr<Binder> Binder::CreateBinder(ClientContext &context, optional_ptr<Binder> parent, bool inherit_ctes) {
25 return make_shared<Binder>(args: true, args&: context, args: parent ? parent->shared_from_this() : nullptr, args&: inherit_ctes);
26}
27
28Binder::Binder(bool, ClientContext &context, shared_ptr<Binder> parent_p, bool inherit_ctes_p)
29 : context(context), parent(std::move(parent_p)), bound_tables(0), inherit_ctes(inherit_ctes_p) {
30 if (parent) {
31
32 // We have to inherit macro and lambda parameter bindings and from the parent binder, if there is a parent.
33 macro_binding = parent->macro_binding;
34 lambda_bindings = parent->lambda_bindings;
35
36 if (inherit_ctes) {
37 // We have to inherit CTE bindings from the parent bind_context, if there is a parent.
38 bind_context.SetCTEBindings(parent->bind_context.GetCTEBindings());
39 bind_context.cte_references = parent->bind_context.cte_references;
40 parameters = parent->parameters;
41 }
42 }
43}
44
45BoundStatement Binder::Bind(SQLStatement &statement) {
46 root_statement = &statement;
47 switch (statement.type) {
48 case StatementType::SELECT_STATEMENT:
49 return Bind(stmt&: statement.Cast<SelectStatement>());
50 case StatementType::INSERT_STATEMENT:
51 return Bind(stmt&: statement.Cast<InsertStatement>());
52 case StatementType::COPY_STATEMENT:
53 return Bind(stmt&: statement.Cast<CopyStatement>());
54 case StatementType::DELETE_STATEMENT:
55 return Bind(stmt&: statement.Cast<DeleteStatement>());
56 case StatementType::UPDATE_STATEMENT:
57 return Bind(stmt&: statement.Cast<UpdateStatement>());
58 case StatementType::RELATION_STATEMENT:
59 return Bind(stmt&: statement.Cast<RelationStatement>());
60 case StatementType::CREATE_STATEMENT:
61 return Bind(stmt&: statement.Cast<CreateStatement>());
62 case StatementType::DROP_STATEMENT:
63 return Bind(stmt&: statement.Cast<DropStatement>());
64 case StatementType::ALTER_STATEMENT:
65 return Bind(stmt&: statement.Cast<AlterStatement>());
66 case StatementType::TRANSACTION_STATEMENT:
67 return Bind(stmt&: statement.Cast<TransactionStatement>());
68 case StatementType::PRAGMA_STATEMENT:
69 return Bind(stmt&: statement.Cast<PragmaStatement>());
70 case StatementType::EXPLAIN_STATEMENT:
71 return Bind(stmt&: statement.Cast<ExplainStatement>());
72 case StatementType::VACUUM_STATEMENT:
73 return Bind(stmt&: statement.Cast<VacuumStatement>());
74 case StatementType::SHOW_STATEMENT:
75 return Bind(stmt&: statement.Cast<ShowStatement>());
76 case StatementType::CALL_STATEMENT:
77 return Bind(stmt&: statement.Cast<CallStatement>());
78 case StatementType::EXPORT_STATEMENT:
79 return Bind(stmt&: statement.Cast<ExportStatement>());
80 case StatementType::SET_STATEMENT:
81 return Bind(stmt&: statement.Cast<SetStatement>());
82 case StatementType::LOAD_STATEMENT:
83 return Bind(stmt&: statement.Cast<LoadStatement>());
84 case StatementType::EXTENSION_STATEMENT:
85 return Bind(stmt&: statement.Cast<ExtensionStatement>());
86 case StatementType::PREPARE_STATEMENT:
87 return Bind(stmt&: statement.Cast<PrepareStatement>());
88 case StatementType::EXECUTE_STATEMENT:
89 return Bind(stmt&: statement.Cast<ExecuteStatement>());
90 case StatementType::LOGICAL_PLAN_STATEMENT:
91 return Bind(stmt&: statement.Cast<LogicalPlanStatement>());
92 case StatementType::ATTACH_STATEMENT:
93 return Bind(stmt&: statement.Cast<AttachStatement>());
94 case StatementType::DETACH_STATEMENT:
95 return Bind(stmt&: statement.Cast<DetachStatement>());
96 default: // LCOV_EXCL_START
97 throw NotImplementedException("Unimplemented statement type \"%s\" for Bind",
98 StatementTypeToString(type: statement.type));
99 } // LCOV_EXCL_STOP
100}
101
102void Binder::AddCTEMap(CommonTableExpressionMap &cte_map) {
103 for (auto &cte_it : cte_map.map) {
104 AddCTE(name: cte_it.first, cte&: *cte_it.second);
105 }
106}
107
108unique_ptr<BoundQueryNode> Binder::BindNode(QueryNode &node) {
109 // first we visit the set of CTEs and add them to the bind context
110 AddCTEMap(cte_map&: node.cte_map);
111 // now we bind the node
112 unique_ptr<BoundQueryNode> result;
113 switch (node.type) {
114 case QueryNodeType::SELECT_NODE:
115 result = BindNode(node&: node.Cast<SelectNode>());
116 break;
117 case QueryNodeType::RECURSIVE_CTE_NODE:
118 result = BindNode(node&: node.Cast<RecursiveCTENode>());
119 break;
120 default:
121 D_ASSERT(node.type == QueryNodeType::SET_OPERATION_NODE);
122 result = BindNode(node&: node.Cast<SetOperationNode>());
123 break;
124 }
125 return result;
126}
127
128BoundStatement Binder::Bind(QueryNode &node) {
129 auto bound_node = BindNode(node);
130
131 BoundStatement result;
132 result.names = bound_node->names;
133 result.types = bound_node->types;
134
135 // and plan it
136 result.plan = CreatePlan(node&: *bound_node);
137 return result;
138}
139
140unique_ptr<LogicalOperator> Binder::CreatePlan(BoundQueryNode &node) {
141 switch (node.type) {
142 case QueryNodeType::SELECT_NODE:
143 return CreatePlan(statement&: node.Cast<BoundSelectNode>());
144 case QueryNodeType::SET_OPERATION_NODE:
145 return CreatePlan(node&: node.Cast<BoundSetOperationNode>());
146 case QueryNodeType::RECURSIVE_CTE_NODE:
147 return CreatePlan(node&: node.Cast<BoundRecursiveCTENode>());
148 default:
149 throw InternalException("Unsupported bound query node type");
150 }
151}
152
153unique_ptr<BoundTableRef> Binder::Bind(TableRef &ref) {
154 unique_ptr<BoundTableRef> result;
155 switch (ref.type) {
156 case TableReferenceType::BASE_TABLE:
157 result = Bind(ref&: ref.Cast<BaseTableRef>());
158 break;
159 case TableReferenceType::JOIN:
160 result = Bind(ref&: ref.Cast<JoinRef>());
161 break;
162 case TableReferenceType::SUBQUERY:
163 result = Bind(ref&: ref.Cast<SubqueryRef>());
164 break;
165 case TableReferenceType::EMPTY:
166 result = Bind(ref&: ref.Cast<EmptyTableRef>());
167 break;
168 case TableReferenceType::TABLE_FUNCTION:
169 result = Bind(ref&: ref.Cast<TableFunctionRef>());
170 break;
171 case TableReferenceType::EXPRESSION_LIST:
172 result = Bind(ref&: ref.Cast<ExpressionListRef>());
173 break;
174 case TableReferenceType::PIVOT:
175 result = Bind(expr&: ref.Cast<PivotRef>());
176 break;
177 case TableReferenceType::CTE:
178 case TableReferenceType::INVALID:
179 default:
180 throw InternalException("Unknown table ref type");
181 }
182 result->sample = std::move(ref.sample);
183 return result;
184}
185
186unique_ptr<LogicalOperator> Binder::CreatePlan(BoundTableRef &ref) {
187 unique_ptr<LogicalOperator> root;
188 switch (ref.type) {
189 case TableReferenceType::BASE_TABLE:
190 root = CreatePlan(ref&: ref.Cast<BoundBaseTableRef>());
191 break;
192 case TableReferenceType::SUBQUERY:
193 root = CreatePlan(ref&: ref.Cast<BoundSubqueryRef>());
194 break;
195 case TableReferenceType::JOIN:
196 root = CreatePlan(ref&: ref.Cast<BoundJoinRef>());
197 break;
198 case TableReferenceType::TABLE_FUNCTION:
199 root = CreatePlan(ref&: ref.Cast<BoundTableFunction>());
200 break;
201 case TableReferenceType::EMPTY:
202 root = CreatePlan(ref&: ref.Cast<BoundEmptyTableRef>());
203 break;
204 case TableReferenceType::EXPRESSION_LIST:
205 root = CreatePlan(ref&: ref.Cast<BoundExpressionListRef>());
206 break;
207 case TableReferenceType::CTE:
208 root = CreatePlan(ref&: ref.Cast<BoundCTERef>());
209 break;
210 case TableReferenceType::PIVOT:
211 root = CreatePlan(ref&: ref.Cast<BoundPivotRef>());
212 break;
213 case TableReferenceType::INVALID:
214 default:
215 throw InternalException("Unsupported bound table ref type");
216 }
217 // plan the sample clause
218 if (ref.sample) {
219 root = make_uniq<LogicalSample>(args: std::move(ref.sample), args: std::move(root));
220 }
221 return root;
222}
223
224void Binder::AddCTE(const string &name, CommonTableExpressionInfo &info) {
225 D_ASSERT(!name.empty());
226 auto entry = CTE_bindings.find(x: name);
227 if (entry != CTE_bindings.end()) {
228 throw InternalException("Duplicate CTE \"%s\" in query!", name);
229 }
230 CTE_bindings.insert(x: make_pair(x: name, y: reference<CommonTableExpressionInfo>(info)));
231}
232
233optional_ptr<CommonTableExpressionInfo> Binder::FindCTE(const string &name, bool skip) {
234 auto entry = CTE_bindings.find(x: name);
235 if (entry != CTE_bindings.end()) {
236 if (!skip || entry->second.get().query->node->type == QueryNodeType::RECURSIVE_CTE_NODE) {
237 return &entry->second.get();
238 }
239 }
240 if (parent && inherit_ctes) {
241 return parent->FindCTE(name, skip: name == alias);
242 }
243 return nullptr;
244}
245
246bool Binder::CTEIsAlreadyBound(CommonTableExpressionInfo &cte) {
247 if (bound_ctes.find(x: cte) != bound_ctes.end()) {
248 return true;
249 }
250 if (parent && inherit_ctes) {
251 return parent->CTEIsAlreadyBound(cte);
252 }
253 return false;
254}
255
256void Binder::AddBoundView(ViewCatalogEntry &view) {
257 // check if the view is already bound
258 auto current = this;
259 while (current) {
260 if (current->bound_views.find(x: view) != current->bound_views.end()) {
261 throw BinderException("infinite recursion detected: attempting to recursively bind view \"%s\"", view.name);
262 }
263 current = current->parent.get();
264 }
265 bound_views.insert(x: view);
266}
267
268idx_t Binder::GenerateTableIndex() {
269 D_ASSERT(parent.get() != this);
270 if (parent) {
271 return parent->GenerateTableIndex();
272 }
273 return bound_tables++;
274}
275
276void Binder::PushExpressionBinder(ExpressionBinder &binder) {
277 GetActiveBinders().push_back(x: binder);
278}
279
280void Binder::PopExpressionBinder() {
281 D_ASSERT(HasActiveBinder());
282 GetActiveBinders().pop_back();
283}
284
285void Binder::SetActiveBinder(ExpressionBinder &binder) {
286 D_ASSERT(HasActiveBinder());
287 GetActiveBinders().back() = binder;
288}
289
290ExpressionBinder &Binder::GetActiveBinder() {
291 return GetActiveBinders().back();
292}
293
294bool Binder::HasActiveBinder() {
295 return !GetActiveBinders().empty();
296}
297
298vector<reference<ExpressionBinder>> &Binder::GetActiveBinders() {
299 if (parent) {
300 return parent->GetActiveBinders();
301 }
302 return active_binders;
303}
304
305void Binder::AddUsingBindingSet(unique_ptr<UsingColumnSet> set) {
306 if (parent) {
307 parent->AddUsingBindingSet(set: std::move(set));
308 return;
309 }
310 bind_context.AddUsingBindingSet(set: std::move(set));
311}
312
313void Binder::MoveCorrelatedExpressions(Binder &other) {
314 MergeCorrelatedColumns(other&: other.correlated_columns);
315 other.correlated_columns.clear();
316}
317
318void Binder::MergeCorrelatedColumns(vector<CorrelatedColumnInfo> &other) {
319 for (idx_t i = 0; i < other.size(); i++) {
320 AddCorrelatedColumn(info: other[i]);
321 }
322}
323
324void Binder::AddCorrelatedColumn(const CorrelatedColumnInfo &info) {
325 // we only add correlated columns to the list if they are not already there
326 if (std::find(first: correlated_columns.begin(), last: correlated_columns.end(), val: info) == correlated_columns.end()) {
327 correlated_columns.push_back(x: info);
328 }
329}
330
331bool Binder::HasMatchingBinding(const string &table_name, const string &column_name, string &error_message) {
332 string empty_schema;
333 return HasMatchingBinding(schema_name: empty_schema, table_name, column_name, error_message);
334}
335
336bool Binder::HasMatchingBinding(const string &schema_name, const string &table_name, const string &column_name,
337 string &error_message) {
338 string empty_catalog;
339 return HasMatchingBinding(catalog_name: empty_catalog, schema_name, table_name, column_name, error_message);
340}
341
342bool Binder::HasMatchingBinding(const string &catalog_name, const string &schema_name, const string &table_name,
343 const string &column_name, string &error_message) {
344 optional_ptr<Binding> binding;
345 D_ASSERT(!lambda_bindings);
346 if (macro_binding && table_name == macro_binding->alias) {
347 binding = optional_ptr<Binding>(macro_binding.get());
348 } else {
349 binding = bind_context.GetBinding(name: table_name, out_error&: error_message);
350 }
351
352 if (!binding) {
353 return false;
354 }
355 if (!catalog_name.empty() || !schema_name.empty()) {
356 auto catalog_entry = binding->GetStandardEntry();
357 if (!catalog_entry) {
358 return false;
359 }
360 if (!catalog_name.empty() && catalog_entry->catalog.GetName() != catalog_name) {
361 return false;
362 }
363 if (!schema_name.empty() && catalog_entry->schema.name != schema_name) {
364 return false;
365 }
366 if (catalog_entry->name != table_name) {
367 return false;
368 }
369 }
370 bool binding_found;
371 binding_found = binding->HasMatchingBinding(column_name);
372 if (!binding_found) {
373 error_message = binding->ColumnNotFoundError(column_name);
374 }
375 return binding_found;
376}
377
378void Binder::SetBindingMode(BindingMode mode) {
379 if (parent) {
380 parent->SetBindingMode(mode);
381 }
382 this->mode = mode;
383}
384
385BindingMode Binder::GetBindingMode() {
386 if (parent) {
387 return parent->GetBindingMode();
388 }
389 return mode;
390}
391
392void Binder::SetCanContainNulls(bool can_contain_nulls_p) {
393 can_contain_nulls = can_contain_nulls_p;
394}
395
396void Binder::AddTableName(string table_name) {
397 if (parent) {
398 parent->AddTableName(table_name: std::move(table_name));
399 return;
400 }
401 table_names.insert(x: std::move(table_name));
402}
403
404const unordered_set<string> &Binder::GetTableNames() {
405 if (parent) {
406 return parent->GetTableNames();
407 }
408 return table_names;
409}
410
411string Binder::FormatError(ParsedExpression &expr_context, const string &message) {
412 return FormatError(query_location: expr_context.query_location, msg: message);
413}
414
415string Binder::FormatError(TableRef &ref_context, const string &message) {
416 return FormatError(query_location: ref_context.query_location, msg: message);
417}
418
419string Binder::FormatErrorRecursive(idx_t query_location, const string &message, vector<ExceptionFormatValue> &values) {
420 QueryErrorContext context(root_statement, query_location);
421 return context.FormatErrorRecursive(msg: message, values);
422}
423
424// FIXME: this is extremely naive
425void VerifyNotExcluded(ParsedExpression &expr) {
426 if (expr.type == ExpressionType::COLUMN_REF) {
427 auto &column_ref = expr.Cast<ColumnRefExpression>();
428 if (!column_ref.IsQualified()) {
429 return;
430 }
431 auto &table_name = column_ref.GetTableName();
432 if (table_name == "excluded") {
433 throw NotImplementedException("'excluded' qualified columns are not supported in the RETURNING clause yet");
434 }
435 return;
436 }
437 ParsedExpressionIterator::EnumerateChildren(
438 expr, callback: [&](const ParsedExpression &child) { VerifyNotExcluded(expr&: (ParsedExpression &)child); });
439}
440
441BoundStatement Binder::BindReturning(vector<unique_ptr<ParsedExpression>> returning_list, TableCatalogEntry &table,
442 const string &alias, idx_t update_table_index,
443 unique_ptr<LogicalOperator> child_operator, BoundStatement result) {
444
445 vector<LogicalType> types;
446 vector<std::string> names;
447
448 auto binder = Binder::CreateBinder(context);
449
450 vector<column_t> bound_columns;
451 idx_t column_count = 0;
452 for (auto &col : table.GetColumns().Logical()) {
453 names.push_back(x: col.Name());
454 types.push_back(x: col.Type());
455 if (!col.Generated()) {
456 bound_columns.push_back(x: column_count);
457 }
458 column_count++;
459 }
460
461 binder->bind_context.AddBaseTable(index: update_table_index, alias: alias.empty() ? table.name : alias, names, types,
462 bound_column_ids&: bound_columns, entry: &table, add_row_id: false);
463 ReturningBinder returning_binder(*binder, context);
464
465 vector<unique_ptr<Expression>> projection_expressions;
466 LogicalType result_type;
467 vector<unique_ptr<ParsedExpression>> new_returning_list;
468 binder->ExpandStarExpressions(select_list&: returning_list, new_select_list&: new_returning_list);
469 for (auto &returning_expr : new_returning_list) {
470 VerifyNotExcluded(expr&: *returning_expr);
471 auto expr = returning_binder.Bind(expr&: returning_expr, result_type: &result_type);
472 result.names.push_back(x: expr->GetName());
473 result.types.push_back(x: result_type);
474 projection_expressions.push_back(x: std::move(expr));
475 }
476
477 auto projection = make_uniq<LogicalProjection>(args: GenerateTableIndex(), args: std::move(projection_expressions));
478 projection->AddChild(child: std::move(child_operator));
479 D_ASSERT(result.types.size() == result.names.size());
480 result.plan = std::move(projection);
481 properties.allow_stream_result = true;
482 properties.return_type = StatementReturnType::QUERY_RESULT;
483 return result;
484}
485
486} // namespace duckdb
487