1#include "duckdb/catalog/catalog.hpp"
2#include "duckdb/catalog/catalog_entry/aggregate_function_catalog_entry.hpp"
3#include "duckdb/catalog/catalog_entry/scalar_function_catalog_entry.hpp"
4#include "duckdb/catalog/catalog_entry/scalar_macro_catalog_entry.hpp"
5#include "duckdb/execution/expression_executor.hpp"
6#include "duckdb/function/function_binder.hpp"
7#include "duckdb/parser/expression/function_expression.hpp"
8#include "duckdb/parser/expression/lambda_expression.hpp"
9#include "duckdb/planner/binder.hpp"
10#include "duckdb/planner/expression/bound_cast_expression.hpp"
11#include "duckdb/planner/expression/bound_constant_expression.hpp"
12#include "duckdb/planner/expression/bound_function_expression.hpp"
13#include "duckdb/planner/expression/bound_lambda_expression.hpp"
14#include "duckdb/planner/expression/bound_reference_expression.hpp"
15#include "duckdb/planner/expression_binder.hpp"
16
17namespace duckdb {
18
19BindResult ExpressionBinder::BindExpression(FunctionExpression &function, idx_t depth,
20 unique_ptr<ParsedExpression> &expr_ptr) {
21 // lookup the function in the catalog
22 QueryErrorContext error_context(binder.root_statement, function.query_location);
23 auto func = Catalog::GetEntry(context, type: CatalogType::SCALAR_FUNCTION_ENTRY, catalog: function.catalog, schema: function.schema,
24 name: function.function_name, if_not_found: OnEntryNotFound::RETURN_NULL, error_context);
25 if (!func) {
26 // function was not found - check if we this is a table function
27 auto table_func =
28 Catalog::GetEntry(context, type: CatalogType::TABLE_FUNCTION_ENTRY, catalog: function.catalog, schema: function.schema,
29 name: function.function_name, if_not_found: OnEntryNotFound::RETURN_NULL, error_context);
30 if (table_func) {
31 throw BinderException(binder.FormatError(
32 expr_context&: function,
33 message: StringUtil::Format(fmt_str: "Function \"%s\" is a table function but it was used as a scalar function. This "
34 "function has to be called in a FROM clause (similar to a table).",
35 params: function.function_name)));
36 }
37 // not a table function - check if the schema is set
38 if (!function.schema.empty()) {
39 // the schema is set - check if we can turn this the schema into a column ref
40 string error;
41 unique_ptr<ColumnRefExpression> colref;
42 if (function.catalog.empty()) {
43 colref = make_uniq<ColumnRefExpression>(args&: function.schema);
44 } else {
45 colref = make_uniq<ColumnRefExpression>(args&: function.schema, args&: function.catalog);
46 }
47 auto new_colref = QualifyColumnName(colref&: *colref, error_message&: error);
48 bool is_col = error.empty() ? true : false;
49 bool is_col_alias = QualifyColumnAlias(colref: *colref);
50
51 if (is_col || is_col_alias) {
52 // we can! transform this into a function call on the column
53 // i.e. "x.lower()" becomes "lower(x)"
54 function.children.insert(position: function.children.begin(), x: std::move(colref));
55 function.catalog = INVALID_CATALOG;
56 function.schema = INVALID_SCHEMA;
57 }
58 }
59 // rebind the function
60 func = Catalog::GetEntry(context, type: CatalogType::SCALAR_FUNCTION_ENTRY, catalog: function.catalog, schema: function.schema,
61 name: function.function_name, if_not_found: OnEntryNotFound::THROW_EXCEPTION, error_context);
62 }
63
64 if (func->type != CatalogType::AGGREGATE_FUNCTION_ENTRY &&
65 (function.distinct || function.filter || !function.order_bys->orders.empty())) {
66 throw InvalidInputException("Function \"%s\" is a %s. \"DISTINCT\", \"FILTER\", and \"ORDER BY\" are only "
67 "applicable to aggregate functions.",
68 function.function_name, CatalogTypeToString(type: func->type));
69 }
70
71 switch (func->type) {
72 case CatalogType::SCALAR_FUNCTION_ENTRY:
73 // scalar function
74
75 // check for lambda parameters, ignore ->> operator (JSON extension)
76 if (function.function_name != "->>") {
77 for (auto &child : function.children) {
78 if (child->expression_class == ExpressionClass::LAMBDA) {
79 return BindLambdaFunction(expr&: function, function&: func->Cast<ScalarFunctionCatalogEntry>(), depth);
80 }
81 }
82 }
83
84 // other scalar function
85 return BindFunction(expr&: function, function&: func->Cast<ScalarFunctionCatalogEntry>(), depth);
86
87 case CatalogType::MACRO_ENTRY:
88 // macro function
89 return BindMacro(expr&: function, macro&: func->Cast<ScalarMacroCatalogEntry>(), depth, expr_ptr);
90 default:
91 // aggregate function
92 return BindAggregate(expr&: function, function&: func->Cast<AggregateFunctionCatalogEntry>(), depth);
93 }
94}
95
96BindResult ExpressionBinder::BindFunction(FunctionExpression &function, ScalarFunctionCatalogEntry &func, idx_t depth) {
97
98 // bind the children of the function expression
99 string error;
100
101 // bind of each child
102 for (idx_t i = 0; i < function.children.size(); i++) {
103 BindChild(expr&: function.children[i], depth, error);
104 }
105
106 if (!error.empty()) {
107 return BindResult(error);
108 }
109 if (binder.GetBindingMode() == BindingMode::EXTRACT_NAMES) {
110 return BindResult(make_uniq<BoundConstantExpression>(args: Value(LogicalType::SQLNULL)));
111 }
112
113 // all children bound successfully
114 // extract the children and types
115 vector<unique_ptr<Expression>> children;
116 for (idx_t i = 0; i < function.children.size(); i++) {
117 auto &child = BoundExpression::GetExpression(expr&: *function.children[i]);
118 children.push_back(x: std::move(child));
119 }
120
121 FunctionBinder function_binder(context);
122 unique_ptr<Expression> result =
123 function_binder.BindScalarFunction(function&: func, children: std::move(children), error, is_operator: function.is_operator, binder: &binder);
124 if (!result) {
125 throw BinderException(binder.FormatError(expr_context&: function, message: error));
126 }
127 return BindResult(std::move(result));
128}
129
130BindResult ExpressionBinder::BindLambdaFunction(FunctionExpression &function, ScalarFunctionCatalogEntry &func,
131 idx_t depth) {
132
133 // bind the children of the function expression
134 string error;
135
136 if (function.children.size() != 2) {
137 throw BinderException("Invalid function arguments!");
138 }
139 D_ASSERT(function.children[1]->GetExpressionClass() == ExpressionClass::LAMBDA);
140
141 // bind the list parameter
142 BindChild(expr&: function.children[0], depth, error);
143 if (!error.empty()) {
144 return BindResult(error);
145 }
146
147 // get the logical type of the children of the list
148 auto &list_child = BoundExpression::GetExpression(expr&: *function.children[0]);
149 if (list_child->return_type.id() != LogicalTypeId::LIST && list_child->return_type.id() != LogicalTypeId::SQLNULL &&
150 list_child->return_type.id() != LogicalTypeId::UNKNOWN) {
151 throw BinderException(" Invalid LIST argument to " + function.function_name + "!");
152 }
153
154 LogicalType list_child_type = list_child->return_type.id();
155 if (list_child->return_type.id() != LogicalTypeId::SQLNULL &&
156 list_child->return_type.id() != LogicalTypeId::UNKNOWN) {
157 list_child_type = ListType::GetChildType(type: list_child->return_type);
158 }
159
160 // bind the lambda parameter
161 auto &lambda_expr = function.children[1]->Cast<LambdaExpression>();
162 BindResult bind_lambda_result = BindExpression(expr&: lambda_expr, depth, is_lambda: true, list_child_type);
163
164 if (bind_lambda_result.HasError()) {
165 error = bind_lambda_result.error;
166 } else {
167 // successfully bound: replace the node with a BoundExpression
168 auto alias = function.children[1]->alias;
169 bind_lambda_result.expression->alias = alias;
170 if (!alias.empty()) {
171 bind_lambda_result.expression->alias = alias;
172 }
173 function.children[1] = make_uniq<BoundExpression>(args: std::move(bind_lambda_result.expression));
174 }
175
176 if (!error.empty()) {
177 return BindResult(error);
178 }
179 if (binder.GetBindingMode() == BindingMode::EXTRACT_NAMES) {
180 return BindResult(make_uniq<BoundConstantExpression>(args: Value(LogicalType::SQLNULL)));
181 }
182
183 // all children bound successfully
184 // extract the children and types
185 vector<unique_ptr<Expression>> children;
186 for (idx_t i = 0; i < function.children.size(); i++) {
187 auto &child = BoundExpression::GetExpression(expr&: *function.children[i]);
188 children.push_back(x: std::move(child));
189 }
190
191 // capture the (lambda) columns
192 auto &bound_lambda_expr = children.back()->Cast<BoundLambdaExpression>();
193 CaptureLambdaColumns(captures&: bound_lambda_expr.captures, list_child_type, expr&: bound_lambda_expr.lambda_expr);
194
195 FunctionBinder function_binder(context);
196 unique_ptr<Expression> result =
197 function_binder.BindScalarFunction(function&: func, children: std::move(children), error, is_operator: function.is_operator, binder: &binder);
198 if (!result) {
199 throw BinderException(binder.FormatError(expr_context&: function, message: error));
200 }
201
202 auto &bound_function_expr = result->Cast<BoundFunctionExpression>();
203 D_ASSERT(bound_function_expr.children.size() == 2);
204
205 // remove the lambda expression from the children
206 auto lambda = std::move(bound_function_expr.children.back());
207 bound_function_expr.children.pop_back();
208 auto &bound_lambda = lambda->Cast<BoundLambdaExpression>();
209
210 // push back (in reverse order) any nested lambda parameters so that we can later use them in the lambda expression
211 // (rhs)
212 if (lambda_bindings) {
213 for (idx_t i = lambda_bindings->size(); i > 0; i--) {
214
215 idx_t lambda_index = lambda_bindings->size() - i + 1;
216 auto &binding = (*lambda_bindings)[i - 1];
217
218 D_ASSERT(binding.names.size() == 1);
219 D_ASSERT(binding.types.size() == 1);
220
221 auto bound_lambda_param =
222 make_uniq<BoundReferenceExpression>(args&: binding.names[0], args&: binding.types[0], args&: lambda_index);
223 bound_function_expr.children.push_back(x: std::move(bound_lambda_param));
224 }
225 }
226
227 // push back the captures into the children vector and the correct return types into the bound_function arguments
228 for (auto &capture : bound_lambda.captures) {
229 bound_function_expr.children.push_back(x: std::move(capture));
230 }
231
232 return BindResult(std::move(result));
233}
234
235BindResult ExpressionBinder::BindAggregate(FunctionExpression &expr, AggregateFunctionCatalogEntry &function,
236 idx_t depth) {
237 return BindResult(binder.FormatError(expr_context&: expr, message: UnsupportedAggregateMessage()));
238}
239
240BindResult ExpressionBinder::BindUnnest(FunctionExpression &expr, idx_t depth, bool root_expression) {
241 return BindResult(binder.FormatError(expr_context&: expr, message: UnsupportedUnnestMessage()));
242}
243
244string ExpressionBinder::UnsupportedAggregateMessage() {
245 return "Aggregate functions are not supported here";
246}
247
248string ExpressionBinder::UnsupportedUnnestMessage() {
249 return "UNNEST not supported here";
250}
251
252} // namespace duckdb
253