1#include "duckdb/planner/expression/bound_parameter_expression.hpp"
2#include "duckdb/common/types/hash.hpp"
3#include "duckdb/common/to_string.hpp"
4#include "duckdb/planner/expression_iterator.hpp"
5#include "duckdb/common/field_writer.hpp"
6
7namespace duckdb {
8
9BoundParameterExpression::BoundParameterExpression(idx_t parameter_nr)
10 : Expression(ExpressionType::VALUE_PARAMETER, ExpressionClass::BOUND_PARAMETER,
11 LogicalType(LogicalTypeId::UNKNOWN)),
12 parameter_nr(parameter_nr) {
13}
14
15void BoundParameterExpression::Invalidate(Expression &expr) {
16 if (expr.type != ExpressionType::VALUE_PARAMETER) {
17 throw InternalException("BoundParameterExpression::Invalidate requires a parameter as input");
18 }
19 auto &bound_parameter = expr.Cast<BoundParameterExpression>();
20 bound_parameter.return_type = LogicalTypeId::SQLNULL;
21 bound_parameter.parameter_data->return_type = LogicalTypeId::INVALID;
22}
23
24void BoundParameterExpression::InvalidateRecursive(Expression &expr) {
25 if (expr.type == ExpressionType::VALUE_PARAMETER) {
26 Invalidate(expr);
27 return;
28 }
29 ExpressionIterator::EnumerateChildren(expression&: expr, callback: [&](Expression &child) { InvalidateRecursive(expr&: child); });
30}
31
32bool BoundParameterExpression::IsScalar() const {
33 return true;
34}
35bool BoundParameterExpression::HasParameter() const {
36 return true;
37}
38bool BoundParameterExpression::IsFoldable() const {
39 return false;
40}
41
42string BoundParameterExpression::ToString() const {
43 return "$" + to_string(val: parameter_nr);
44}
45
46bool BoundParameterExpression::Equals(const BaseExpression &other_p) const {
47 if (!Expression::Equals(other: other_p)) {
48 return false;
49 }
50 auto &other = other_p.Cast<BoundParameterExpression>();
51 return parameter_nr == other.parameter_nr;
52}
53
54hash_t BoundParameterExpression::Hash() const {
55 hash_t result = Expression::Hash();
56 result = CombineHash(left: duckdb::Hash(val: parameter_nr), right: result);
57 return result;
58}
59
60unique_ptr<Expression> BoundParameterExpression::Copy() {
61 auto result = make_uniq<BoundParameterExpression>(args&: parameter_nr);
62 result->parameter_data = parameter_data;
63 result->return_type = return_type;
64 result->CopyProperties(other&: *this);
65 return std::move(result);
66}
67
68void BoundParameterExpression::Serialize(FieldWriter &writer) const {
69 writer.WriteField(element: parameter_nr);
70 writer.WriteSerializable(element: return_type);
71 writer.WriteSerializable(element: *parameter_data);
72}
73
74unique_ptr<Expression> BoundParameterExpression::Deserialize(ExpressionDeserializationState &state,
75 FieldReader &reader) {
76 auto &global_parameter_set = state.gstate.parameter_data;
77 auto parameter_nr = reader.ReadRequired<idx_t>();
78 auto result = make_uniq<BoundParameterExpression>(args&: parameter_nr);
79 result->return_type = reader.ReadRequiredSerializable<LogicalType, LogicalType>();
80 auto parameter_data = reader.ReadRequiredSerializable<BoundParameterData, shared_ptr<BoundParameterData>>();
81 // check if we have already deserialized a parameter with this number
82 auto entry = global_parameter_set.find(x: parameter_nr);
83 if (entry == global_parameter_set.end()) {
84 // we have not - store the entry we deserialized from this parameter expression
85 global_parameter_set[parameter_nr] = parameter_data;
86 } else {
87 // we have! use the previously deserialized entry
88 parameter_data = entry->second;
89 }
90 result->parameter_data = std::move(parameter_data);
91 return std::move(result);
92}
93
94} // namespace duckdb
95