From cb6fbc9c461bcb2bd65f8847f4c753226a05405b Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Wed, 28 Feb 2024 19:56:39 -0800 Subject: [PATCH] Make Obj trivial and add a separate ObjCollectionParent type --- src/realm/collection.hpp | 8 +- src/realm/collection_parent.cpp | 282 +++++++++------------- src/realm/collection_parent.hpp | 31 +-- src/realm/obj.cpp | 32 +-- src/realm/obj.hpp | 97 ++++++-- src/realm/parser/generated/query_flex.cpp | 31 +-- src/realm/parser/generated/query_flex.hpp | 7 +- src/realm/path.hpp | 39 ++- src/realm/replication.cpp | 2 +- src/realm/set.hpp | 2 +- test/test_parser.cpp | 4 +- 11 files changed, 268 insertions(+), 267 deletions(-) diff --git a/src/realm/collection.hpp b/src/realm/collection.hpp index f2b5c8f56c7..efc1a273d31 100644 --- a/src/realm/collection.hpp +++ b/src/realm/collection.hpp @@ -577,7 +577,7 @@ class CollectionBaseImpl : public Interface, protected ArrayParent { using Interface::get_target_table; protected: - Obj m_obj_mem; + ObjCollectionParent m_obj_mem; std::shared_ptr m_col_parent; CollectionParent::Index m_index; mutable size_t m_my_version = 0; @@ -735,19 +735,19 @@ class CollectionBaseImpl : public Interface, protected ArrayParent { void set_backlink(ColKey col_key, ObjLink new_link) const { check_parent(); - m_parent->set_backlink(col_key, new_link); + m_parent->set_backlink(m_parent->get_object(), col_key, new_link); } // Used when replacing a link, return true if CascadeState contains objects to remove bool replace_backlink(ColKey col_key, ObjLink old_link, ObjLink new_link, CascadeState& state) const { check_parent(); - return m_parent->replace_backlink(col_key, old_link, new_link, state); + return m_parent->replace_backlink(m_parent->get_object(), col_key, old_link, new_link, state); } // Used when removing a backlink, return true if CascadeState contains objects to remove bool remove_backlink(ColKey col_key, ObjLink old_link, CascadeState& state) const { check_parent(); - return m_parent->remove_backlink(col_key, old_link, state); + return m_parent->remove_backlink(m_parent->get_object(), col_key, old_link, state); } /// Reset the accessor's tracking of the content version. Derived classes diff --git a/src/realm/collection_parent.cpp b/src/realm/collection_parent.cpp index b54ac869e25..f71654d81bc 100644 --- a/src/realm/collection_parent.cpp +++ b/src/realm/collection_parent.cpp @@ -66,14 +66,7 @@ bool StablePath::is_prefix_of(const StablePath& other) const noexcept { if (size() > other.size()) return false; - - auto it = other.begin(); - for (auto& p : *this) { - if (!(p == *it)) - return false; - ++it; - } - return true; + return std::equal(other.begin(), other.end(), begin()); } /***************************** CollectionParent ******************************/ @@ -86,212 +79,157 @@ void CollectionParent::check_level() const throw LogicError(ErrorCodes::LimitExceeded, "Max nesting level reached"); } } -void CollectionParent::set_backlink(ColKey col_key, ObjLink new_link) const +void CollectionParent::set_backlink(const Obj& obj, ColKey col_key, ObjLink new_link) { - if (new_link && new_link.get_obj_key()) { - auto t = get_table(); - auto target_table = t->get_parent_group()->get_table(new_link.get_table_key()); - ColKey backlink_col_key; - auto type = col_key.get_type(); - if (type == col_type_TypedLink || type == col_type_Mixed || col_key.is_dictionary()) { - // This may modify the target table - backlink_col_key = target_table->find_or_add_backlink_column(col_key, t->get_key()); - // it is possible that this was a link to the same table and that adding a backlink column has - // caused the need to update this object as well. - update_if_needed(); - } - else { - backlink_col_key = t->get_opposite_column(col_key); - } - auto obj_key = new_link.get_obj_key(); - auto target_obj = obj_key.is_unresolved() ? target_table->try_get_tombstone(obj_key) - : target_table->try_get_object(obj_key); - if (!target_obj) { - throw InvalidArgument(ErrorCodes::KeyNotFound, "Target object not found"); - } - target_obj.add_backlink(backlink_col_key, get_object().get_key()); + if (!new_link) { + return; } + + auto t = obj.get_table(); + auto target_table = t->get_parent_group()->get_table(new_link.get_table_key()); + ColKey backlink_col_key; + auto type = col_key.get_type(); + if (type == col_type_TypedLink || type == col_type_Mixed || col_key.is_dictionary()) { + // This may modify the target table + backlink_col_key = target_table->find_or_add_backlink_column(col_key, t->get_key()); + // it is possible that this was a link to the same table and that adding a backlink column has + // caused the need to update this object as well. + obj.update_if_needed(); + } + else { + backlink_col_key = t->get_opposite_column(col_key); + } + auto obj_key = new_link.get_obj_key(); + auto target_obj = + obj_key.is_unresolved() ? target_table->try_get_tombstone(obj_key) : target_table->try_get_object(obj_key); + if (!target_obj) { + throw InvalidArgument(ErrorCodes::KeyNotFound, "Target object not found"); + } + target_obj.add_backlink(backlink_col_key, obj.get_key()); } -bool CollectionParent::replace_backlink(ColKey col_key, ObjLink old_link, ObjLink new_link, CascadeState& state) const +bool CollectionParent::replace_backlink(const Obj& obj, ColKey col_key, ObjLink old_link, ObjLink new_link, + CascadeState& state) { - bool recurse = remove_backlink(col_key, old_link, state); - set_backlink(col_key, new_link); - + bool recurse = remove_backlink(obj, col_key, old_link, state); + set_backlink(obj, col_key, new_link); return recurse; } -bool CollectionParent::remove_backlink(ColKey col_key, ObjLink old_link, CascadeState& state) const +bool CollectionParent::remove_backlink(const Obj& obj, ColKey col_key, ObjLink old_link, CascadeState& state) { - if (old_link && old_link.get_obj_key()) { - auto t = get_table(); - REALM_ASSERT(t->valid_column(col_key)); - ObjKey old_key = old_link.get_obj_key(); - auto target_obj = t->get_parent_group()->get_object(old_link); - TableRef target_table = target_obj.get_table(); - ColKey backlink_col_key; - auto type = col_key.get_type(); - if (type == col_type_TypedLink || type == col_type_Mixed || col_key.is_dictionary()) { - backlink_col_key = target_table->find_or_add_backlink_column(col_key, t->get_key()); - } - else { - backlink_col_key = t->get_opposite_column(col_key); - } + if (!old_link) { + return false; + } - bool strong_links = target_table->is_embedded(); - bool is_unres = old_key.is_unresolved(); + auto t = obj.get_table(); + REALM_ASSERT(t->valid_column(col_key)); + ObjKey old_key = old_link.get_obj_key(); + auto target_obj = t->get_parent_group()->get_object(old_link); + TableRef target_table = target_obj.get_table(); + ColKey backlink_col_key; + auto type = col_key.get_type(); + if (type == col_type_TypedLink || type == col_type_Mixed || col_key.is_dictionary()) { + backlink_col_key = target_table->find_or_add_backlink_column(col_key, t->get_key()); + } + else { + backlink_col_key = t->get_opposite_column(col_key); + } - bool last_removed = target_obj.remove_one_backlink(backlink_col_key, get_object().get_key()); // Throws - if (is_unres) { - if (last_removed) { - // Check is there are more backlinks - if (!target_obj.has_backlinks(false)) { - // Tombstones can be erased right away - there is no cascading effect - target_table->m_tombstones->erase(old_key, state); - } + bool strong_links = target_table->is_embedded(); + bool is_unres = old_key.is_unresolved(); + + bool last_removed = target_obj.remove_one_backlink(backlink_col_key, obj.get_key()); // Throws + if (is_unres) { + if (last_removed) { + // Check is there are more backlinks + if (!target_obj.has_backlinks(false)) { + // Tombstones can be erased right away - there is no cascading effect + target_table->m_tombstones->erase(old_key, state); } } - else { - return state.enqueue_for_cascade(target_obj, strong_links, last_removed); - } + } + else { + return state.enqueue_for_cascade(target_obj, strong_links, last_removed); } return false; } -LstBasePtr CollectionParent::get_listbase_ptr(ColKey col_key) const +template typename Collection, typename LinkCol> +std::unique_ptr create_collection(ColKey col_key, size_t level) { - auto table = get_table(); - auto attr = table->get_column_attr(col_key); - REALM_ASSERT(attr.test(col_attr_List) || attr.test(col_attr_Nullable)); - bool nullable = attr.test(col_attr_Nullable); - - switch (table->get_column_type(col_key)) { - case type_Int: { + bool nullable = col_key.get_attrs().test(col_attr_Nullable); + switch (col_key.get_type()) { + case col_type_Int: if (nullable) - return std::make_unique>>(col_key); - else - return std::make_unique>(col_key); - } - case type_Bool: { + return std::make_unique>>(col_key); + return std::make_unique>(col_key); + case col_type_Bool: if (nullable) - return std::make_unique>>(col_key); - else - return std::make_unique>(col_key); - } - case type_Float: { + return std::make_unique>>(col_key); + return std::make_unique>(col_key); + case col_type_Float: if (nullable) - return std::make_unique>>(col_key); - else - return std::make_unique>(col_key); - } - case type_Double: { + return std::make_unique>>(col_key); + return std::make_unique>(col_key); + case col_type_Double: if (nullable) - return std::make_unique>>(col_key); - else - return std::make_unique>(col_key); - } - case type_String: { - return std::make_unique>(col_key); - } - case type_Binary: { - return std::make_unique>(col_key); - } - case type_Timestamp: { - return std::make_unique>(col_key); - } - case type_Decimal: { - return std::make_unique>(col_key); - } - case type_ObjectId: { + return std::make_unique>>(col_key); + return std::make_unique>(col_key); + case col_type_String: + return std::make_unique>(col_key); + case col_type_Binary: + return std::make_unique>(col_key); + case col_type_Timestamp: + return std::make_unique>(col_key); + case col_type_Decimal: + return std::make_unique>(col_key); + case col_type_ObjectId: if (nullable) - return std::make_unique>>(col_key); - else - return std::make_unique>(col_key); - } - case type_UUID: { + return std::make_unique>>(col_key); + return std::make_unique>(col_key); + case col_type_UUID: if (nullable) - return std::make_unique>>(col_key); - else - return std::make_unique>(col_key); - } - case type_TypedLink: { - return std::make_unique>(col_key); - } - case type_Mixed: { - return std::make_unique>(col_key, get_level() + 1); - } - case type_Link: - return std::make_unique(col_key); + return std::make_unique>>(col_key); + return std::make_unique>(col_key); + case col_type_TypedLink: + return std::make_unique>(col_key); + case col_type_Mixed: + return std::make_unique>(col_key, level + 1); + case col_type_Link: + return std::make_unique(col_key); + default: + REALM_TERMINATE("Unsupported column type."); } - REALM_TERMINATE("Unsupported column type"); } -SetBasePtr CollectionParent::get_setbase_ptr(ColKey col_key) const +LstBasePtr CollectionParent::get_listbase_ptr(ColKey col_key, size_t level) { - auto table = get_table(); - auto attr = table->get_column_attr(col_key); - REALM_ASSERT(attr.test(col_attr_Set)); - bool nullable = attr.test(col_attr_Nullable); + REALM_ASSERT(col_key.get_attrs().test(col_attr_List) || col_key.get_type() == col_type_Mixed); + return create_collection(col_key, level); +} - switch (table->get_column_type(col_key)) { - case type_Int: - if (nullable) - return std::make_unique>>(col_key); - return std::make_unique>(col_key); - case type_Bool: - if (nullable) - return std::make_unique>>(col_key); - return std::make_unique>(col_key); - case type_Float: - if (nullable) - return std::make_unique>>(col_key); - return std::make_unique>(col_key); - case type_Double: - if (nullable) - return std::make_unique>>(col_key); - return std::make_unique>(col_key); - case type_String: - return std::make_unique>(col_key); - case type_Binary: - return std::make_unique>(col_key); - case type_Timestamp: - return std::make_unique>(col_key); - case type_Decimal: - return std::make_unique>(col_key); - case type_ObjectId: - if (nullable) - return std::make_unique>>(col_key); - return std::make_unique>(col_key); - case type_UUID: - if (nullable) - return std::make_unique>>(col_key); - return std::make_unique>(col_key); - case type_TypedLink: - return std::make_unique>(col_key); - case type_Mixed: - return std::make_unique>(col_key); - case type_Link: - return std::make_unique(col_key); - } - REALM_TERMINATE("Unsupported column type."); +SetBasePtr CollectionParent::get_setbase_ptr(ColKey col_key, size_t level) +{ + REALM_ASSERT(col_key.get_attrs().test(col_attr_Set)); + return create_collection(col_key, level); } -CollectionBasePtr CollectionParent::get_collection_ptr(ColKey col_key) const +CollectionBasePtr CollectionParent::get_collection_ptr(ColKey col_key, size_t level) { if (col_key.is_list()) { - return get_listbase_ptr(col_key); + return get_listbase_ptr(col_key, level); } else if (col_key.is_set()) { - return get_setbase_ptr(col_key); + return get_setbase_ptr(col_key, level); } else if (col_key.is_dictionary()) { - return std::make_unique(col_key, get_level() + 1); + return std::make_unique(col_key, level + 1); } return {}; } - int64_t CollectionParent::generate_key(size_t sz) { static std::mt19937 gen32; diff --git a/src/realm/collection_parent.hpp b/src/realm/collection_parent.hpp index d7a6f9d1e06..e8e4694629d 100644 --- a/src/realm/collection_parent.hpp +++ b/src/realm/collection_parent.hpp @@ -20,9 +20,9 @@ #define REALM_COLLECTION_PARENT_HPP #include -#include -#include #include +#include +#include namespace realm { @@ -95,6 +95,20 @@ class CollectionParent : public std::enable_shared_from_this { /// Get table of owning object virtual TableRef get_table() const noexcept = 0; + static LstBasePtr get_listbase_ptr(ColKey col_key, size_t level); + static SetBasePtr get_setbase_ptr(ColKey col_key, size_t level); + static CollectionBasePtr get_collection_ptr(ColKey col_key, size_t level); + + // Used when inserting a new link. You will not remove existing links in this process + static void set_backlink(const Obj&, ColKey col_key, ObjLink new_link); + // Used when replacing a link, return true if CascadeState contains objects to remove + static bool replace_backlink(const Obj& obj, ColKey col_key, ObjLink old_link, ObjLink new_link, + CascadeState& state); + // Used when removing a backlink, return true if CascadeState contains objects to remove + static bool remove_backlink(const Obj& obj, ColKey col_key, ObjLink old_link, CascadeState& state); + + static int64_t generate_key(size_t sz); + protected: friend class Collection; template @@ -132,19 +146,6 @@ class CollectionParent : public std::enable_shared_from_this { } /// 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; - // Used when replacing a link, return true if CascadeState contains objects to remove - bool replace_backlink(ColKey col_key, ObjLink old_link, ObjLink new_link, CascadeState& state) const; - // Used when removing a backlink, return true if CascadeState contains objects to remove - bool remove_backlink(ColKey col_key, ObjLink old_link, CascadeState& state) const; - - LstBasePtr get_listbase_ptr(ColKey col_key) const; - SetBasePtr get_setbase_ptr(ColKey col_key) const; - CollectionBasePtr get_collection_ptr(ColKey col_key) const; - - static int64_t generate_key(size_t sz); }; } // namespace realm diff --git a/src/realm/obj.cpp b/src/realm/obj.cpp index 4d482988076..657bd8af624 100644 --- a/src/realm/obj.cpp +++ b/src/realm/obj.cpp @@ -385,7 +385,6 @@ bool Obj::update() const if (changes) { m_mem = new_obj.m_mem; m_row_ndx = new_obj.m_row_ndx; - CollectionParent::m_parent_version++; } // Always update versions m_storage_version = new_obj.m_storage_version; @@ -423,7 +422,6 @@ UpdateStatus Obj::update_if_needed_with_status() const if ((m_mem.get_addr() != state.mem.get_addr()) || (m_row_ndx != state.index)) { m_mem = state.mem; m_row_ndx = state.index; - CollectionParent::m_parent_version++; return UpdateStatus::Updated; } } @@ -1099,7 +1097,7 @@ StablePath Obj::get_stable_path() const noexcept return {}; } -void Obj::add_index(Path& path, const Index& index) const +void Obj::add_index(Path& path, const CollectionParent::Index& index) const { if (path.empty()) { path.emplace_back(get_table()->get_column_key(index)); @@ -1173,7 +1171,7 @@ Obj& Obj::set(ColKey col_key, Mixed value, bool is_default) return *this; } auto old_link = old_value.get(); - recurse = remove_backlink(col_key, old_link, state); + recurse = CollectionParent::remove_backlink(*this, col_key, old_link, state); } else if (old_value.is_type(type_Dictionary)) { Dictionary dict(*this, col_key); @@ -1190,7 +1188,7 @@ Obj& Obj::set(ColKey col_key, Mixed value, bool is_default) } auto new_link = value.get(); m_table->get_parent_group()->validate(new_link); - set_backlink(col_key, new_link); + CollectionParent::set_backlink(*this, col_key, new_link); } SearchIndex* index = m_table->get_search_index(col_key); @@ -1429,7 +1427,8 @@ Obj& Obj::set(ColKey col_key, ObjKey target_key, bool is_default) if (target_key != old_key) { CascadeState state(CascadeState::Mode::Strong); - bool recurse = replace_backlink(col_key, {target_table_key, old_key}, {target_table_key, target_key}, state); + bool recurse = CollectionParent::replace_backlink(*this, col_key, {target_table_key, old_key}, + {target_table_key, target_key}, state); _update_if_needed(); Allocator& alloc = get_alloc(); @@ -1474,7 +1473,7 @@ Obj& Obj::set(ColKey col_key, ObjLink target_link, bool is_default) CascadeState state(old_link.get_obj_key().is_unresolved() ? CascadeState::Mode::All : CascadeState::Mode::Strong); - bool recurse = replace_backlink(col_key, old_link, target_link, state); + bool recurse = CollectionParent::replace_backlink(*this, col_key, old_link, target_link, state); _update_if_needed(); Allocator& alloc = get_alloc(); @@ -1536,7 +1535,8 @@ Obj Obj::create_and_set_linked_object(ColKey col_key, bool is_default) if (target_key != old_key) { CascadeState state; - bool recurse = replace_backlink(col_key, {target_table_key, old_key}, {target_table_key, target_key}, state); + bool recurse = CollectionParent::replace_backlink(*this, col_key, {target_table_key, old_key}, + {target_table_key, target_key}, state); _update_if_needed(); Allocator& alloc = get_alloc(); @@ -1957,14 +1957,14 @@ void Obj::handle_multiple_backlinks_during_schema_migration() LstBasePtr Obj::get_listbase_ptr(ColKey col_key) const { - auto list = CollectionParent::get_listbase_ptr(col_key); + auto list = CollectionParent::get_listbase_ptr(col_key, 0); list->set_owner(*this, col_key); return list; } SetBasePtr Obj::get_setbase_ptr(ColKey col_key) const { - auto set = CollectionParent::get_setbase_ptr(col_key); + auto set = CollectionParent::get_setbase_ptr(col_key, 0); set->set_owner(*this, col_key); return set; } @@ -1994,7 +1994,7 @@ Obj& Obj::set_collection(ColKey col_key, CollectionType type) if (old_val != new_val) { CascadeState state; if (old_val.is_type(type_TypedLink)) { - remove_backlink(col_key, old_val.get(), state); + CollectionParent::remove_backlink(*this, col_key, old_val.get(), state); } else if (old_val.is_type(type_Dictionary)) { Dictionary dict(*this, col_key); @@ -2019,7 +2019,7 @@ Obj& Obj::set_collection(ColKey col_key, CollectionType type) values.init_from_parent(); values.set(m_row_ndx, new_val); - values.set_key(m_row_ndx, generate_key(0x10)); + values.set_key(m_row_ndx, CollectionParent::generate_key(0x10)); sync(fields); @@ -2127,7 +2127,7 @@ CollectionPtr Obj::get_collection_by_stable_path(const StablePath& path) const CollectionBasePtr Obj::get_collection_ptr(ColKey col_key) const { if (col_key.is_collection()) { - auto collection = CollectionParent::get_collection_ptr(col_key); + auto collection = CollectionParent::get_collection_ptr(col_key, 0); collection->set_owner(*this, col_key); return collection; } @@ -2427,7 +2427,7 @@ ref_type Obj::Internal::get_ref(const Obj& obj, ColKey col_key) return to_ref(obj._get(col_key.get_index())); } -ref_type Obj::get_collection_ref(Index index, CollectionType type) const +ref_type Obj::get_collection_ref(StableIndex index, CollectionType type) const { if (index.is_collection()) { return to_ref(_get(index.get_index())); @@ -2442,7 +2442,7 @@ ref_type Obj::get_collection_ref(Index index, CollectionType type) const throw StaleAccessor("This collection is no more"); } -bool Obj::check_collection_ref(Index index, CollectionType type) const noexcept +bool Obj::check_collection_ref(StableIndex index, CollectionType type) const noexcept { if (index.is_collection()) { return true; @@ -2453,7 +2453,7 @@ bool Obj::check_collection_ref(Index index, CollectionType type) const noexcept return false; } -void Obj::set_collection_ref(Index index, ref_type ref, CollectionType type) +void Obj::set_collection_ref(StableIndex index, ref_type ref, CollectionType type) { if (index.is_collection()) { set_int(index.get_index(), from_ref(ref)); diff --git a/src/realm/obj.hpp b/src/realm/obj.hpp index edf9db3aa60..cfd9c23d63a 100644 --- a/src/realm/obj.hpp +++ b/src/realm/obj.hpp @@ -57,7 +57,7 @@ class DeepChangeChecker; } // 'Object' would have been a better name, but it clashes with a class in ObjectStore -class Obj : public CollectionParent { +class Obj { public: constexpr Obj() : m_table(nullptr) @@ -69,33 +69,33 @@ class Obj : public CollectionParent { Obj(TableRef table, MemRef mem, ObjKey key, size_t row_ndx); // Overriding members of CollectionParent: - UpdateStatus update_if_needed_with_status() const final; + UpdateStatus update_if_needed_with_status() const; // Get the path in a minimal format without including object accessors. // If you need to obtain additional information for each object in the path, // you should use get_fat_path() or traverse_path() instead (see below). - FullPath get_path() const final; + FullPath get_path() const; std::string get_id() const; - Path get_short_path() const noexcept final; - ColKey get_col_key() const noexcept final; - StablePath get_stable_path() const noexcept final; - void add_index(Path& path, const Index& ndx) const final; - size_t find_index(const Index&) const final + Path get_short_path() const noexcept; + ColKey get_col_key() const noexcept; + StablePath get_stable_path() const noexcept; + void add_index(Path& path, const CollectionParent::Index& ndx) const; + size_t find_index(const CollectionParent::Index&) const { return realm::npos; } - bool update_if_needed() const final; - TableRef get_table() const noexcept final + bool update_if_needed() const; + TableRef get_table() const noexcept { return m_table.cast_away_const(); } - const Obj& get_object() const noexcept final + const Obj& get_object() const noexcept { return *this; } - ref_type get_collection_ref(Index, CollectionType) const final; - bool check_collection_ref(Index, CollectionType) const noexcept final; - void set_collection_ref(Index, ref_type, CollectionType) final; + ref_type get_collection_ref(CollectionParent::Index, CollectionType) const; + bool check_collection_ref(CollectionParent::Index, CollectionType) const noexcept; + void set_collection_ref(CollectionParent::Index, ref_type, CollectionType); StableIndex build_index(ColKey) const; bool check_index(StableIndex) const; @@ -420,6 +420,75 @@ class Obj : public CollectionParent { bool compare_dict_in_mixed(Dictionary&, Dictionary&, ColKey, Obj, StringData) const; }; +class ObjCollectionParent : public Obj, public CollectionParent { +public: + ObjCollectionParent() = default; + ObjCollectionParent(const Obj& obj) noexcept + : Obj(obj) + { + } + ObjCollectionParent& operator=(const Obj& obj) noexcept + { + static_cast(*this) = obj; + return *this; + } + +private: + FullPath get_path() const override + { + return Obj::get_path(); + } + Path get_short_path() const override + { + return Obj::get_short_path(); + } + ColKey get_col_key() const noexcept override + { + return Obj::get_col_key(); + } + StablePath get_stable_path() const override + { + return Obj::get_stable_path(); + } + void add_index(Path& path, const Index& ndx) const override + { + Obj::add_index(path, ndx); + } + size_t find_index(const Index& ndx) const override + { + return Obj::find_index(ndx); + } + TableRef get_table() const noexcept override + { + return Obj::get_table(); + } + + UpdateStatus update_if_needed_with_status() const override + { + return Obj::update_if_needed_with_status(); + } + bool update_if_needed() const override + { + return Obj::update_if_needed(); + } + const Obj& get_object() const noexcept override + { + return Obj::get_object(); + } + ref_type get_collection_ref(Index index, CollectionType type) const override + { + return Obj::get_collection_ref(index, type); + } + bool check_collection_ref(Index index, CollectionType type) const noexcept override + { + return Obj::check_collection_ref(index, type); + } + void set_collection_ref(Index index, ref_type ref, CollectionType type) override + { + Obj::set_collection_ref(index, ref, type); + } +}; + std::ostream& operator<<(std::ostream&, const Obj& obj); template <> diff --git a/src/realm/parser/generated/query_flex.cpp b/src/realm/parser/generated/query_flex.cpp index efeb479959a..91b35ec7db3 100644 --- a/src/realm/parser/generated/query_flex.cpp +++ b/src/realm/parser/generated/query_flex.cpp @@ -101,6 +101,7 @@ typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; +typedef uint64_t flex_uint64_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; @@ -330,7 +331,7 @@ struct yy_buffer_state /* Number of characters read into yy_ch_buf, not including EOB * characters. */ - int yy_n_chars; + yy_size_t yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to @@ -428,7 +429,7 @@ static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner ); YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner ); -YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, yy_size_t len , yyscan_t yyscanner ); /* %endif */ @@ -495,7 +496,7 @@ static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner ); #define YY_DO_BEFORE_ACTION \ yyg->yytext_ptr = yy_bp; \ /* %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ */\ - yyleng = (int) (yy_cp - yy_bp); \ + yyleng = (yy_size_t) (yy_cp - yy_bp); \ yyg->yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ /* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\ @@ -1309,8 +1310,8 @@ struct yyguts_t size_t yy_buffer_stack_max; /**< capacity of stack. */ YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ char yy_hold_char; - int yy_n_chars; - int yyleng_r; + yy_size_t yy_n_chars; + yy_size_t yyleng_r; char *yy_c_buf_p; int yy_init; int yy_start; @@ -1402,7 +1403,7 @@ void yyset_out ( FILE * _out_str , yyscan_t yyscanner ); - int yyget_leng ( yyscan_t yyscanner ); + yy_size_t yyget_leng ( yyscan_t yyscanner ); @@ -1516,7 +1517,7 @@ static int input ( yyscan_t yyscanner ); if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ - int n; \ + yy_size_t n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -2266,7 +2267,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) else { - int num_to_read = + yy_size_t num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) @@ -2280,7 +2281,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) if ( b->yy_is_our_buffer ) { - int new_size = b->yy_buf_size * 2; + yy_size_t new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; @@ -2338,7 +2339,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ - int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); + yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) @@ -2466,7 +2467,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) else { /* need more input */ - int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr); + yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr; ++yyg->yy_c_buf_p; switch ( yy_get_next_buffer( yyscanner ) ) @@ -2935,12 +2936,12 @@ YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner) * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ -YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len , yyscan_t yyscanner) +YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, yy_size_t _yybytes_len , yyscan_t yyscanner) { YY_BUFFER_STATE b; char *buf; yy_size_t n; - int i; + yy_size_t i; /* Get memory for full buffer, including space for trailing EOB's. */ n = (yy_size_t) (_yybytes_len + 2); @@ -2999,7 +3000,7 @@ static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner) do \ { \ /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ + yy_size_t yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = yyg->yy_hold_char; \ yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ @@ -3087,7 +3088,7 @@ FILE *yyget_out (yyscan_t yyscanner) /** Get the length of the current token. * @param yyscanner The scanner object. */ -int yyget_leng (yyscan_t yyscanner) +yy_size_t yyget_leng (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyleng; diff --git a/src/realm/parser/generated/query_flex.hpp b/src/realm/parser/generated/query_flex.hpp index 29b3ba5916f..ccb937ad959 100644 --- a/src/realm/parser/generated/query_flex.hpp +++ b/src/realm/parser/generated/query_flex.hpp @@ -100,6 +100,7 @@ typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; +typedef uint64_t flex_uint64_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; @@ -278,7 +279,7 @@ struct yy_buffer_state /* Number of characters read into yy_ch_buf, not including EOB * characters. */ - int yy_n_chars; + yy_size_t yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to @@ -339,7 +340,7 @@ void yypop_buffer_state ( yyscan_t yyscanner ); YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner ); YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner ); -YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, yy_size_t len , yyscan_t yyscanner ); /* %endif */ @@ -459,7 +460,7 @@ void yyset_out ( FILE * _out_str , yyscan_t yyscanner ); - int yyget_leng ( yyscan_t yyscanner ); + yy_size_t yyget_leng ( yyscan_t yyscanner ); diff --git a/src/realm/path.hpp b/src/realm/path.hpp index 08ead2dbae9..6124590271c 100644 --- a/src/realm/path.hpp +++ b/src/realm/path.hpp @@ -271,54 +271,45 @@ class ExtendedColumnKey { */ class StableIndex { public: - StableIndex() - { - value.raw = 0; - } + StableIndex() = default; StableIndex(ColKey col_key, int64_t salt) { - value.col_index = col_key.get_index().val; - value.is_collection = col_key.is_collection(); - value.is_column = true; - value.salt = int32_t(salt); + m_col_index = col_key.get_index().val; + m_is_collection = col_key.is_collection(); + m_is_column = true; + m_salt = int32_t(salt); } StableIndex(int64_t salt) { - value.raw = 0; - value.salt = int32_t(salt); + m_salt = int32_t(salt); } int64_t get_salt() const { - return value.salt; + return m_salt; } ColKey::Idx get_index() const noexcept { - return {unsigned(value.col_index)}; + return {unsigned(m_col_index)}; } bool is_collection() const noexcept { - return value.is_collection; + return m_is_collection; } bool operator==(const StableIndex& other) const noexcept { - return value.is_column ? value.col_index == other.value.col_index : value.salt == other.value.salt; + return m_is_column ? m_col_index == other.m_col_index : m_salt == other.m_salt; } bool operator<(const StableIndex& other) const noexcept { - return value.is_column ? value.col_index < other.value.col_index : value.salt < other.value.salt; + return m_is_column ? m_col_index < other.m_col_index : m_salt < other.m_salt; } private: - union { - struct { - bool is_column; - bool is_collection; - int16_t col_index; - int32_t salt; - }; - int64_t raw; - } value; + bool m_is_column = false; + bool m_is_collection = false; + int16_t m_col_index = 0; + int32_t m_salt = 0; }; static_assert(sizeof(StableIndex) == 8); diff --git a/src/realm/replication.cpp b/src/realm/replication.cpp index 35bd32d8b3a..cfc60c6580b 100644 --- a/src/realm/replication.cpp +++ b/src/realm/replication.cpp @@ -177,7 +177,7 @@ void Replication::remove_object(const Table* t, ObjKey key) m_encoder.remove_object(key); // Throws } -inline void Replication::select_obj(ObjKey key) +void Replication::select_obj(ObjKey key) { if (key == m_selected_obj) { return; diff --git a/src/realm/set.hpp b/src/realm/set.hpp index 7c6ce92e083..a9de915fd02 100644 --- a/src/realm/set.hpp +++ b/src/realm/set.hpp @@ -102,7 +102,7 @@ class Set final : public CollectionBaseImpl { this->set_owner(owner, col_key); } - Set(ColKey col_key) + Set(ColKey col_key, size_t = 0) : Base(col_key) { if (!col_key.is_set()) { diff --git a/test/test_parser.cpp b/test/test_parser.cpp index be7a7bd9f6f..a8ec6796891 100644 --- a/test/test_parser.cpp +++ b/test/test_parser.cpp @@ -5845,8 +5845,8 @@ TEST(Parser_CollectionLinks) Obj charlie = persons->create_object_with_primary_key("charlie"); Obj david = persons->create_object_with_primary_key("david"); - Obj elisabeth = persons->create_object_with_primary_key("elisabeth"); - Obj felix = persons->create_object_with_primary_key("felix"); + persons->create_object_with_primary_key("elisabeth"); + persons->create_object_with_primary_key("felix"); Obj gary = persons->create_object_with_primary_key("gary"); Obj hutch = persons->create_object_with_primary_key("hutch");