Skip to content

Commit

Permalink
RCORE-2168: Replicate clear instruction unconditionally (#7810)
Browse files Browse the repository at this point in the history
This will fix inconsistent merge behavior
  • Loading branch information
jedelbo authored Jun 18, 2024
1 parent 3e0473f commit b5ca450
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
* Opening an FLX realm asynchronously may not wait to download all data ([#7720](https://github.com/realm/realm-core/issues/7720), since FLX sync was introduced).
* Clearing a List of Mixed in an upgraded file would lead to an assertion failing ([#7771](https://github.com/realm/realm-core/issues/7771), since 14.0.0)
* Fix compilation with Xcode 16 ([PR #7802](https://github.com/realm/realm-core/pull/7802))
* You could get unexpected merge results when assigning to a list ([#7809](https://github.com/realm/realm-core/issues/7809), since v10.2.0)

### Breaking changes
* None.
Expand Down
9 changes: 5 additions & 4 deletions src/realm/dictionary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -823,10 +823,11 @@ size_t Dictionary::find_first(Mixed value) const

void Dictionary::clear()
{
if (size() > 0) {
if (Replication* repl = get_replication()) {
repl->dictionary_clear(*this);
}
auto sz = size();
if (Replication* repl = get_replication()) {
repl->dictionary_clear(*this);
}
if (sz > 0) {
CascadeState cascade_state(CascadeState::Mode::Strong);
bool recurse = remove_backlinks(cascade_state);

Expand Down
9 changes: 5 additions & 4 deletions src/realm/list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -503,10 +503,11 @@ void Lst<Mixed>::remove(size_t from, size_t to)

void Lst<Mixed>::clear()
{
if (size() > 0) {
if (Replication* repl = Base::get_replication()) {
repl->list_clear(*this);
}
auto sz = size();
if (Replication* repl = Base::get_replication()) {
repl->list_clear(*this);
}
if (sz > 0) {
CascadeState state;
bool recurse = remove_backlinks(state);

Expand Down
9 changes: 5 additions & 4 deletions src/realm/list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -930,10 +930,11 @@ inline LnkLst Obj::get_linklist(StringData col_name) const
template <class T>
void Lst<T>::clear()
{
if (size() > 0) {
if (Replication* repl = Base::get_replication()) {
repl->list_clear(*this);
}
auto sz = size();
if (Replication* repl = Base::get_replication()) {
repl->list_clear(*this);
}
if (sz > 0) {
do_clear();
bump_content_version();
}
Expand Down
4 changes: 2 additions & 2 deletions test/object-store/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2011,8 +2011,8 @@ TEST_CASE("object") {

r1->begin_transaction();
r2->begin_transaction();
auto object1 = Object::create(c1, r1, *r1->schema().find("pk after list"), std::any(v1));
auto object2 = Object::create(c2, r2, *r2->schema().find("pk after list"), std::any(v2));
auto object1 = Object::create(c1, r1, "pk after list", std::any(v1), CreatePolicy::UpdateModified);
auto object2 = Object::create(c2, r2, "pk after list", std::any(v2), CreatePolicy::UpdateModified);
r2->commit_transaction();
r1->commit_transaction();

Expand Down
73 changes: 73 additions & 0 deletions test/test_sync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6204,6 +6204,79 @@ TEST(Sync_DeleteCollectionInCollection)
}
}

TEST(Sync_CollectionClear)
{
TEST_CLIENT_DB(db_1);
TEST_CLIENT_DB(db_2);

TEST_DIR(dir);
fixtures::ClientServerFixture fixture{dir, test_context};
fixture.start();

Session session_1 = fixture.make_session(db_1, "/test");
Session session_2 = fixture.make_session(db_2, "/test");

Timestamp now{std::chrono::system_clock::now()};

write_transaction(db_1, [&](WriteTransaction& tr) {
auto& g = tr.get_group();
auto table = g.add_table_with_primary_key("class_Table", type_Int, "id");
auto col_list = table->add_column_list(type_Int, "ints");
auto col_list_mixed = table->add_column_list(type_Mixed, "any");
auto col_dict = table->add_column_dictionary(type_String, "features");

auto foo = table->create_object_with_primary_key(123);
auto list = foo.get_list<Int>(col_list);
list.clear();
list.add(1);
auto list_mixed = foo.get_list<Mixed>(col_list_mixed);
list_mixed.clear();
list_mixed.add("Hello");
auto dict = foo.get_dictionary(col_dict);
dict.clear();
dict.insert("address", "Any Road 3");
});

write_transaction(db_2, [&](WriteTransaction& tr) {
auto& g = tr.get_group();
auto table = g.add_table_with_primary_key("class_Table", type_Int, "id");
auto col_list = table->add_column_list(type_Int, "ints");
auto col_list_mixed = table->add_column_list(type_Mixed, "any");
auto col_dict = table->add_column_dictionary(type_String, "features");

auto foo = table->create_object_with_primary_key(123);
auto list = foo.get_list<Int>(col_list);
list.clear();
list.add(2);
auto list_mixed = foo.get_list<Mixed>(col_list_mixed);
list_mixed.clear();
list_mixed.add("Godbye");
auto dict = foo.get_dictionary(col_dict);
dict.clear();
dict.insert("city", "Andeby");
});

session_1.wait_for_upload_complete_or_client_stopped();
session_2.wait_for_upload_complete_or_client_stopped();
session_1.wait_for_download_complete_or_client_stopped();
session_2.wait_for_download_complete_or_client_stopped();

{
ReadTransaction read_1{db_1};
auto table = read_1.get_table("class_Table");
auto obj = table->get_object_with_primary_key(123);
auto list = obj.get_list<Int>("ints");
auto list_mixed = obj.get_list<Mixed>("any");
auto dict = obj.get_dictionary("features");
CHECK_EQUAL(list.size(), 1);
CHECK_EQUAL(list_mixed.size(), 1);
CHECK_EQUAL(dict.size(), 1);

ReadTransaction read_2{db_2};
CHECK(compare_groups(read_1, read_2));
}
}

TEST(Sync_Dictionary_Links)
{
TEST_CLIENT_DB(db_1);
Expand Down

0 comments on commit b5ca450

Please sign in to comment.