Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow using aggregate operations on Mixed properties in queries #7398

Merged
merged 1 commit into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

### Enhancements
* <New feature description> (PR [#????](https://github.com/realm/realm-core/pull/????))
* None.
* Add support for using aggregate operations on Mixed properties in queries ([PR #7398](https://github.com/realm/realm-core/pull/7398))

### Fixed
* <How do the end-user experience this issue? what was the impact?> ([#????](https://github.com/realm/realm-core/issues/????), since v?.?.?)
Expand Down
3 changes: 3 additions & 0 deletions src/realm/parser/driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1146,6 +1146,9 @@ std::unique_ptr<Subexpr> LinkAggrNode::visit(ParserDriver* drv, DataType)
case col_type_Timestamp:
subexpr = link_prop->column<Timestamp>(col_key).clone();
break;
case col_type_Mixed:
subexpr = link_prop->column<Mixed>(col_key).clone();
break;
default:
throw InvalidQueryError(util::format("collection aggregate not supported for type '%1'",
get_data_type_name(DataType(col_key.get_type()))));
Expand Down
18 changes: 7 additions & 11 deletions src/realm/query_expression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -735,11 +735,6 @@ class Subexpr {
virtual DataType get_type() const = 0;

virtual void evaluate(size_t index, ValueBase& destination) = 0;
// This function supports SubColumnAggregate
virtual void evaluate(ObjKey, ValueBase&)
{
REALM_ASSERT(false); // Unimplemented
}

virtual Mixed get_mixed() const
{
Expand Down Expand Up @@ -1923,7 +1918,7 @@ class SimpleQuerySupport : public ObjPropertyExpr<T> {
}
}

void evaluate(ObjKey key, ValueBase& destination) override
void evaluate(ObjKey key, ValueBase& destination)
{
Value<T>& d = static_cast<Value<T>&>(destination);
d.set(0, m_link_map.get_target_table()->get_object(key).template get<T>(m_column_key));
Expand Down Expand Up @@ -2015,6 +2010,7 @@ class Columns<Decimal128> : public SimpleQuerySupport<Decimal128> {
template <>
class Columns<Mixed> : public SimpleQuerySupport<Mixed> {
public:
using SimpleQuerySupport::evaluate; // don't hide the ObjKey overload
using SimpleQuerySupport::SimpleQuerySupport;
void evaluate(size_t index, ValueBase& destination) override
{
Expand Down Expand Up @@ -3891,7 +3887,7 @@ class Columns : public ObjPropertyExpr<T> {
}
}

void evaluate(ObjKey key, ValueBase& destination) override
void evaluate(ObjKey key, ValueBase& destination)
{
destination.init(false, 1);
auto table = m_link_map.get_target_table();
Expand Down Expand Up @@ -3993,7 +3989,7 @@ class SubColumns : public Subexpr, public SubColumnBase {

std::unique_ptr<Subexpr> max_of() override
{
if constexpr (realm::is_any_v<T, Int, Float, Double, Decimal128, Timestamp>) {
if constexpr (realm::is_any_v<T, Int, Float, Double, Decimal128, Timestamp, Mixed>) {
return max().clone();
}
else {
Expand All @@ -4002,7 +3998,7 @@ class SubColumns : public Subexpr, public SubColumnBase {
}
std::unique_ptr<Subexpr> min_of() override
{
if constexpr (realm::is_any_v<T, Int, Float, Double, Decimal128, Timestamp>) {
if constexpr (realm::is_any_v<T, Int, Float, Double, Decimal128, Timestamp, Mixed>) {
return min().clone();
}
else {
Expand All @@ -4011,7 +4007,7 @@ class SubColumns : public Subexpr, public SubColumnBase {
}
std::unique_ptr<Subexpr> sum_of() override
{
if constexpr (realm::is_any_v<T, Int, Float, Double, Decimal128>) {
if constexpr (realm::is_any_v<T, Int, Float, Double, Decimal128, Mixed>) {
return sum().clone();
}
else {
Expand All @@ -4020,7 +4016,7 @@ class SubColumns : public Subexpr, public SubColumnBase {
}
std::unique_ptr<Subexpr> avg_of() override
{
if constexpr (realm::is_any_v<T, Int, Float, Double, Decimal128>) {
if constexpr (realm::is_any_v<T, Int, Float, Double, Decimal128, Mixed>) {
return average().clone();
}
else {
Expand Down
15 changes: 15 additions & 0 deletions test/test_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1296,6 +1296,7 @@ TEST(Parser_TwoColumnAggregates)
ColKey item_price_col = items->add_column(type_Double, "price");
ColKey item_price_float_col = items->add_column(type_Float, "price_float");
ColKey item_price_decimal_col = items->add_column(type_Decimal, "price_decimal");
ColKey item_price_mixed_col = items->add_column(type_Mixed, "price_mixed");
ColKey item_discount_col = items->add_column(*discounts, "discount");
ColKey item_creation_date = items->add_column(type_Timestamp, "creation_date");
using item_t = std::pair<std::string, double>;
Expand All @@ -1308,6 +1309,7 @@ TEST(Parser_TwoColumnAggregates)
obj.set(item_price_col, item_info[i].second);
obj.set(item_price_float_col, float(item_info[i].second));
obj.set(item_price_decimal_col, Decimal128(item_info[i].second));
obj.set(item_price_mixed_col, Mixed(item_info[i].second));
obj.set(item_creation_date, Timestamp(static_cast<int64_t>(item_info[i].second * 10), 0));
}
items->get_object(item_keys[0]).set(item_discount_col, discount_keys[2]); // milk -0.50
Expand All @@ -1320,6 +1322,7 @@ TEST(Parser_TwoColumnAggregates)
ColKey items_col = t->add_column_list(*items, "items");
ColKey account_float_col = t->add_column(type_Float, "account_balance_float");
ColKey account_decimal_col = t->add_column(type_Decimal, "account_balance_decimal");
ColKey account_mixed_col = t->add_column(type_Mixed, "account_balance_mixed");
ColKey account_creation_date_col = t->add_column(type_Timestamp, "account_creation_date");

Obj person0 = t->create_object();
Expand All @@ -1330,16 +1333,19 @@ TEST(Parser_TwoColumnAggregates)
person0.set(account_col, double(10.0));
person0.set(account_float_col, float(10.0));
person0.set(account_decimal_col, Decimal128(10.0));
person0.set(account_mixed_col, Mixed(10.0));
person0.set(account_creation_date_col, Timestamp(30, 0));
person1.set(id_col, int64_t(1));
person1.set(account_col, double(20.0));
person1.set(account_float_col, float(20.0));
person1.set(account_decimal_col, Decimal128(20.0));
person1.set(account_mixed_col, Mixed(20.0));
person1.set(account_creation_date_col, Timestamp(50, 0));
person2.set(id_col, int64_t(2));
person2.set(account_col, double(30.0));
person2.set(account_float_col, float(30.0));
person2.set(account_decimal_col, Decimal128(30.0));
person2.set(account_mixed_col, Mixed(30.0));
person2.set(account_creation_date_col, Timestamp(70, 0));

LnkLst list_0 = person0.get_linklist(items_col);
Expand Down Expand Up @@ -1397,6 +1403,15 @@ TEST(Parser_TwoColumnAggregates)
verify_query(test_context, t, "items.@min.price_decimal > account_balance_decimal", 0);
verify_query(test_context, t, "items.@max.price_decimal > account_balance_decimal", 0);
verify_query(test_context, t, "items.@avg.price_decimal > account_balance_decimal", 0);
// Mixed vs Mixed
verify_query(test_context, t, "items.@sum.price_mixed == 25.5", 2); // person0, person2
verify_query(test_context, t, "items.@min.price_mixed == 4.0", 1); // person0
verify_query(test_context, t, "items.@max.price_mixed == 9.5", 2); // person0, person2
verify_query(test_context, t, "items.@avg.price_mixed == 6.375", 1); // person0
verify_query(test_context, t, "items.@sum.price_mixed > account_balance_mixed", 2);
verify_query(test_context, t, "items.@min.price_mixed > account_balance_mixed", 0);
verify_query(test_context, t, "items.@max.price_mixed > account_balance_mixed", 0);
verify_query(test_context, t, "items.@avg.price_mixed > account_balance_mixed", 0);
// Timestamp vs Timestamp
verify_query(test_context, t, "items.@min.creation_date == T40:0", 1); // person0
verify_query(test_context, t, "items.@max.creation_date == T95:0", 2); // person0, person2
Expand Down
Loading