1#include "duckdb/catalog/catalog.hpp"
2#include "duckdb/parser/expression/function_expression.hpp"
3#include "duckdb/parser/tableref/table_function_ref.hpp"
4#include "duckdb/planner/binder.hpp"
5#include "duckdb/planner/expression_binder/constant_binder.hpp"
6#include "duckdb/planner/tableref/bound_table_function.hpp"
7#include "duckdb/execution/expression_executor.hpp"
8
9using namespace duckdb;
10using namespace std;
11
12unique_ptr<BoundTableRef> Binder::Bind(TableFunctionRef &ref) {
13 auto bind_index = GenerateTableIndex();
14
15 assert(ref.function->type == ExpressionType::FUNCTION);
16 auto fexpr = (FunctionExpression *)ref.function.get();
17 // parse the parameters of the function
18 auto function =
19 Catalog::GetCatalog(context).GetEntry<TableFunctionCatalogEntry>(context, fexpr->schema, fexpr->function_name);
20
21 // check if the argument lengths match
22 if (fexpr->children.size() != function->function.arguments.size()) {
23 throw CatalogException("Function with name %s exists, but argument length does not match! "
24 "Expected %d arguments but got %d.",
25 fexpr->function_name.c_str(), (int)function->function.arguments.size(),
26 (int)fexpr->children.size());
27 }
28 auto result = make_unique<BoundTableFunction>(function, bind_index);
29 // evalate the input parameters to the function
30 for (auto &child : fexpr->children) {
31 ConstantBinder binder(*this, context, "TABLE FUNCTION parameter");
32 auto expr = binder.Bind(child);
33 auto constant = ExpressionExecutor::EvaluateScalar(*expr);
34 result->parameters.push_back(constant);
35 }
36 // perform the binding
37 result->bind_data = function->function.bind(context, result->parameters, result->return_types, result->names);
38 assert(result->return_types.size() == result->names.size());
39 assert(result->return_types.size() > 0);
40 // now add the table function to the bind context so its columns can be bound
41 bind_context.AddGenericBinding(bind_index, ref.alias.empty() ? fexpr->function_name : ref.alias, result->names,
42 result->return_types);
43 return move(result);
44}
45