1#include "duckdb/planner/expression.hpp"
2
3#include "duckdb/common/exception.hpp"
4#include "duckdb/common/field_writer.hpp"
5#include "duckdb/common/types/hash.hpp"
6#include "duckdb/planner/expression_iterator.hpp"
7#include "duckdb/storage/statistics/base_statistics.hpp"
8#include "duckdb/planner/expression/list.hpp"
9#include "duckdb/parser/expression_util.hpp"
10
11namespace duckdb {
12
13Expression::Expression(ExpressionType type, ExpressionClass expression_class, LogicalType return_type)
14 : BaseExpression(type, expression_class), return_type(std::move(return_type)) {
15}
16
17Expression::~Expression() {
18}
19
20bool Expression::IsAggregate() const {
21 bool is_aggregate = false;
22 ExpressionIterator::EnumerateChildren(expr: *this, callback: [&](const Expression &child) { is_aggregate |= child.IsAggregate(); });
23 return is_aggregate;
24}
25
26bool Expression::IsWindow() const {
27 bool is_window = false;
28 ExpressionIterator::EnumerateChildren(expr: *this, callback: [&](const Expression &child) { is_window |= child.IsWindow(); });
29 return is_window;
30}
31
32bool Expression::IsScalar() const {
33 bool is_scalar = true;
34 ExpressionIterator::EnumerateChildren(expr: *this, callback: [&](const Expression &child) {
35 if (!child.IsScalar()) {
36 is_scalar = false;
37 }
38 });
39 return is_scalar;
40}
41
42bool Expression::HasSideEffects() const {
43 bool has_side_effects = false;
44 ExpressionIterator::EnumerateChildren(expr: *this, callback: [&](const Expression &child) {
45 if (child.HasSideEffects()) {
46 has_side_effects = true;
47 }
48 });
49 return has_side_effects;
50}
51
52bool Expression::PropagatesNullValues() const {
53 if (type == ExpressionType::OPERATOR_IS_NULL || type == ExpressionType::OPERATOR_IS_NOT_NULL ||
54 type == ExpressionType::COMPARE_NOT_DISTINCT_FROM || type == ExpressionType::COMPARE_DISTINCT_FROM ||
55 type == ExpressionType::CONJUNCTION_OR || type == ExpressionType::CONJUNCTION_AND ||
56 type == ExpressionType::OPERATOR_COALESCE) {
57 return false;
58 }
59 bool propagate_null_values = true;
60 ExpressionIterator::EnumerateChildren(expr: *this, callback: [&](const Expression &child) {
61 if (!child.PropagatesNullValues()) {
62 propagate_null_values = false;
63 }
64 });
65 return propagate_null_values;
66}
67
68bool Expression::IsFoldable() const {
69 bool is_foldable = true;
70 ExpressionIterator::EnumerateChildren(expr: *this, callback: [&](const Expression &child) {
71 if (!child.IsFoldable()) {
72 is_foldable = false;
73 }
74 });
75 return is_foldable;
76}
77
78bool Expression::HasParameter() const {
79 bool has_parameter = false;
80 ExpressionIterator::EnumerateChildren(expr: *this,
81 callback: [&](const Expression &child) { has_parameter |= child.HasParameter(); });
82 return has_parameter;
83}
84
85bool Expression::HasSubquery() const {
86 bool has_subquery = false;
87 ExpressionIterator::EnumerateChildren(expr: *this, callback: [&](const Expression &child) { has_subquery |= child.HasSubquery(); });
88 return has_subquery;
89}
90
91hash_t Expression::Hash() const {
92 hash_t hash = duckdb::Hash<uint32_t>(value: (uint32_t)type);
93 hash = CombineHash(left: hash, right: return_type.Hash());
94 ExpressionIterator::EnumerateChildren(expr: *this,
95 callback: [&](const Expression &child) { hash = CombineHash(left: child.Hash(), right: hash); });
96 return hash;
97}
98
99void Expression::Serialize(Serializer &serializer) const {
100 FieldWriter writer(serializer);
101 writer.WriteField<ExpressionClass>(element: expression_class);
102 writer.WriteField<ExpressionType>(element: type);
103 writer.WriteString(val: alias);
104 Serialize(writer);
105 writer.Finalize();
106}
107
108unique_ptr<Expression> Expression::Deserialize(Deserializer &source, PlanDeserializationState &gstate) {
109 FieldReader reader(source);
110 auto expression_class = reader.ReadRequired<ExpressionClass>();
111 auto type = reader.ReadRequired<ExpressionType>();
112 auto alias = reader.ReadRequired<string>();
113
114 ExpressionDeserializationState state(gstate, type);
115
116 unique_ptr<Expression> result;
117 switch (expression_class) {
118 case ExpressionClass::BOUND_REF:
119 result = BoundReferenceExpression::Deserialize(state, reader);
120 break;
121 case ExpressionClass::BOUND_COLUMN_REF:
122 result = BoundColumnRefExpression::Deserialize(state, reader);
123 break;
124 case ExpressionClass::BOUND_AGGREGATE:
125 result = BoundAggregateExpression::Deserialize(state, reader);
126 break;
127 case ExpressionClass::BOUND_BETWEEN:
128 result = BoundBetweenExpression::Deserialize(state, reader);
129 break;
130 case ExpressionClass::BOUND_CONSTANT:
131 result = BoundConstantExpression::Deserialize(state, reader);
132 break;
133 case ExpressionClass::BOUND_DEFAULT:
134 result = BoundDefaultExpression::Deserialize(state, reader);
135 break;
136 case ExpressionClass::BOUND_FUNCTION:
137 result = BoundFunctionExpression::Deserialize(state, reader);
138 break;
139 case ExpressionClass::BOUND_CAST:
140 result = BoundCastExpression::Deserialize(state, reader);
141 break;
142 case ExpressionClass::BOUND_CASE:
143 result = BoundCaseExpression::Deserialize(state, reader);
144 break;
145 case ExpressionClass::BOUND_CONJUNCTION:
146 result = BoundConjunctionExpression::Deserialize(state, reader);
147 break;
148 case ExpressionClass::BOUND_COMPARISON:
149 result = BoundComparisonExpression::Deserialize(state, reader);
150 break;
151 case ExpressionClass::BOUND_OPERATOR:
152 result = BoundOperatorExpression::Deserialize(state, reader);
153 break;
154 case ExpressionClass::BOUND_WINDOW:
155 result = BoundWindowExpression::Deserialize(state, reader);
156 break;
157 case ExpressionClass::BOUND_UNNEST:
158 result = BoundUnnestExpression::Deserialize(state, reader);
159 break;
160 case ExpressionClass::BOUND_PARAMETER:
161 result = BoundParameterExpression::Deserialize(state, reader);
162 break;
163 default:
164 throw SerializationException("Unsupported type for expression deserialization %s",
165 ExpressionTypeToString(type));
166 }
167 result->alias = alias;
168 reader.Finalize();
169 return result;
170}
171
172bool Expression::Equals(const unique_ptr<Expression> &left, const unique_ptr<Expression> &right) {
173 if (left.get() == right.get()) {
174 return true;
175 }
176 if (!left || !right) {
177 return false;
178 }
179 return left->Equals(other: *right);
180}
181
182bool Expression::ListEquals(const vector<unique_ptr<Expression>> &left, const vector<unique_ptr<Expression>> &right) {
183 return ExpressionUtil::ListEquals(a: left, b: right);
184}
185
186} // namespace duckdb
187