1 | #include "duckdb/parser/expression/window_expression.hpp" |
2 | |
3 | #include "duckdb/common/limits.hpp" |
4 | #include "duckdb/common/field_writer.hpp" |
5 | #include "duckdb/common/string_util.hpp" |
6 | |
7 | #include "duckdb/common/enum_util.hpp" |
8 | #include "duckdb/common/serializer/format_serializer.hpp" |
9 | #include "duckdb/common/serializer/format_deserializer.hpp" |
10 | |
11 | namespace duckdb { |
12 | |
13 | WindowExpression::WindowExpression(ExpressionType type, string catalog_name, string schema, const string &function_name) |
14 | : ParsedExpression(type, ExpressionClass::WINDOW), catalog(std::move(catalog_name)), schema(std::move(schema)), |
15 | function_name(StringUtil::Lower(str: function_name)), ignore_nulls(false) { |
16 | switch (type) { |
17 | case ExpressionType::WINDOW_AGGREGATE: |
18 | case ExpressionType::WINDOW_ROW_NUMBER: |
19 | case ExpressionType::WINDOW_FIRST_VALUE: |
20 | case ExpressionType::WINDOW_LAST_VALUE: |
21 | case ExpressionType::WINDOW_NTH_VALUE: |
22 | case ExpressionType::WINDOW_RANK: |
23 | case ExpressionType::WINDOW_RANK_DENSE: |
24 | case ExpressionType::WINDOW_PERCENT_RANK: |
25 | case ExpressionType::WINDOW_CUME_DIST: |
26 | case ExpressionType::WINDOW_LEAD: |
27 | case ExpressionType::WINDOW_LAG: |
28 | case ExpressionType::WINDOW_NTILE: |
29 | break; |
30 | default: |
31 | throw NotImplementedException("Window aggregate type %s not supported" , ExpressionTypeToString(type).c_str()); |
32 | } |
33 | } |
34 | |
35 | ExpressionType WindowExpression::WindowToExpressionType(string &fun_name) { |
36 | if (fun_name == "rank" ) { |
37 | return ExpressionType::WINDOW_RANK; |
38 | } else if (fun_name == "rank_dense" || fun_name == "dense_rank" ) { |
39 | return ExpressionType::WINDOW_RANK_DENSE; |
40 | } else if (fun_name == "percent_rank" ) { |
41 | return ExpressionType::WINDOW_PERCENT_RANK; |
42 | } else if (fun_name == "row_number" ) { |
43 | return ExpressionType::WINDOW_ROW_NUMBER; |
44 | } else if (fun_name == "first_value" || fun_name == "first" ) { |
45 | return ExpressionType::WINDOW_FIRST_VALUE; |
46 | } else if (fun_name == "last_value" || fun_name == "last" ) { |
47 | return ExpressionType::WINDOW_LAST_VALUE; |
48 | } else if (fun_name == "nth_value" ) { |
49 | return ExpressionType::WINDOW_NTH_VALUE; |
50 | } else if (fun_name == "cume_dist" ) { |
51 | return ExpressionType::WINDOW_CUME_DIST; |
52 | } else if (fun_name == "lead" ) { |
53 | return ExpressionType::WINDOW_LEAD; |
54 | } else if (fun_name == "lag" ) { |
55 | return ExpressionType::WINDOW_LAG; |
56 | } else if (fun_name == "ntile" ) { |
57 | return ExpressionType::WINDOW_NTILE; |
58 | } |
59 | return ExpressionType::WINDOW_AGGREGATE; |
60 | } |
61 | |
62 | string WindowExpression::ToString() const { |
63 | return ToString<WindowExpression, ParsedExpression, OrderByNode>(entry: *this, schema, function_name); |
64 | } |
65 | |
66 | bool WindowExpression::Equal(const WindowExpression &a, const WindowExpression &b) { |
67 | // check if the child expressions are equivalent |
68 | if (a.ignore_nulls != b.ignore_nulls) { |
69 | return false; |
70 | } |
71 | if (!ParsedExpression::ListEquals(left: a.children, right: b.children)) { |
72 | return false; |
73 | } |
74 | if (a.start != b.start || a.end != b.end) { |
75 | return false; |
76 | } |
77 | // check if the framing expressions are equivalentbind_ |
78 | if (!ParsedExpression::Equals(left: a.start_expr, right: b.start_expr) || !ParsedExpression::Equals(left: a.end_expr, right: b.end_expr) || |
79 | !ParsedExpression::Equals(left: a.offset_expr, right: b.offset_expr) || |
80 | !ParsedExpression::Equals(left: a.default_expr, right: b.default_expr)) { |
81 | return false; |
82 | } |
83 | |
84 | // check if the partitions are equivalent |
85 | if (!ParsedExpression::ListEquals(left: a.partitions, right: b.partitions)) { |
86 | return false; |
87 | } |
88 | // check if the orderings are equivalent |
89 | if (a.orders.size() != b.orders.size()) { |
90 | return false; |
91 | } |
92 | for (idx_t i = 0; i < a.orders.size(); i++) { |
93 | if (a.orders[i].type != b.orders[i].type) { |
94 | return false; |
95 | } |
96 | if (!a.orders[i].expression->Equals(other: *b.orders[i].expression)) { |
97 | return false; |
98 | } |
99 | } |
100 | // check if the filter clauses are equivalent |
101 | if (!ParsedExpression::Equals(left: a.filter_expr, right: b.filter_expr)) { |
102 | return false; |
103 | } |
104 | |
105 | return true; |
106 | } |
107 | |
108 | unique_ptr<ParsedExpression> WindowExpression::Copy() const { |
109 | auto new_window = make_uniq<WindowExpression>(args: type, args: catalog, args: schema, args: function_name); |
110 | new_window->CopyProperties(other: *this); |
111 | |
112 | for (auto &child : children) { |
113 | new_window->children.push_back(x: child->Copy()); |
114 | } |
115 | |
116 | for (auto &e : partitions) { |
117 | new_window->partitions.push_back(x: e->Copy()); |
118 | } |
119 | |
120 | for (auto &o : orders) { |
121 | new_window->orders.emplace_back(args: o.type, args: o.null_order, args: o.expression->Copy()); |
122 | } |
123 | |
124 | new_window->filter_expr = filter_expr ? filter_expr->Copy() : nullptr; |
125 | |
126 | new_window->start = start; |
127 | new_window->end = end; |
128 | new_window->start_expr = start_expr ? start_expr->Copy() : nullptr; |
129 | new_window->end_expr = end_expr ? end_expr->Copy() : nullptr; |
130 | new_window->offset_expr = offset_expr ? offset_expr->Copy() : nullptr; |
131 | new_window->default_expr = default_expr ? default_expr->Copy() : nullptr; |
132 | new_window->ignore_nulls = ignore_nulls; |
133 | |
134 | return std::move(new_window); |
135 | } |
136 | |
137 | void WindowExpression::Serialize(FieldWriter &writer) const { |
138 | auto &serializer = writer.GetSerializer(); |
139 | |
140 | writer.WriteString(val: function_name); |
141 | writer.WriteString(val: schema); |
142 | writer.WriteSerializableList(elements: children); |
143 | writer.WriteSerializableList(elements: partitions); |
144 | // FIXME: should not use serializer here (probably)? |
145 | D_ASSERT(orders.size() <= NumericLimits<uint32_t>::Maximum()); |
146 | writer.WriteField<uint32_t>(element: (uint32_t)orders.size()); |
147 | for (auto &order : orders) { |
148 | order.Serialize(serializer); |
149 | } |
150 | writer.WriteField<WindowBoundary>(element: start); |
151 | writer.WriteField<WindowBoundary>(element: end); |
152 | |
153 | writer.WriteOptional(element: start_expr); |
154 | writer.WriteOptional(element: end_expr); |
155 | writer.WriteOptional(element: offset_expr); |
156 | writer.WriteOptional(element: default_expr); |
157 | writer.WriteField<bool>(element: ignore_nulls); |
158 | writer.WriteOptional(element: filter_expr); |
159 | writer.WriteString(val: catalog); |
160 | } |
161 | |
162 | void WindowExpression::FormatSerialize(FormatSerializer &serializer) const { |
163 | ParsedExpression::FormatSerialize(serializer); |
164 | serializer.WriteProperty(tag: "function_name" , value: function_name); |
165 | serializer.WriteProperty(tag: "schema" , value: schema); |
166 | serializer.WriteProperty(tag: "children" , value: children); |
167 | serializer.WriteProperty(tag: "partitions" , value: partitions); |
168 | serializer.WriteProperty(tag: "orders" , value: orders); |
169 | serializer.WriteProperty(tag: "start" , value: start); |
170 | serializer.WriteProperty(tag: "end" , value: end); |
171 | serializer.WriteOptionalProperty(tag: "start_expr" , ptr: start_expr); |
172 | serializer.WriteOptionalProperty(tag: "end_expr" , ptr: end_expr); |
173 | serializer.WriteOptionalProperty(tag: "offset_expr" , ptr: offset_expr); |
174 | serializer.WriteOptionalProperty(tag: "default_expr" , ptr: default_expr); |
175 | serializer.WriteProperty(tag: "ignore_nulls" , value: ignore_nulls); |
176 | serializer.WriteOptionalProperty(tag: "filter_expr" , ptr: filter_expr); |
177 | serializer.WriteProperty(tag: "catalog" , value: catalog); |
178 | } |
179 | |
180 | unique_ptr<ParsedExpression> WindowExpression::FormatDeserialize(ExpressionType type, |
181 | FormatDeserializer &deserializer) { |
182 | auto function_name = deserializer.ReadProperty<string>(tag: "function_name" ); |
183 | auto schema = deserializer.ReadProperty<string>(tag: "schema" ); |
184 | auto expr = make_uniq<WindowExpression>(args&: type, INVALID_CATALOG, args: std::move(schema), args&: function_name); |
185 | |
186 | deserializer.ReadProperty(tag: "children" , ret&: expr->children); |
187 | deserializer.ReadProperty(tag: "partitions" , ret&: expr->partitions); |
188 | deserializer.ReadProperty(tag: "orders" , ret&: expr->orders); |
189 | deserializer.ReadProperty(tag: "start" , ret&: expr->start); |
190 | deserializer.ReadProperty(tag: "end" , ret&: expr->end); |
191 | deserializer.ReadOptionalProperty(tag: "start_expr" , ret&: expr->start_expr); |
192 | deserializer.ReadOptionalProperty(tag: "end_expr" , ret&: expr->end_expr); |
193 | deserializer.ReadOptionalProperty(tag: "offset_expr" , ret&: expr->offset_expr); |
194 | deserializer.ReadOptionalProperty(tag: "default_expr" , ret&: expr->default_expr); |
195 | deserializer.ReadProperty(tag: "ignore_nulls" , ret&: expr->ignore_nulls); |
196 | deserializer.ReadOptionalProperty(tag: "filter_expr" , ret&: expr->filter_expr); |
197 | deserializer.ReadProperty(tag: "catalog" , ret&: expr->catalog); |
198 | return std::move(expr); |
199 | } |
200 | |
201 | unique_ptr<ParsedExpression> WindowExpression::Deserialize(ExpressionType type, FieldReader &reader) { |
202 | auto function_name = reader.ReadRequired<string>(); |
203 | auto schema = reader.ReadRequired<string>(); |
204 | auto expr = make_uniq<WindowExpression>(args&: type, INVALID_CATALOG, args: std::move(schema), args&: function_name); |
205 | expr->children = reader.ReadRequiredSerializableList<ParsedExpression>(); |
206 | expr->partitions = reader.ReadRequiredSerializableList<ParsedExpression>(); |
207 | |
208 | auto order_count = reader.ReadRequired<uint32_t>(); |
209 | auto &source = reader.GetSource(); |
210 | for (idx_t i = 0; i < order_count; i++) { |
211 | expr->orders.push_back(x: OrderByNode::Deserialize(source)); |
212 | } |
213 | expr->start = reader.ReadRequired<WindowBoundary>(); |
214 | expr->end = reader.ReadRequired<WindowBoundary>(); |
215 | |
216 | expr->start_expr = reader.ReadOptional<ParsedExpression>(default_value: nullptr); |
217 | expr->end_expr = reader.ReadOptional<ParsedExpression>(default_value: nullptr); |
218 | expr->offset_expr = reader.ReadOptional<ParsedExpression>(default_value: nullptr); |
219 | expr->default_expr = reader.ReadOptional<ParsedExpression>(default_value: nullptr); |
220 | expr->ignore_nulls = reader.ReadRequired<bool>(); |
221 | expr->filter_expr = reader.ReadOptional<ParsedExpression>(default_value: nullptr); |
222 | expr->catalog = reader.ReadField<string>(INVALID_CATALOG); |
223 | return std::move(expr); |
224 | } |
225 | |
226 | } // namespace duckdb |
227 | |