8000 Api nested collections in OS by nicola-cab · Pull Request #6618 · realm/realm-core · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Api nested collections in OS #6618

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

Merged
merged 29 commits into from
May 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
3781bdd
Allow Lst<Mixed> to contain a collections
jedelbo May 4, 2023
38f3f0d
Update after review
jedelbo May 10, 2023
c1dc0c3
Merge branch 'next-major' of github.com:realm/realm-core into nc/api_…
nicola-cab May 11, 2023
e638686
Streamlining interface
jedelbo May 11, 2023
d92c0e1
draft interface for nesting a collection in Mixed
nicola-cab May 12, 2023
fa875b3
Virtual interface for getting nested collections
jedelbo May 13, 2023
655127f
merge new streamline interface
nicola-cab May 15, 2023
1fc1492
align to new streamline interface
nicola-cab May 15, 2023
be1bd2d
Fix compilation
jedelbo May 15, 2023
2bb37ac
tweak interface
nicola-cab May 15, 2023
bc5997f
Outline C-API for nested collections
jedelbo May 15, 2023
3c01b54
fix dictionary getter
nicola-cab May 15, 2023
b0a66db
removed not nedeed changes
nicola-cab May 15, 2023
50bdaf2
try to fix windows compilation error
nicola-cab May 15, 2023
971c4a1
Add Collection::set_collection
jedelbo May 15, 2023
18b7a86
code review
nicola-cab May 15, 2023
b2c4dbe
Merge branch 'je/streamline-interface' into nc/api_nested_collections
nicola-cab May 15, 2023
69814d7
Fix sanitizer error
jedelbo May 15, 2023
3f8f72f
c_api interface pick up basic implementation + adding list
nicola-cab May 15, 2023
c2ab7fa
get nested collection interface c api
nicola-cab May 15, 2023
ab8da70
Make CollectionParent::generate_key() threadsafe
jedelbo May 15, 2023
15dec9d
fix tests
nicola-cab May 15, 2023
6ad6055
format fixes
nicola-cab May 15, 2023
11d844a
Merge branch 'je/streamline-interface' of github.com:realm/realm-core…
nicola-cab May 15, 2023
da63eeb
format fixes
nicola-cab May 15, 2023
b0bd5ca
remove format file
nicola-cab May 15, 2023
085bc4e
Merge branch 'next-major' into nc/api_nested_collections
jedelbo May 16, 2023
81ef368
Small changes
jedelbo May 16, 2023
5a80501
Fix memory leak
jedelbo May 16, 2023
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
64 changes: 64 additions & 0 deletions src/realm.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ typedef enum realm_value_type {
RLM_TYPE_OBJECT_ID,
RLM_TYPE_LINK,
RLM_TYPE_UUID,
RLM_TYPE_LIST,
RLM_TYPE_SET,
RLM_TYPE_DICTIONARY,
} realm_value_type_e;

typedef enum realm_schema_validation_mode {
Expand Down Expand Up @@ -1635,6 +1638,12 @@ RLM_API bool realm_set_value(realm_object_t*, realm_property_key_t, realm_value_
*/
RLM_API realm_object_t* realm_set_embedded(realm_object_t*, realm_property_key_t);

/**
* Create a collection in a given Mixed property.
*
*/
RLM_API bool realm_set_collection(realm_object_t*, realm_property_key_t, realm_collection_type_e);

/** Return the object linked by the given property
*
* @return A non-NULL pointer if an object is found.
Expand Down Expand Up @@ -1776,6 +1785,44 @@ RLM_API bool realm_list_set(realm_list_t*, size_t index, realm_value_t value);
*/
RLM_API bool realm_list_insert(realm_list_t*, size_t index, realm_value_t value);

/**
* Insert a collection inside a list (only available for mixed properities)
*
* @param list valid ptr to a list where a nested collection needs to be added
* @param index position in the list where to add the collection
* @return RLM_API
*/
RLM_API bool realm_list_insert_collection(realm_list_t* list, size_t index, realm_collection_type_e);

/**
* Set a collection inside a list (only available for mixed properities).
* If the list already contains a collection of the requested type, the
* operation is idempotent.
*
* @param list valid ptr to a list where a nested collection needs to be set
* @param index position in the list where to set the collection
* @return RLM_API
*/
RLM_API bool realm_list_set_collection(realm_list_t* list, size_t index, realm_collection_type_e);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the main use case for this? Also, I noticed that I forgot to add an API for removing a collection... I'll push into another PR..


/**
* Returns a nested list if such collection exists, NULL otherwise.
*
* @param list pointer to the list that containes the nested list
* @param index index of collection in the list
* @return a pointer to the the nested list found at the index passed as argument
*/
RLM_API realm_list_t* realm_list_get_list(realm_list_t* list, size_t index);

/**
* Returns a nested dictionary if such collection exists, NULL otherwise.
*
* @param list pointer to the list that containes the nested collection into
* @param index position of collection in the list
* @return a pointer to the the nested dictionary found at index passed as argument
*/
RLM_API realm_dictionary_t* realm_list_get_dictionary(realm_list_t* list, size_t index);

/**
* Move the element at @a from_index to @a to_index.
*
Expand Down Expand Up @@ -2253,6 +2300,23 @@ RLM_API bool realm_dictionary_insert(realm_dictionary_t*, realm_value_t key, rea
*/
RLM_API realm_object_t* realm_dictionary_insert_embedded(realm_dictionary_t*, realm_value_t key);

/**
* Insert a nested collection
*/
RLM_API bool realm_dictionary_insert_collection(realm_dictionary_t*, realm_value_t key, realm_collection_type_e);

/**
* Fetch a list from a dictionary.
* @return a valid list that needs to be deleted by the caller or nullptr in case of an error.
*/
RLM_API realm_list_t* realm_dictionary_get_list(realm_dictionary_t* dictionary, realm_value_t key);

/**
* Fetch a dictioanry from a dictionary.
* @return a valid dictionary that needs to be deleted by the caller or nullptr in case of an error.
*/
RLM_API realm_dictionary_t* realm_dictionary_get_dictionary(realm_dictionary_t* dictionary, realm_value_t key);

/**
* Get object identified by key
*
Expand Down
34 changes: 33 additions & 1 deletion src/realm/object-store/c_api/conversion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ static inline Mixed from_capi(realm_value_t val)
return Mixed{ObjLink{TableKey(val.link.target_table), ObjKey(val.link.target)}};
case RLM_TYPE_UUID:
return Mixed{UUID{from_capi(val.uuid)}};
case RLM_TYPE_LIST:
return Mixed{0, CollectionType::List};
case RLM_TYPE_SET:
return Mixed{0, CollectionType::Set};
case RLM_TYPE_DICTIONARY:
return Mixed{0, CollectionType::Dictionary};
}
REALM_TERMINATE("Invalid realm_value_t"); // LCOV_EXCL_LINE
}
Expand All @@ -155,7 +161,8 @@ static inline realm_value_t to_capi(Mixed value)
val.type = RLM_TYPE_NULL;
}
else {
switch (value.get_type()) {
auto type = value.get_type();
switch (type) {
case type_Int: {
val.type = RLM_TYPE_INT;
val.integer = value.get<int64_t>();
Expand Down Expand Up @@ -221,6 +228,16 @@ static inline realm_value_t to_capi(Mixed value)
case type_LinkList:
case type_Mixed:
REALM_TERMINATE("Invalid Mixed value type"); // LCOV_EXCL_LINE
default:
if (type == type_List) {
val.type = RLM_TYPE_LIST;
}
else if (type == type_Set) {
val.type = RLM_TYPE_SET;
}
else if (type == type_Dictionary) {
val.type = RLM_TYPE_DICTIONARY;
}
}
}

Expand Down Expand Up @@ -418,6 +435,21 @@ static inline Property from_capi(const realm_property_info_t& p) noexcept
return prop;
}

static inline std::optional<CollectionType> from_capi(realm_collection_type_e type)
{
switch (type) {
case RLM_COLLECTION_TYPE_NONE:
break;
case RLM_COLLECTION_TYPE_LIST:
return CollectionType::List;
case RLM_COLLECTION_TYPE_SET:
return CollectionType::Set;
case RLM_COLLECTION_TYPE_DICTIONARY:
return CollectionType::Dictionary;
}
return {};
}

static inline realm_property_info_t to_capi(const Property& prop) noexcept
{
realm_property_info_t p;
Expand Down
39 changes: 39 additions & 0 deletions src/realm/object-store/c_api/dictionary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,45 @@ RLM_API realm_object_t* realm_dictionary_insert_embedded(realm_dictionary_t* dic
});
}

RLM_API bool realm_dictionary_insert_collection(realm_dictionary_t* dict, realm_value_t key,
realm_collection_type_e type)
{
return wrap_err([&]() {
if (key.type != RLM_TYPE_STRING) {
throw InvalidArgument{"Only string keys are supported in dictionaries"};
}

StringData k{key.string.data, key.string.size};
dict->insert_collection(k, *from_capi(type));
return true;
});
}


RLM_API realm_list_t* realm_dictionary_get_list(realm_dictionary_t* dictionary, realm_value_t key)
{
return wrap_err([&]() {
if (key.type != RLM_TYPE_STRING) {
throw InvalidArgument{"Only string keys are supported in dictionaries"};
}

StringData k{key.string.data, key.string.size};
return new realm_list_t{dictionary->get_list(k)};
});
}

RLM_API realm_dictionary_t* realm_dictionary_get_dictionary(realm_dictionary_t* dictionary, realm_value_t key)
{
return wrap_err([&]() {
if (key.type != RLM_TYPE_STRING) {
throw InvalidArgument{"Only string keys are supported in dictionaries"};
}

StringData k{key.string.data, key.string.size};
return new realm_dictionary_t{dictionary->get_dictionary(k)};
});
}

RLM_API realm_object_t* realm_dictionary_get_linked_object(realm_dictionary_t* dict, realm_value_t key)
{
return wrap_err([&]() {
Expand Down
31 changes: 31 additions & 0 deletions src/realm/object-store/c_api/list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,37 @@ RLM_API bool realm_list_insert(realm_list_t* list, size_t index, realm_value_t v
});
}

RLM_API bool realm_list_insert_collection(realm_list_t* list, size_t index, realm_collection_type_e type)
{
return wrap_err([&]() {
list->insert_collection(index, *from_capi(type));
return true;
});
}

RLM_API bool realm_list_set_collection(realm_list_t* list, size_t index, realm_collection_type_e type)
{
return wrap_err([&]() {
list->set_collection(index, *from_capi(type));
return true;
});
}


RLM_API realm_list_t* realm_list_get_list(realm_list_t* list, size_t index)
{
return wrap_err([&]() {
return new realm_list_t{list->get_list(index)};
});
}

RLM_API realm_dictionary_t* realm_list_get_dictionary(realm_list_t* list, size_t index)
{
return wrap_err([&]() {
return new realm_dictionary_t{list->get_dictionary(index)};
});
}

RLM_API bool realm_list_move(realm_list_t* list, size_t from_index, size_t to_index)
{
return wrap_err([&]() {
Expand Down
13 changes: 11 additions & 2 deletions src/realm/object-store/c_api/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,15 @@ RLM_API realm_object_t* realm_set_embedded(realm_object_t* obj, realm_property_k
});
}

RLM_API bool realm_set_collection(realm_object_t* obj, realm_property_key_t col, realm_collection_type_e type)
{
return wrap_err([&]() {
obj->verify_attached();
obj->obj().set_collection(ColKey(col), *from_capi(type));
return true;
});
}

RLM_API realm_object_t* realm_get_linked_object(realm_object_t* obj, realm_property_key_t col)
{
return wrap_err([&]() {
Expand All @@ -357,7 +366,7 @@ RLM_API realm_list_t* realm_get_list(realm_object_t* object, realm_property_key_
auto col_key = ColKey(key);
table->check_column(col_key);

if (!col_key.is_list()) {
if (!(col_key.is_list() || col_key.get_type() == col_type_Mixed)) {
report_type_mismatch(object->get_realm(), *table, col_key);
}

Expand Down Expand Up @@ -394,7 +403,7 @@ RLM_API realm_dictionary_t* realm_get_dictionary(realm_object_t* object, realm_p
auto col_key = ColKey(key);
table->check_column(col_key);

if (!col_key.is_dictionary()) {
if (!(col_key.is_dictionary() || col_key.get_type() == col_type_Mixed)) {
report_type_mismatch(object->get_realm(), *table, col_key);
}

Expand Down
6 changes: 6 additions & 0 deletions src/realm/object-store/c_api/query.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,12 @@ struct QueryArgumentsAdapter : query_parser::Arguments {
return type_Decimal;
case RLM_TYPE_UUID:
return type_UUID;
case RLM_TYPE_LIST:
return type_List;
case RLM_TYPE_SET:
return type_Set;
case RLM_TYPE_DICTIONARY:
return type_Dictionary;
}
throw LogicError{ErrorCodes::TypeMismatch, "Unsupported type"}; // LCOV_EXCL_LINE
return type_Int;
Expand Down
24 changes: 24 additions & 0 deletions src/realm/object-store/collection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <realm/object-store/object_store.hpp>
#include <realm/object-store/results.hpp>
#include <realm/object-store/shared_realm.hpp>
#include <realm/object-store/list.hpp>
#include <realm/object-store/dictionary.hpp>

namespace realm::object_store {

Expand Down Expand Up @@ -261,4 +263,26 @@ size_t Collection::hash() const noexcept
return hash_combine(impl.get_owner_key().value, impl.get_table()->get_key().value, impl.get_col_key().value);
}

void Collection::insert_collection(const PathElement& path, CollectionType type)
{
verify_in_transaction();
m_coll_base->insert_collection(path, type);
}

void Collection::set_collection(const PathElement& path, CollectionType type)
{
verify_in_transaction();
m_coll_base->set_collection(path, type);
}

List Collection::get_list(const PathElement& path) const
{
return List{m_realm, m_coll_base->get_list(path)};
}

Dictionary Collection::get_dictionary(const PathElement& path) const
{
return Dictionary{m_realm, m_coll_base->get_dictionary(path)};
}

} // namespace realm::object_store
8 changes: 8 additions & 0 deletions src/realm/object-store/collection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ namespace realm {
class Realm;
class Results;
class ObjectSchema;
class List;

namespace _impl {
class ListNotifier;
}

namespace object_store {
class Dictionary;
class Collection {
public:
Collection(PropertyType type) noexcept;
Expand Down Expand Up @@ -112,6 +114,12 @@ class Collection {
return *m_coll_base;
}

// nested collections
void insert_collection(const PathElement&, CollectionType);
void set_collection(const PathElement&, CollectionType);
List get_list(const PathElement&) const;
Dictionary get_dictionary(const PathElement&) const;

protected:
std::shared_ptr<Realm> m_realm;
PropertyType m_type;
Expand Down
2 changes: 1 addition & 1 deletion src/realm/object-store/property.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ inline Property::Property(std::string name, PropertyType type, const NestedTypes
, object_type(std::move(target_type))
, nested_types(nested_types)
{
REALM_ASSERT(is_collection(type));
REALM_ASSERT(is_collection(type) || is_mixed(type));
REALM_ASSERT((type == PropertyType::Object) == (object_type.size() != 0));
}

Expand Down
Loading
0