From 3334d3869b8cba9a4ae63247f80f3f1739e32c07 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 5 Jul 2024 15:18:01 +0200 Subject: [PATCH 1/4] New changelog section to prepare for vNext (#7866) --- CHANGELOG.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84b3156103..0a5b123906 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,26 @@ +# NEXT RELEASE + +### Enhancements +* (PR [#????](https://github.com/realm/realm-core/pull/????)) +* None. + +### Fixed +* ([#????](https://github.com/realm/realm-core/issues/????), since v?.?.?) +* None. + +### Breaking changes +* None. + +### Compatibility +* Fileformat: Generates files with format v24. Reads and automatically upgrade from fileformat v10. If you want to upgrade from an earlier file format version you will have to use RealmCore v13.x.y or earlier. + +----------- + +### Internals +* None. + +---------------------------------------------- + # 14.10.3 Release notes ### Enhancements From 77ba4274444f5712ed401159b6f54e40029e8591 Mon Sep 17 00:00:00 2001 From: Daniel Tabacaru <96778637+danieltabacaru@users.noreply.github.com> Date: Wed, 10 Jul 2024 11:37:39 +0300 Subject: [PATCH 2/4] Bump baas (#7875) --- dependencies.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.yml b/dependencies.yml index 930a99026a..a79050f91e 100644 --- a/dependencies.yml +++ b/dependencies.yml @@ -3,5 +3,5 @@ VERSION: 14.10.3 OPENSSL_VERSION: 3.2.0 ZLIB_VERSION: 1.2.13 # https://github.com/10gen/baas/commits -# 9d1b4d6 is 2024 May 8 -BAAS_VERSION: 9d1b4d628babadfb606ebcadb93b1e5cae3c9565 +# 2f308db is 2024 July 10 +BAAS_VERSION: 2f308db6f65333728a101d1fecbb792f9659a5ce From 5dc121b35f4f02b70d6424ffe44c9a9c0dff79ad Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Wed, 10 Jul 2024 18:03:13 -0700 Subject: [PATCH 3/4] Fix data races in the connection state changes tests (#7871) The assignment to token1 on the main thread and the read of it on the sync worker thread didn't have any intervening synchronization and in theory the callback could read it before it's actually written. Fixing this requires adding some locking. Conversely, listener2 doesn't actually need to be atomic since the second callback should only ever be invokved synchronously inside log_out(), and if it's called at some other time that's a bug. It doesn't matter here, but `listener1_call_cnt = listener1_call_cnt + 1` is a nonatomic increment that will drop updates if it happens on multiple threads at once, while `++` will not. --- CHANGELOG.md | 2 +- .../session/connection_change_notifications.cpp | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a5b123906..37269ebe22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ ----------- ### Internals -* None. +* Fix a thread sanitizer failure in the "unregister connection change listener during callback" test ([PR #7871](https://github.com/realm/realm-core/pull/7871)). ---------------------------------------------- diff --git a/test/object-store/sync/session/connection_change_notifications.cpp b/test/object-store/sync/session/connection_change_notifications.cpp index d9c52546ac..8a9fd2591c 100644 --- a/test/object-store/sync/session/connection_change_notifications.cpp +++ b/test/object-store/sync/session/connection_change_notifications.cpp @@ -69,7 +69,7 @@ TEST_CASE("sync: Connection state changes", "[sync][session][connection change]" auto token1 = session->register_connection_change_callback( [&](SyncSession::ConnectionState, SyncSession::ConnectionState) { - listener1_call_cnt = listener1_call_cnt + 1; + ++listener1_call_cnt; }); session->unregister_connection_change_callback(token1); // One call may have been in progress when unregistered @@ -87,16 +87,18 @@ TEST_CASE("sync: Connection state changes", "[sync][session][connection change]" } SECTION("unregister connection change listener during callback") { - uint64_t token1; - std::atomic listener1_call_cnt(0); - std::atomic listener2_called(false); + int listener1_call_cnt = 0; auto session = sync_session( user, "/connection-state-changes-3", [](auto, auto) {}, SyncSessionStopPolicy::AfterChangesUploaded); - token1 = session->register_connection_change_callback( + std::mutex mutex; + std::unique_lock lock(mutex); + uint64_t token1 = session->register_connection_change_callback( [&](SyncSession::ConnectionState, SyncSession::ConnectionState) { - listener1_call_cnt = listener1_call_cnt + 1; + std::lock_guard lock(mutex); + ++listener1_call_cnt; session->unregister_connection_change_callback(token1); }); + lock.unlock(); EventLoop::main().run_until([&] { return sessions_are_active(*session); @@ -105,6 +107,7 @@ TEST_CASE("sync: Connection state changes", "[sync][session][connection change]" return sessions_are_connected(*session); }); + bool listener2_called = false; session->register_connection_change_callback([&](SyncSession::ConnectionState, SyncSession::ConnectionState) { listener2_called = true; }); From a7479e58c14f02cc152014dfaf538ee377863d6a Mon Sep 17 00:00:00 2001 From: Kenneth Geisshirt Date: Thu, 11 Jul 2024 13:07:45 +0200 Subject: [PATCH 4/4] Allow both internal and public name in realm::Results::{sort, distinct} (#7877) --- CHANGELOG.md | 3 +-- src/realm/object-store/results.cpp | 3 +++ test/object-store/results.cpp | 27 +++++++++++++++++++++++++-- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37269ebe22..6c0032ba6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,7 @@ * None. ### Fixed -* ([#????](https://github.com/realm/realm-core/issues/????), since v?.?.?) -* None. +* When a public name is defined on a property, calling `realm::Results::sort()` or `realm::Results::distinct()` with the internal name could throw an error like `Cannot sort on key path 'NAME': property 'PersonObject.NAME' does not exist`. ([realm/realm-js#6779](https://github.com/realm/realm-js/issues/6779), since v12.12.0) ### Breaking changes * None. diff --git a/src/realm/object-store/results.cpp b/src/realm/object-store/results.cpp index e9584d2b41..8d959ae05a 100644 --- a/src/realm/object-store/results.cpp +++ b/src/realm/object-store/results.cpp @@ -871,6 +871,9 @@ static std::vector parse_keypath(StringData keypath, Schema c begin = sep + (sep != end); auto prop = object_schema->property_for_public_name(key); + if (!prop) { + prop = object_schema->property_for_name(key); + } check(prop, "property '%1.%2' does not exist", object_schema->name, key); if (is_dictionary(prop->type)) { check(index.length(), "missing dictionary key"); diff --git a/test/object-store/results.cpp b/test/object-store/results.cpp index 4b3c6a9cb0..1814d06cd8 100644 --- a/test/object-store/results.cpp +++ b/test/object-store/results.cpp @@ -4984,7 +4984,7 @@ TEST_CASE("results: public name declared", "[results]") { realm->commit_transaction(); Results r(realm, table); - SECTION("sorted") { + SECTION("sorted by public_name") { auto sorted = r.sort({{"public_value", true}}); REQUIRE(sorted.limit(0).size() == 0); REQUIRE_ORDER(sorted.limit(1), 2); @@ -4993,7 +4993,16 @@ TEST_CASE("results: public name declared", "[results]") { REQUIRE_ORDER(sorted.limit(100), 2, 6, 3, 7, 0, 4, 1, 5); } - SECTION("distinct") { + SECTION("sorted by name") { + auto sorted = r.sort({{"value", true}}); + REQUIRE(sorted.limit(0).size() == 0); + REQUIRE_ORDER(sorted.limit(1), 2); + REQUIRE_ORDER(sorted.limit(2), 2, 6); + REQUIRE_ORDER(sorted.limit(8), 2, 6, 3, 7, 0, 4, 1, 5); + REQUIRE_ORDER(sorted.limit(100), 2, 6, 3, 7, 0, 4, 1, 5); + } + + SECTION("distinct by public_name") { auto sorted = r.distinct({"public_value"}); REQUIRE(sorted.limit(0).size() == 0); REQUIRE_ORDER(sorted.limit(1), 0); @@ -5006,6 +5015,20 @@ TEST_CASE("results: public name declared", "[results]") { REQUIRE_ORDER(sorted.limit(2), 2, 3); REQUIRE_ORDER(sorted.limit(8), 2, 3, 0, 1); } + + SECTION("distinct by name") { + auto sorted = r.distinct({"value"}); + REQUIRE(sorted.limit(0).size() == 0); + REQUIRE_ORDER(sorted.limit(1), 0); + REQUIRE_ORDER(sorted.limit(2), 0, 1); + REQUIRE_ORDER(sorted.limit(8), 0, 1, 2, 3); + + sorted = r.sort({{"value", true}}).distinct({"value"}); + REQUIRE(sorted.limit(0).size() == 0); + REQUIRE_ORDER(sorted.limit(1), 2); + REQUIRE_ORDER(sorted.limit(2), 2, 3); + REQUIRE_ORDER(sorted.limit(8), 2, 3, 0, 1); + } } TEST_CASE("notifications: objects with PK recreated", "[results]") {