1 | #include "duckdb/parser/expression/window_expression.hpp" |
2 | |
3 | #include "duckdb/common/serializer.hpp" |
4 | #include "duckdb/common/string_util.hpp" |
5 | |
6 | using namespace duckdb; |
7 | using namespace std; |
8 | |
9 | WindowExpression::WindowExpression(ExpressionType type, string schema, string function_name) |
10 | : ParsedExpression(type, ExpressionClass::WINDOW), schema(schema), function_name(StringUtil::Lower(function_name)) { |
11 | switch (type) { |
12 | case ExpressionType::WINDOW_AGGREGATE: |
13 | case ExpressionType::WINDOW_ROW_NUMBER: |
14 | case ExpressionType::WINDOW_FIRST_VALUE: |
15 | case ExpressionType::WINDOW_LAST_VALUE: |
16 | case ExpressionType::WINDOW_RANK: |
17 | case ExpressionType::WINDOW_RANK_DENSE: |
18 | case ExpressionType::WINDOW_PERCENT_RANK: |
19 | case ExpressionType::WINDOW_CUME_DIST: |
20 | case ExpressionType::WINDOW_LEAD: |
21 | case ExpressionType::WINDOW_LAG: |
22 | case ExpressionType::WINDOW_NTILE: |
23 | break; |
24 | default: |
25 | throw NotImplementedException("Window aggregate type %s not supported" , ExpressionTypeToString(type).c_str()); |
26 | } |
27 | } |
28 | |
29 | string WindowExpression::ToString() const { |
30 | return "WINDOW" ; |
31 | } |
32 | |
33 | bool WindowExpression::Equals(const WindowExpression *a, const WindowExpression *b) { |
34 | // check if the child expressions are equivalent |
35 | if (b->children.size() != a->children.size()) { |
36 | return false; |
37 | } |
38 | for (idx_t i = 0; i < a->children.size(); i++) { |
39 | if (!a->children[i]->Equals(b->children[i].get())) { |
40 | return false; |
41 | } |
42 | } |
43 | if (a->start != b->start || a->end != b->end) { |
44 | return false; |
45 | } |
46 | // check if the framing expressions are equivalent |
47 | if (!BaseExpression::Equals(a->start_expr.get(), b->start_expr.get()) || |
48 | !BaseExpression::Equals(a->end_expr.get(), b->end_expr.get()) || |
49 | !BaseExpression::Equals(a->offset_expr.get(), b->offset_expr.get()) || |
50 | !BaseExpression::Equals(a->default_expr.get(), b->default_expr.get())) { |
51 | return false; |
52 | } |
53 | |
54 | // check if the partitions are equivalent |
55 | if (a->partitions.size() != b->partitions.size()) { |
56 | return false; |
57 | } |
58 | for (idx_t i = 0; i < a->partitions.size(); i++) { |
59 | if (!a->partitions[i]->Equals(b->partitions[i].get())) { |
60 | return false; |
61 | } |
62 | } |
63 | // check if the orderings are equivalent |
64 | if (a->orders.size() != b->orders.size()) { |
65 | return false; |
66 | } |
67 | for (idx_t i = 0; i < a->orders.size(); i++) { |
68 | if (a->orders[i].type != b->orders[i].type) { |
69 | return false; |
70 | } |
71 | if (!a->orders[i].expression->Equals(b->orders[i].expression.get())) { |
72 | return false; |
73 | } |
74 | } |
75 | return true; |
76 | } |
77 | |
78 | unique_ptr<ParsedExpression> WindowExpression::Copy() const { |
79 | auto new_window = make_unique<WindowExpression>(type, schema, function_name); |
80 | new_window->CopyProperties(*this); |
81 | |
82 | for (auto &child : children) { |
83 | new_window->children.push_back(child->Copy()); |
84 | } |
85 | |
86 | for (auto &e : partitions) { |
87 | new_window->partitions.push_back(e->Copy()); |
88 | } |
89 | |
90 | for (auto &o : orders) { |
91 | OrderByNode node; |
92 | node.type = o.type; |
93 | node.expression = o.expression->Copy(); |
94 | new_window->orders.push_back(move(node)); |
95 | } |
96 | |
97 | new_window->start = start; |
98 | new_window->end = end; |
99 | new_window->start_expr = start_expr ? start_expr->Copy() : nullptr; |
100 | new_window->end_expr = end_expr ? end_expr->Copy() : nullptr; |
101 | new_window->offset_expr = offset_expr ? offset_expr->Copy() : nullptr; |
102 | new_window->default_expr = default_expr ? default_expr->Copy() : nullptr; |
103 | |
104 | return move(new_window); |
105 | } |
106 | |
107 | void WindowExpression::Serialize(Serializer &serializer) { |
108 | ParsedExpression::Serialize(serializer); |
109 | serializer.WriteString(function_name); |
110 | serializer.WriteString(schema); |
111 | serializer.WriteList(children); |
112 | serializer.WriteList(partitions); |
113 | assert(orders.size() <= numeric_limits<uint32_t>::max()); |
114 | serializer.Write<uint32_t>((uint32_t)orders.size()); |
115 | for (auto &order : orders) { |
116 | serializer.Write<OrderType>(order.type); |
117 | order.expression->Serialize(serializer); |
118 | } |
119 | serializer.Write<WindowBoundary>(start); |
120 | serializer.Write<WindowBoundary>(end); |
121 | |
122 | serializer.WriteOptional(start_expr); |
123 | serializer.WriteOptional(end_expr); |
124 | serializer.WriteOptional(offset_expr); |
125 | serializer.WriteOptional(default_expr); |
126 | } |
127 | |
128 | unique_ptr<ParsedExpression> WindowExpression::Deserialize(ExpressionType type, Deserializer &source) { |
129 | auto function_name = source.Read<string>(); |
130 | auto schema = source.Read<string>(); |
131 | auto expr = make_unique<WindowExpression>(type, schema, function_name); |
132 | source.ReadList<ParsedExpression>(expr->children); |
133 | source.ReadList<ParsedExpression>(expr->partitions); |
134 | |
135 | auto order_count = source.Read<uint32_t>(); |
136 | for (idx_t i = 0; i < order_count; i++) { |
137 | auto order_type = source.Read<OrderType>(); |
138 | auto expression = ParsedExpression::Deserialize(source); |
139 | expr->orders.push_back(OrderByNode(order_type, move(expression))); |
140 | } |
141 | expr->start = source.Read<WindowBoundary>(); |
142 | expr->end = source.Read<WindowBoundary>(); |
143 | |
144 | expr->start_expr = source.ReadOptional<ParsedExpression>(); |
145 | expr->end_expr = source.ReadOptional<ParsedExpression>(); |
146 | expr->offset_expr = source.ReadOptional<ParsedExpression>(); |
147 | expr->default_expr = source.ReadOptional<ParsedExpression>(); |
148 | return move(expr); |
149 | } |
150 | |