| 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 | |