From 430a044fea5447546dd19efebdbd5a056272ac59 Mon Sep 17 00:00:00 2001 From: James Stone Date: Thu, 8 Aug 2024 09:17:04 -0700 Subject: [PATCH] fix RQL BETWEEN regression for properties over links (#7965) --- CHANGELOG.md | 4 ++-- src/realm/parser/driver.cpp | 2 +- test/test_parser.cpp | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fba468c4b8c..c28abe11e97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ ### Fixed * ([#????](https://github.com/realm/realm-core/issues/????), since v?.?.?) -* None. +* Fixed an "invalid column key" exception when using a RQL "BETWEEN" query on an int or timestamp property across links. ([#7935](https://github.com/realm/realm-core/issues/7935), since v14.10.1) ### Breaking changes * None. @@ -171,7 +171,7 @@ ### Enhancements * It is no longer an error to set a base url for an App with a trailing slash - for example, `https://services.cloud.mongodb.com/` instead of `https://services.cloud.mongodb.com` - before this change that would result in a 404 error from the server ([PR #7791](https://github.com/realm/realm-core/pull/7791)). -* Performance has been improved for range queries on integers and timestamps. Requires that you use the "BETWEEN" operation in MQL or the Query::between() method when you build the query. (PR [#7785](https://github.com/realm/realm-core/pull/7785)) +* Performance has been improved for range queries on integers and timestamps. Requires that you use the "BETWEEN" operation in RQL or the Query::between() method when you build the query. (PR [#7785](https://github.com/realm/realm-core/pull/7785)) * Expose `Obj::add_int()` in the bindgen spec. ([PR #7797](https://github.com/realm/realm-core/pull/7797)). ### Fixed diff --git a/src/realm/parser/driver.cpp b/src/realm/parser/driver.cpp index 0dae67ffa4a..e91f762df7c 100644 --- a/src/realm/parser/driver.cpp +++ b/src/realm/parser/driver.cpp @@ -644,7 +644,7 @@ Query BetweenNode::visit(ParserDriver* drv) auto tmp = prop->visit(drv); const ObjPropertyBase* obj_prop = dynamic_cast(tmp.get()); - if (obj_prop) { + if (obj_prop && !obj_prop->links_exist()) { if (tmp->get_type() == type_Int) { auto min_val = min->visit(drv, type_Int); auto max_val = max->visit(drv, type_Int); diff --git a/test/test_parser.cpp b/test/test_parser.cpp index 233cfd2f88d..2db5738418b 100644 --- a/test/test_parser.cpp +++ b/test/test_parser.cpp @@ -6100,6 +6100,41 @@ TEST(Parser_Between) CHECK_THROW_ANY(verify_query(test_context, table, "NONE scores between {10, 12}", 1)); } +TEST(Test_Between_OverLinks) +{ + Group g; + TableRef parent = g.add_table("Parent"); + TableRef child = g.add_table("Child"); + + ColKey ck_child = parent->add_column(*child, "child"); + ColKey ck_int = child->add_column(type_Int, "int"); + ColKey ck_timestamp = child->add_column(type_Timestamp, "timestamp"); + + constexpr size_t num_children = 100; + for (size_t i = 0; i < num_children; ++i) { + auto obj = child->create_object(); + obj.set(ck_int, (int)i); + obj.set(ck_timestamp, Timestamp{int64_t(i), 0}); + parent->create_object().set(ck_child, obj.get_key()); + parent->create_object().set(ck_child, obj.get_key()); + } + parent->create_object(); // null link + + verify_query(test_context, child, "int BETWEEN {0, 100}", 100); + verify_query(test_context, child, "timestamp BETWEEN {$0, $1}", {Timestamp{0, 0}, Timestamp{100, 0}}, 100); + verify_query(test_context, child, "int BETWEEN {1, 2}", 2); + verify_query(test_context, child, "timestamp BETWEEN {$0, $1}", {Timestamp{1, 0}, Timestamp{2, 0}}, 2); + verify_query(test_context, child, "int BETWEEN {-1, -2}", 0); + verify_query(test_context, child, "timestamp BETWEEN {$0, $1}", {Timestamp{-1, 0}, Timestamp{-2, 0}}, 0); + + verify_query(test_context, parent, "child.int BETWEEN {0, 100}", 200); + verify_query(test_context, parent, "child.timestamp BETWEEN {$0, $1}", {Timestamp{0, 0}, Timestamp{100, 0}}, 200); + verify_query(test_context, parent, "child.int BETWEEN {1, 2}", 4); + verify_query(test_context, parent, "child.timestamp BETWEEN {$0, $1}", {Timestamp{1, 0}, Timestamp{2, 0}}, 4); + verify_query(test_context, parent, "child.int BETWEEN {-1, -2}", 0); + verify_query(test_context, parent, "child.timestamp BETWEEN {$0, $1}", {Timestamp{-1, 0}, Timestamp{-2, 0}}, 0); +} + TEST(Parser_PrimaryKey) { UUID u1("3b241101-e2bb-4255-8caf-4136c566a961");