1//===----------------------------------------------------------------------===//
2// DuckDB
3//
4// duckdb/parser/expression/function_expression.hpp
5//
6//
7//===----------------------------------------------------------------------===//
8
9#pragma once
10
11#include "duckdb/common/vector.hpp"
12#include "duckdb/parser/parsed_expression.hpp"
13#include "duckdb/parser/result_modifier.hpp"
14
15namespace duckdb {
16//! Represents a function call
17class FunctionExpression : public ParsedExpression {
18public:
19 static constexpr const ExpressionClass TYPE = ExpressionClass::FUNCTION;
20
21public:
22 DUCKDB_API FunctionExpression(string catalog_name, string schema_name, const string &function_name,
23 vector<unique_ptr<ParsedExpression>> children,
24 unique_ptr<ParsedExpression> filter = nullptr,
25 unique_ptr<OrderModifier> order_bys = nullptr, bool distinct = false,
26 bool is_operator = false, bool export_state = false);
27 DUCKDB_API FunctionExpression(const string &function_name, vector<unique_ptr<ParsedExpression>> children,
28 unique_ptr<ParsedExpression> filter = nullptr,
29 unique_ptr<OrderModifier> order_bys = nullptr, bool distinct = false,
30 bool is_operator = false, bool export_state = false);
31
32 //! Catalog of the function
33 string catalog;
34 //! Schema of the function
35 string schema;
36 //! Function name
37 string function_name;
38 //! Whether or not the function is an operator, only used for rendering
39 bool is_operator;
40 //! List of arguments to the function
41 vector<unique_ptr<ParsedExpression>> children;
42 //! Whether or not the aggregate function is distinct, only used for aggregates
43 bool distinct;
44 //! Expression representing a filter, only used for aggregates
45 unique_ptr<ParsedExpression> filter;
46 //! Modifier representing an ORDER BY, only used for aggregates
47 unique_ptr<OrderModifier> order_bys;
48 //! whether this function should export its state or not
49 bool export_state;
50
51public:
52 string ToString() const override;
53
54 unique_ptr<ParsedExpression> Copy() const override;
55
56 static bool Equal(const FunctionExpression &a, const FunctionExpression &b);
57 hash_t Hash() const override;
58
59 void Serialize(FieldWriter &writer) const override;
60 static unique_ptr<ParsedExpression> Deserialize(ExpressionType type, FieldReader &source);
61 void FormatSerialize(FormatSerializer &serializer) const override;
62 static unique_ptr<ParsedExpression> FormatDeserialize(ExpressionType type, FormatDeserializer &deserializer);
63
64 void Verify() const override;
65
66public:
67 template <class T, class BASE, class ORDER_MODIFIER = OrderModifier>
68 static string ToString(const T &entry, const string &schema, const string &function_name, bool is_operator = false,
69 bool distinct = false, BASE *filter = nullptr, ORDER_MODIFIER *order_bys = nullptr,
70 bool export_state = false, bool add_alias = false) {
71 if (is_operator) {
72 // built-in operator
73 D_ASSERT(!distinct);
74 if (entry.children.size() == 1) {
75 if (StringUtil::Contains(haystack: function_name, needle: "__postfix")) {
76 return "((" + entry.children[0]->ToString() + ")" +
77 StringUtil::Replace(source: function_name, from: "__postfix", to: "") + ")";
78 } else {
79 return function_name + "(" + entry.children[0]->ToString() + ")";
80 }
81 } else if (entry.children.size() == 2) {
82 return StringUtil::Format("(%s %s %s)", entry.children[0]->ToString(), function_name,
83 entry.children[1]->ToString());
84 }
85 }
86 // standard function call
87 string result = schema.empty() ? function_name : schema + "." + function_name;
88 result += "(";
89 if (distinct) {
90 result += "DISTINCT ";
91 }
92 result += StringUtil::Join(entry.children, entry.children.size(), ", ", [&](const unique_ptr<BASE> &child) {
93 return child->alias.empty() || !add_alias
94 ? child->ToString()
95 : StringUtil::Format("%s := %s", SQLIdentifier(child->alias), child->ToString());
96 });
97 // ordered aggregate
98 if (order_bys && !order_bys->orders.empty()) {
99 if (entry.children.empty()) {
100 result += ") WITHIN GROUP (";
101 }
102 result += " ORDER BY ";
103 for (idx_t i = 0; i < order_bys->orders.size(); i++) {
104 if (i > 0) {
105 result += ", ";
106 }
107 result += order_bys->orders[i].ToString();
108 }
109 }
110 result += ")";
111
112 // filtered aggregate
113 if (filter) {
114 result += " FILTER (WHERE " + filter->ToString() + ")";
115 }
116
117 if (export_state) {
118 result += " EXPORT_STATE";
119 }
120
121 return result;
122 }
123};
124} // namespace duckdb
125