Skip to content

Commit

Permalink
Support getting nested collections via templated API
Browse files Browse the repository at this point in the history
  • Loading branch information
jedelbo committed Mar 15, 2024
1 parent 9eaf6c3 commit f3563f3
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 19 deletions.
7 changes: 7 additions & 0 deletions src/realm/object-store/collection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ void Collection::validate_embedded(Context& ctx, T&& value, CreatePolicy policy)
throw IllegalOperation(util::format("Cannot add an existing managed embedded object to a %1.", type_name()));
}

// Dummy implementation to satisfy StringifyingContext
inline std::ostream& operator<<(std::ostream& out, const Collection&)
{
return out;
}


} // namespace object_store
} // namespace realm

Expand Down
18 changes: 15 additions & 3 deletions src/realm/object-store/dictionary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,21 @@ void Dictionary::insert(Context& ctx, StringData key, T&& value, CreatePolicy po
template <typename Context>
auto Dictionary::get(Context& ctx, StringData key) const
{
return dispatch([&](auto t) {
return ctx.box(this->get<std::decay_t<decltype(*t)>>(key));
});
if (m_type == PropertyType::Mixed) {
Mixed value = dict().get(key);
if (value.is_type(type_Dictionary)) {
return ctx.box(get_dictionary(key));
}
if (value.is_type(type_List)) {
return ctx.box(get_list(key));
}
return ctx.box(value);
}
else {
return dispatch([&](auto t) {
return ctx.box(this->get<std::decay_t<decltype(*t)>>(key));
});
}
}

template <typename T, typename Context>
Expand Down
18 changes: 15 additions & 3 deletions src/realm/object-store/list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,21 @@ auto List::dispatch(Fn&& fn) const
template <typename Context>
auto List::get(Context& ctx, size_t row_ndx) const
{
return dispatch([&](auto t) {
return ctx.box(this->get<std::decay_t<decltype(*t)>>(row_ndx));
});
if (m_type == PropertyType::Mixed) {
Mixed value = get<Mixed>(row_ndx);
if (value.is_type(type_Dictionary)) {
return ctx.box(get_dictionary(row_ndx));
}
if (value.is_type(type_List)) {
return ctx.box(get_list(row_ndx));
}
return ctx.box(value);
}
else {
return dispatch([&](auto t) {
return ctx.box(this->get<std::decay_t<decltype(*t)>>(row_ndx));
});
}
}

template <typename T, typename Context>
Expand Down
12 changes: 10 additions & 2 deletions src/realm/object-store/object_accessor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,16 @@ ValueType Object::get_property_value_impl(ContextType& ctx, const Property& prop
case PropertyType::UUID:
return is_nullable(property.type) ? ctx.box(m_obj.get<util::Optional<UUID>>(column))
: ctx.box(m_obj.get<UUID>(column));
case PropertyType::Mixed:
return ctx.box(m_obj.get<Mixed>(column));
case PropertyType::Mixed: {
Mixed value = m_obj.get<Mixed>(column);
if (value.is_type(type_Dictionary)) {
return ctx.box(object_store::Dictionary(m_realm, m_obj, column));
}
if (value.is_type(type_List)) {
return ctx.box(List(m_realm, m_obj, column));
}
return ctx.box(value);
}
case PropertyType::Object: {
auto linkObjectSchema = m_realm->schema().find(property.object_type);
auto linked = const_cast<Obj&>(m_obj).get_linked_object(column);
Expand Down
13 changes: 7 additions & 6 deletions test/object-store/dictionary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1369,9 +1369,10 @@ TEST_CASE("nested collection set by Object::create", "[dictionary]") {
auto obj = Object::create(ctx, r, *r->schema().find("DictionaryObject"), value);
r->commit_transaction();

object_store::Dictionary dict(obj, r->schema().find("DictionaryObject")->property_for_name("any"));
auto dict0 = dict.get_dictionary("0");
auto list1 = dict.get_list("1");
auto dict = util::any_cast<object_store::Dictionary&&>(obj.get_property_value<std::any>(ctx, "any"));

auto dict0 = util::any_cast<object_store::Dictionary&&>(dict.get(ctx, "0"));
auto list1 = util::any_cast<List&&>(dict.get(ctx, "1"));
auto dict2 = dict.get_dictionary("2");
CHECK(dict0.get_any("zero") == Mixed(0));
CHECK(list1.get_any(0) == Mixed("one"));
Expand Down Expand Up @@ -1422,8 +1423,8 @@ TEST_CASE("nested collection set by Object::create", "[dictionary]") {
r->begin_transaction();
Object::create(ctx, r, *r->schema().find("DictionaryObject"), value, CreatePolicy::UpdateModified);
r->commit_transaction();
List list(obj, r->schema().find("DictionaryObject")->property_for_name("any"));
dict0 = list.get_dictionary(0);
auto list = util::any_cast<List&&>(obj.get_property_value<std::any>(ctx, "any"));
dict0 = util::any_cast<object_store::Dictionary&&>(list.get(ctx, 0));
CHECK(dict0.get_any("zero") == Mixed(0));

SECTION("modify dictionary only") {
Expand All @@ -1443,7 +1444,7 @@ TEST_CASE("nested collection set by Object::create", "[dictionary]") {
r->begin_transaction();
Object::create(ctx, r, *r->schema().find("DictionaryObject"), new_value, CreatePolicy::UpdateModified);
r->commit_transaction();
auto list0 = list.get_list(0);
auto list0 = util::any_cast<List&&>(list.get(ctx, 0));
CHECK(list0.get_any(0) == Mixed("seven"));
CHECK(list0.get_any(1) == Mixed(7));
}
Expand Down
18 changes: 13 additions & 5 deletions test/object-store/primitive_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -803,29 +803,37 @@ TEMPLATE_TEST_CASE("primitive list", "[primitives]", cf::MixedVal, cf::Int, cf::
}
}

#if REALM_ENABLE_SYNC && REALM_HAVE_SYNC_STABLE_IDS
#if REALM_ENABLE_SYNC
SECTION("sync compatibility") {
if (!util::EventLoop::has_implementation())
return;

SyncServer server;
SyncTestFile sync_config(server, "shared");
sync_config.schema = config.schema;
TestSyncManager init_sync_manager({}, {false});
auto& server = init_sync_manager.sync_server();
SyncTestFile sync_config(init_sync_manager, "shared");
sync_config.schema = Schema{
{"object",
{{"value", PropertyType::Array | TestType::property_type},
{"_id", PropertyType::Int, Property::IsPrimary{true}}}},
};
sync_config.schema_version = 0;
server.start();

{
auto r = Realm::get_shared_realm(sync_config);
r->begin_transaction();

CppContext ctx(r);
auto obj = Object::create(ctx, r, *r->schema().find("object"), std::any(AnyDict{}));
auto obj = Object::create(ctx, r, *r->schema().find("object"), std::any(AnyDict{{"_id", INT64_C(5)}}));
auto list = util::any_cast<List>(obj.get_property_value<std::any>(ctx, "value"));
list.add(static_cast<T>(values[0]));

r->commit_transaction();
wait_for_upload(*r);
wait_for_download(*r);
}

std::this_thread::sleep_for(std::chrono::milliseconds(5));
util::File::remove(sync_config.path);

{
Expand Down

0 comments on commit f3563f3

Please sign in to comment.