Skip to content
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

Actually store collection type in Mixed #6583

Merged
merged 4 commits into from
May 9, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
27 changes: 15 additions & 12 deletions src/realm/collection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,9 @@ std::pair<std::string, std::string> CollectionBase::get_open_close_strings(size_
{
std::string open_str;
std::string close_str;
auto ck = get_col_key();
auto collection_type = get_collection_type();
Table* target_table = get_target_table().unchecked_ptr();
auto ck = get_col_key();
auto type = ck.get_type();
if (type == col_type_LinkList)
type = col_type_Link;
Expand All @@ -107,29 +108,31 @@ std::pair<std::string, std::string> CollectionBase::get_open_close_strings(size_

if (output_mode == output_mode_xjson_plus) {
open_str = std::string("{ ") + (is_embedded ? "\"$embedded" : "\"$link");
open_str += collection_type_name(ck, true);
open_str += collection_type_name(collection_type, true);
open_str += "\": ";
close_str += " }";
}

if ((link_depth_reached && output_mode != output_mode_xjson) || output_mode == output_mode_xjson_plus) {
open_str += "{ \"table\": \"" + std::string(target_table->get_name()) + "\", ";
open_str += ((is_embedded || ck.is_dictionary()) ? "\"value" : "\"key");
if (ck.is_collection())
open_str += "s";
open_str += ((is_embedded || collection_type == CollectionType::Dictionary) ? "\"values" : "\"keys");
open_str += "\": ";
close_str += "}";
}
}
else {
if (output_mode == output_mode_xjson_plus) {
if (ck.is_set()) {
open_str = "{ \"$set\": ";
close_str = " }";
}
else if (ck.is_dictionary()) {
open_str = "{ \"$dictionary\": ";
close_str = " }";
switch (collection_type) {
case CollectionType::List:
break;
case CollectionType::Set:
open_str = "{ \"$set\": ";
close_str = " }";
break;
case CollectionType::Dictionary:
open_str = "{ \"$dictionary\": ";
close_str = " }";
break;
}
}
}
Expand Down
30 changes: 20 additions & 10 deletions src/realm/collection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ class CollectionBase : public Collection {
/// the internal state of the accessor if it has changed.
virtual bool has_changed() const noexcept = 0;

/// Get collection type (set, list, dictionary)
virtual CollectionType get_collection_type() const noexcept = 0;

/// Returns true if the accessor is in the attached state. By default, this
/// checks if the owning object is still valid.
virtual bool is_attached() const
Expand Down Expand Up @@ -154,21 +157,23 @@ class CollectionBase : public Collection {
std::pair<std::string, std::string> get_open_close_strings(size_t link_depth, JSONOutputMode output_mode) const;
};

inline std::string_view collection_type_name(ColKey col, bool uppercase = false)
inline std::string_view collection_type_name(CollectionType col_type, bool uppercase = false)
{
if (col.is_list())
return uppercase ? "List" : "list";
if (col.is_set())
return uppercase ? "Set" : "set";
if (col.is_dictionary())
return uppercase ? "Dictionary" : "dictionary";
switch (col_type) {
case CollectionType::List:
return uppercase ? "List" : "list";
case CollectionType::Set:
return uppercase ? "Set" : "set";
case CollectionType::Dictionary:
return uppercase ? "Dictionary" : "dictionary";
}
return "";
}

inline void CollectionBase::validate_index(const char* msg, size_t index, size_t size) const
{
if (index >= size) {
throw OutOfBounds(util::format("%1 on %2 '%3.%4'", msg, collection_type_name(get_col_key()),
throw OutOfBounds(util::format("%1 on %2 '%3.%4'", msg, collection_type_name(get_collection_type()),
get_table()->get_class_name(), get_property_name()),
index, size);
}
Expand Down Expand Up @@ -382,6 +387,11 @@ class CollectionBaseImpl : public Interface, protected ArrayParent {
return false;
}

CollectionType get_collection_type() const noexcept override
{
return Interface::s_collection_type;
}

void set_owner(const Obj& obj, ColKey ck) override
{
m_obj_mem = obj;
Expand Down Expand Up @@ -471,7 +481,7 @@ class CollectionBaseImpl : public Interface, protected ArrayParent {
ref_type get_collection_ref() const noexcept
{
try {
return m_parent->get_collection_ref(m_index);
return m_parent->get_collection_ref(m_index, Interface::s_collection_type);
}
catch (const KeyNotFound&) {
return ref_type(0);
Expand All @@ -480,7 +490,7 @@ class CollectionBaseImpl : public Interface, protected ArrayParent {

void set_collection_ref(ref_type ref)
{
m_parent->set_collection_ref(m_index, ref);
m_parent->set_collection_ref(m_index, ref, Interface::s_collection_type);
}

UpdateStatus get_update_status() const noexcept
Expand Down
44 changes: 22 additions & 22 deletions src/realm/collection_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ CollectionList::CollectionList(std::shared_ptr<CollectionParent> parent, ColKey
, m_col_key(col_key)
, m_top(*m_alloc)
, m_refs(*m_alloc)
, m_key_type(coll_type == CollectionType::List ? type_Int : type_String)
, m_coll_type(coll_type)
{
m_top.set_parent(this, 0);
m_refs.set_parent(&m_top, 1);
Expand All @@ -51,7 +51,7 @@ CollectionList::CollectionList(CollectionParent* obj, ColKey col_key)
, m_col_key(col_key)
, m_top(*m_alloc)
, m_refs(*m_alloc)
, m_key_type(get_table()->get_nested_column_type(col_key, 0) == CollectionType::List ? type_Int : type_String)
, m_coll_type(get_table()->get_nested_column_type(col_key, 0))
{
m_top.set_parent(this, 0);
m_refs.set_parent(&m_top, 1);
Expand All @@ -61,14 +61,14 @@ CollectionList::~CollectionList() {}

bool CollectionList::init_from_parent(bool allow_create) const
{
auto ref = m_parent->get_collection_ref(m_index);
auto ref = m_parent->get_collection_ref(m_index, m_coll_type);
if ((ref || allow_create) && !m_keys) {
switch (m_key_type) {
case type_String: {
switch (m_coll_type) {
case CollectionType::Dictionary: {
m_keys.reset(new BPlusTree<StringData>(*m_alloc));
break;
}
case type_Int: {
case CollectionType::List: {
m_keys.reset(new BPlusTree<Int>(*m_alloc));
break;
}
Expand Down Expand Up @@ -170,19 +170,19 @@ bool CollectionList::update_if_needed() const

ref_type CollectionList::get_child_ref(size_t) const noexcept
{
return m_parent->get_collection_ref(m_col_key);
return m_parent->get_collection_ref(m_col_key, m_coll_type);
}

void CollectionList::update_child_ref(size_t, ref_type ref)
{
m_parent->set_collection_ref(m_index, ref);
m_parent->set_collection_ref(m_index, ref, m_coll_type);
}

CollectionBasePtr CollectionList::insert_collection(size_t ndx)
{
REALM_ASSERT(get_table()->get_nesting_levels(m_col_key) == m_level);
ensure_created();
REALM_ASSERT(m_key_type == type_Int);
REALM_ASSERT(m_coll_type == CollectionType::List);
auto int_keys = static_cast<BPlusTree<Int>*>(m_keys.get());
int64_t key = 0;
if (auto max = bptree_maximum(*int_keys, nullptr)) {
Expand All @@ -202,7 +202,7 @@ CollectionBasePtr CollectionList::insert_collection(StringData key)
{
REALM_ASSERT(get_table()->get_nesting_levels(m_col_key) == m_level);
ensure_created();
REALM_ASSERT(m_key_type == type_String);
REALM_ASSERT(m_coll_type == CollectionType::Dictionary);
auto string_keys = static_cast<BPlusTree<String>*>(m_keys.get());
StringData actual;
IteratorAdapter help(string_keys);
Expand Down Expand Up @@ -231,7 +231,7 @@ CollectionBasePtr CollectionList::get_collection(size_t ndx) const
if (ndx >= sz) {
throw OutOfBounds("CollectionList::get_collection_ptr()", ndx, sz);
}
if (m_key_type == type_Int) {
if (m_coll_type == CollectionType::List) {
auto int_keys = static_cast<BPlusTree<Int>*>(m_keys.get());
index = int_keys->get(ndx);
}
Expand All @@ -246,7 +246,7 @@ CollectionBasePtr CollectionList::get_collection(size_t ndx) const
CollectionListPtr CollectionList::insert_collection_list(size_t ndx)
{
ensure_created();
REALM_ASSERT(m_key_type == type_Int);
REALM_ASSERT(m_coll_type == CollectionType::List);
auto int_keys = static_cast<BPlusTree<Int>*>(m_keys.get());
int64_t key = 0;
if (auto max = bptree_maximum(*int_keys, nullptr)) {
Expand All @@ -263,7 +263,7 @@ CollectionListPtr CollectionList::insert_collection_list(size_t ndx)
CollectionListPtr CollectionList::insert_collection_list(StringData key)
{
ensure_created();
REALM_ASSERT(m_key_type == type_String);
REALM_ASSERT(m_coll_type == CollectionType::Dictionary);
auto string_keys = static_cast<BPlusTree<String>*>(m_keys.get());
StringData actual;
IteratorAdapter help(string_keys);
Expand All @@ -289,7 +289,7 @@ CollectionListPtr CollectionList::get_collection_list(size_t ndx) const
if (ndx >= sz) {
throw OutOfBounds("CollectionList::get_collection_ptr()", ndx, sz);
}
if (m_key_type == type_Int) {
if (m_coll_type == CollectionType::List) {
auto int_keys = static_cast<BPlusTree<Int>*>(m_keys.get());
index = int_keys->get(ndx);
}
Expand All @@ -303,7 +303,7 @@ CollectionListPtr CollectionList::get_collection_list(size_t ndx) const

void CollectionList::remove(size_t ndx)
{
REALM_ASSERT(m_key_type == type_Int);
REALM_ASSERT(m_coll_type == CollectionType::List);
auto int_keys = static_cast<BPlusTree<Int>*>(m_keys.get());
const auto sz = int_keys->size();
if (ndx >= sz) {
Expand Down Expand Up @@ -331,7 +331,7 @@ void CollectionList::remove(size_t ndx)

void CollectionList::remove(StringData key)
{
REALM_ASSERT(m_key_type == type_String);
REALM_ASSERT(m_coll_type == CollectionType::Dictionary);
auto string_keys = static_cast<BPlusTree<String>*>(m_keys.get());
IteratorAdapter help(string_keys);
auto it = std::lower_bound(help.begin(), help.end(), key);
Expand All @@ -347,10 +347,10 @@ void CollectionList::remove(StringData key)
bump_content_version();
}

ref_type CollectionList::get_collection_ref(Index index) const noexcept
ref_type CollectionList::get_collection_ref(Index index, CollectionType) const noexcept
{
size_t ndx;
if (m_key_type == type_Int) {
if (m_coll_type == CollectionType::List) {
auto int_keys = static_cast<BPlusTree<Int>*>(m_keys.get());
ndx = int_keys->find_first(mpark::get<int64_t>(index));
}
Expand All @@ -361,10 +361,10 @@ ref_type CollectionList::get_collection_ref(Index index) const noexcept
return ndx == realm::not_found ? 0 : m_refs.get(ndx);
}

void CollectionList::set_collection_ref(Index index, ref_type ref)
void CollectionList::set_collection_ref(Index index, ref_type ref, CollectionType)
{
size_t ndx;
if (m_key_type == type_Int) {
if (m_coll_type == CollectionType::List) {
auto int_keys = static_cast<BPlusTree<Int>*>(m_keys.get());
ndx = int_keys->find_first(mpark::get<int64_t>(index));
}
Expand All @@ -380,7 +380,7 @@ void CollectionList::set_collection_ref(Index index, ref_type ref)

auto CollectionList::get_index(size_t ndx) const noexcept -> Index
{
if (m_key_type == type_Int) {
if (m_coll_type == CollectionType::List) {
auto int_keys = static_cast<BPlusTree<Int>*>(m_keys.get());
return int_keys->get(ndx);
}
Expand Down Expand Up @@ -431,7 +431,7 @@ void CollectionList::to_json(std::ostream& out, size_t link_depth, JSONOutputMod
util::FunctionRef<void(const Mixed&)> fn) const
{
bool is_leaf = m_level == get_table()->get_nesting_levels(m_col_key);
bool is_dictionary = m_key_type == type_String;
bool is_dictionary = m_coll_type == CollectionType::Dictionary;
auto sz = size();
auto string_keys = static_cast<BPlusTree<String>*>(m_keys.get());

Expand Down
6 changes: 3 additions & 3 deletions src/realm/collection_list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ class CollectionList final : public Collection,

Index get_index(size_t ndx) const noexcept;

ref_type get_collection_ref(Index index) const noexcept final;
void set_collection_ref(Index index, ref_type ref) final;
ref_type get_collection_ref(Index index, CollectionType) const noexcept final;
void set_collection_ref(Index index, ref_type ref, CollectionType) final;

// If this list is at the outermost nesting level, use these functions to
// get the leaf collections
Expand Down Expand Up @@ -112,7 +112,7 @@ class CollectionList final : public Collection,
mutable Array m_top;
mutable std::unique_ptr<BPlusTreeBase> m_keys;
mutable BPlusTree<ref_type> m_refs;
DataType m_key_type;
CollectionType m_coll_type;
mutable uint_fast64_t m_content_version = 0;


Expand Down
10 changes: 5 additions & 5 deletions src/realm/collection_parent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,9 @@ class CollectionParent {
/// Get owning object
virtual const Obj& get_object() const noexcept = 0;
/// Get the top ref from pareht
virtual ref_type get_collection_ref(Index) const noexcept = 0;
/// Set the top ref from pareht
virtual void set_collection_ref(Index, ref_type ref) = 0;
virtual ref_type get_collection_ref(Index, CollectionType) const = 0;
/// Set the top ref in parent
virtual void set_collection_ref(Index, ref_type ref, CollectionType) = 0;

// Used when inserting a new link. You will not remove existing links in this process
void set_backlink(ColKey col_key, ObjLink new_link) const;
Expand Down Expand Up @@ -145,11 +145,11 @@ class DummyParent : public CollectionParent {
return true;
}
const Obj& get_object() const noexcept final;
ref_type get_collection_ref(Index) const noexcept final
ref_type get_collection_ref(Index, CollectionType) const final
{
return m_ref;
}
void set_collection_ref(Index, ref_type) {}
void set_collection_ref(Index, ref_type, CollectionType) {}
};

} // namespace realm
Expand Down
4 changes: 4 additions & 0 deletions src/realm/dictionary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,10 @@ class DictionaryLinkValues final : public ObjCollectionBase<CollectionBase> {
{
return m_source.has_changed();
}
CollectionType get_collection_type() const noexcept override
{
return CollectionType::List;
}

// Overrides of ObjCollectionBase:
UpdateStatus do_update_if_needed() const final
Expand Down
5 changes: 5 additions & 0 deletions src/realm/list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class LstBase : public CollectionBase {
virtual void swap(size_t ndx1, size_t ndx2) = 0;

protected:
static constexpr CollectionType s_collection_type = CollectionType::List;
Copy link
Member

@nicola-cab nicola-cab May 8, 2023

Choose a reason for hiding this comment

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

Why not to have a CollectionBase::collection_type variable and let the implementor set that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we can replace a variable with a constant, that is better.

void swap_repl(Replication* repl, size_t ndx1, size_t ndx2) const;
};

Expand Down Expand Up @@ -399,6 +400,10 @@ class LnkLst final : public ObjCollectionBase<LstBase> {
const Obj& get_obj() const noexcept final;
bool has_changed() const noexcept final;
ColKey get_col_key() const noexcept final;
CollectionType get_collection_type() const noexcept override
{
return CollectionType::List;
}

// Overriding members of LstBase:
std::unique_ptr<LstBase> clone() const override
Expand Down
Loading