1#include "duckdb/planner/expression/bound_function_expression.hpp"
2#include "duckdb/parser/expression/function_expression.hpp"
3#include "duckdb/catalog/catalog_entry/scalar_function_catalog_entry.hpp"
4#include "duckdb/common/types/hash.hpp"
5#include "duckdb/function/function_serialization.hpp"
6
7namespace duckdb {
8
9BoundFunctionExpression::BoundFunctionExpression(LogicalType return_type, ScalarFunction bound_function,
10 vector<unique_ptr<Expression>> arguments,
11 unique_ptr<FunctionData> bind_info, bool is_operator)
12 : Expression(ExpressionType::BOUND_FUNCTION, ExpressionClass::BOUND_FUNCTION, std::move(return_type)),
13 function(std::move(bound_function)), children(std::move(arguments)), bind_info(std::move(bind_info)),
14 is_operator(is_operator) {
15 D_ASSERT(!function.name.empty());
16}
17
18bool BoundFunctionExpression::HasSideEffects() const {
19 return function.side_effects == FunctionSideEffects::HAS_SIDE_EFFECTS ? true : Expression::HasSideEffects();
20}
21
22bool BoundFunctionExpression::IsFoldable() const {
23 // functions with side effects cannot be folded: they have to be executed once for every row
24 return function.side_effects == FunctionSideEffects::HAS_SIDE_EFFECTS ? false : Expression::IsFoldable();
25}
26
27string BoundFunctionExpression::ToString() const {
28 return FunctionExpression::ToString<BoundFunctionExpression, Expression>(entry: *this, schema: string(), function_name: function.name,
29 is_operator);
30}
31bool BoundFunctionExpression::PropagatesNullValues() const {
32 return function.null_handling == FunctionNullHandling::SPECIAL_HANDLING ? false
33 : Expression::PropagatesNullValues();
34}
35
36hash_t BoundFunctionExpression::Hash() const {
37 hash_t result = Expression::Hash();
38 return CombineHash(left: result, right: function.Hash());
39}
40
41bool BoundFunctionExpression::Equals(const BaseExpression &other_p) const {
42 if (!Expression::Equals(other: other_p)) {
43 return false;
44 }
45 auto &other = other_p.Cast<BoundFunctionExpression>();
46 if (other.function != function) {
47 return false;
48 }
49 if (!Expression::ListEquals(left: children, right: other.children)) {
50 return false;
51 }
52 if (!FunctionData::Equals(left: bind_info.get(), right: other.bind_info.get())) {
53 return false;
54 }
55 return true;
56}
57
58unique_ptr<Expression> BoundFunctionExpression::Copy() {
59 vector<unique_ptr<Expression>> new_children;
60 new_children.reserve(n: children.size());
61 for (auto &child : children) {
62 new_children.push_back(x: child->Copy());
63 }
64 unique_ptr<FunctionData> new_bind_info = bind_info ? bind_info->Copy() : nullptr;
65
66 auto copy = make_uniq<BoundFunctionExpression>(args&: return_type, args&: function, args: std::move(new_children),
67 args: std::move(new_bind_info), args&: is_operator);
68 copy->CopyProperties(other&: *this);
69 return std::move(copy);
70}
71
72void BoundFunctionExpression::Verify() const {
73 D_ASSERT(!function.name.empty());
74}
75
76void BoundFunctionExpression::Serialize(FieldWriter &writer) const {
77 D_ASSERT(!function.name.empty());
78 D_ASSERT(return_type == function.return_type);
79 writer.WriteField(element: is_operator);
80 FunctionSerializer::Serialize<ScalarFunction>(writer, function, return_type, children, bind_info: bind_info.get());
81}
82
83unique_ptr<Expression> BoundFunctionExpression::Deserialize(ExpressionDeserializationState &state,
84 FieldReader &reader) {
85 auto is_operator = reader.ReadRequired<bool>();
86 vector<unique_ptr<Expression>> children;
87 unique_ptr<FunctionData> bind_info;
88 auto function = FunctionSerializer::Deserialize<ScalarFunction, ScalarFunctionCatalogEntry>(
89 reader, state, type: CatalogType::SCALAR_FUNCTION_ENTRY, children, bind_info);
90
91 auto return_type = function.return_type;
92 return make_uniq<BoundFunctionExpression>(args: std::move(return_type), args: std::move(function), args: std::move(children),
93 args: std::move(bind_info), args&: is_operator);
94}
95} // namespace duckdb
96