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 | |
22 | namespace duckdb { |
23 | |
24 | shared_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 | |
28 | Binder::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 | |
45 | BoundStatement 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 | |
102 | void 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 | |
108 | unique_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 | |
128 | BoundStatement 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 | |
140 | unique_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 | |
153 | unique_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 | |
186 | unique_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 | |
224 | void 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 | |
233 | optional_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 | |
246 | bool 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 | |
256 | void 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 | |
268 | idx_t Binder::GenerateTableIndex() { |
269 | D_ASSERT(parent.get() != this); |
270 | if (parent) { |
271 | return parent->GenerateTableIndex(); |
272 | } |
273 | return bound_tables++; |
274 | } |
275 | |
276 | void Binder::PushExpressionBinder(ExpressionBinder &binder) { |
277 | GetActiveBinders().push_back(x: binder); |
278 | } |
279 | |
280 | void Binder::PopExpressionBinder() { |
281 | D_ASSERT(HasActiveBinder()); |
282 | GetActiveBinders().pop_back(); |
283 | } |
284 | |
285 | void Binder::SetActiveBinder(ExpressionBinder &binder) { |
286 | D_ASSERT(HasActiveBinder()); |
287 | GetActiveBinders().back() = binder; |
288 | } |
289 | |
290 | ExpressionBinder &Binder::GetActiveBinder() { |
291 | return GetActiveBinders().back(); |
292 | } |
293 | |
294 | bool Binder::HasActiveBinder() { |
295 | return !GetActiveBinders().empty(); |
296 | } |
297 | |
298 | vector<reference<ExpressionBinder>> &Binder::GetActiveBinders() { |
299 | if (parent) { |
300 | return parent->GetActiveBinders(); |
301 | } |
302 | return active_binders; |
303 | } |
304 | |
305 | void 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 | |
313 | void Binder::MoveCorrelatedExpressions(Binder &other) { |
314 | MergeCorrelatedColumns(other&: other.correlated_columns); |
315 | other.correlated_columns.clear(); |
316 | } |
317 | |
318 | void Binder::MergeCorrelatedColumns(vector<CorrelatedColumnInfo> &other) { |
319 | for (idx_t i = 0; i < other.size(); i++) { |
320 | AddCorrelatedColumn(info: other[i]); |
321 | } |
322 | } |
323 | |
324 | void 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 | |
331 | bool 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 | |
336 | bool 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 | |
342 | bool 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 | |
378 | void Binder::SetBindingMode(BindingMode mode) { |
379 | if (parent) { |
380 | parent->SetBindingMode(mode); |
381 | } |
382 | this->mode = mode; |
383 | } |
384 | |
385 | BindingMode Binder::GetBindingMode() { |
386 | if (parent) { |
387 | return parent->GetBindingMode(); |
388 | } |
389 | return mode; |
390 | } |
391 | |
392 | void Binder::SetCanContainNulls(bool can_contain_nulls_p) { |
393 | can_contain_nulls = can_contain_nulls_p; |
394 | } |
395 | |
396 | void 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 | |
404 | const unordered_set<string> &Binder::GetTableNames() { |
405 | if (parent) { |
406 | return parent->GetTableNames(); |
407 | } |
408 | return table_names; |
409 | } |
410 | |
411 | string Binder::FormatError(ParsedExpression &expr_context, const string &message) { |
412 | return FormatError(query_location: expr_context.query_location, msg: message); |
413 | } |
414 | |
415 | string Binder::FormatError(TableRef &ref_context, const string &message) { |
416 | return FormatError(query_location: ref_context.query_location, msg: message); |
417 | } |
418 | |
419 | string 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 |
425 | void 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 | |
441 | BoundStatement 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 | |