1#include "duckdb/main/relation/table_function_relation.hpp"
2#include "duckdb/parser/tableref/basetableref.hpp"
3#include "duckdb/parser/query_node/select_node.hpp"
4#include "duckdb/parser/expression/star_expression.hpp"
5#include "duckdb/parser/tableref/table_function_ref.hpp"
6#include "duckdb/parser/expression/constant_expression.hpp"
7#include "duckdb/parser/expression/function_expression.hpp"
8#include "duckdb/parser/expression/subquery_expression.hpp"
9#include "duckdb/main/client_context.hpp"
10#include "duckdb/parser/expression/comparison_expression.hpp"
11#include "duckdb/parser/expression/columnref_expression.hpp"
12
13namespace duckdb {
14
15void TableFunctionRelation::AddNamedParameter(const string &name, Value argument) {
16 named_parameters[name] = std::move(argument);
17}
18
19TableFunctionRelation::TableFunctionRelation(const std::shared_ptr<ClientContext> &context, string name_p,
20 vector<Value> parameters_p, named_parameter_map_t named_parameters,
21 shared_ptr<Relation> input_relation_p, bool auto_init)
22 : Relation(context, RelationType::TABLE_FUNCTION_RELATION), name(std::move(name_p)),
23 parameters(std::move(parameters_p)), named_parameters(std::move(named_parameters)),
24 input_relation(std::move(input_relation_p)), auto_initialize(auto_init) {
25 InitializeColumns();
26}
27
28TableFunctionRelation::TableFunctionRelation(const std::shared_ptr<ClientContext> &context, string name_p,
29 vector<Value> parameters_p, shared_ptr<Relation> input_relation_p,
30 bool auto_init)
31 : Relation(context, RelationType::TABLE_FUNCTION_RELATION), name(std::move(name_p)),
32 parameters(std::move(parameters_p)), input_relation(std::move(input_relation_p)), auto_initialize(auto_init) {
33 InitializeColumns();
34}
35
36void TableFunctionRelation::InitializeColumns() {
37 if (!auto_initialize) {
38 return;
39 }
40 context.GetContext()->TryBindRelation(relation&: *this, result_columns&: this->columns);
41}
42
43unique_ptr<QueryNode> TableFunctionRelation::GetQueryNode() {
44 auto result = make_uniq<SelectNode>();
45 result->select_list.push_back(x: make_uniq<StarExpression>());
46 result->from_table = GetTableRef();
47 return std::move(result);
48}
49
50unique_ptr<TableRef> TableFunctionRelation::GetTableRef() {
51 vector<unique_ptr<ParsedExpression>> children;
52 if (input_relation) { // input relation becomes first parameter if present, always
53 auto subquery = make_uniq<SubqueryExpression>();
54 subquery->subquery = make_uniq<SelectStatement>();
55 subquery->subquery->node = input_relation->GetQueryNode();
56 subquery->subquery_type = SubqueryType::SCALAR;
57 children.push_back(x: std::move(subquery));
58 }
59 for (auto &parameter : parameters) {
60 children.push_back(x: make_uniq<ConstantExpression>(args&: parameter));
61 }
62
63 for (auto &parameter : named_parameters) {
64 // Hackity-hack some comparisons with column refs
65 // This is all but pretty, basically the named parameter is the column, the table is empty because that's what
66 // the function binder likes
67 auto column_ref = make_uniq<ColumnRefExpression>(args: parameter.first);
68 auto constant_value = make_uniq<ConstantExpression>(args&: parameter.second);
69 auto comparison = make_uniq<ComparisonExpression>(args: ExpressionType::COMPARE_EQUAL, args: std::move(column_ref),
70 args: std::move(constant_value));
71 children.push_back(x: std::move(comparison));
72 }
73
74 auto table_function = make_uniq<TableFunctionRef>();
75 auto function = make_uniq<FunctionExpression>(args&: name, args: std::move(children));
76 table_function->function = std::move(function);
77 return std::move(table_function);
78}
79
80string TableFunctionRelation::GetAlias() {
81 return name;
82}
83
84const vector<ColumnDefinition> &TableFunctionRelation::Columns() {
85 return columns;
86}
87
88string TableFunctionRelation::ToString(idx_t depth) {
89 string function_call = name + "(";
90 for (idx_t i = 0; i < parameters.size(); i++) {
91 if (i > 0) {
92 function_call += ", ";
93 }
94 function_call += parameters[i].ToString();
95 }
96 function_call += ")";
97 return RenderWhitespace(depth) + function_call;
98}
99
100} // namespace duckdb
101