Skip to content

Commit cb6fbc9

Browse files
committed
Make Obj trivial and add a separate ObjCollectionParent type
1 parent ef979fe commit cb6fbc9

File tree

11 files changed

+268
-267
lines changed

11 files changed

+268
-267
lines changed

src/realm/collection.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ class CollectionBaseImpl : public Interface, protected ArrayParent {
577577
using Interface::get_target_table;
578578

579579
protected:
580-
Obj m_obj_mem;
580+
ObjCollectionParent m_obj_mem;
581581
std::shared_ptr<CollectionParent> m_col_parent;
582582
CollectionParent::Index m_index;
583583
mutable size_t m_my_version = 0;
@@ -735,19 +735,19 @@ class CollectionBaseImpl : public Interface, protected ArrayParent {
735735
void set_backlink(ColKey col_key, ObjLink new_link) const
736736
{
737737
check_parent();
738-
m_parent->set_backlink(col_key, new_link);
738+
m_parent->set_backlink(m_parent->get_object(), col_key, new_link);
739739
}
740740
// Used when replacing a link, return true if CascadeState contains objects to remove
741741
bool replace_backlink(ColKey col_key, ObjLink old_link, ObjLink new_link, CascadeState& state) const
742742
{
743743
check_parent();
744-
return m_parent->replace_backlink(col_key, old_link, new_link, state);
744+
return m_parent->replace_backlink(m_parent->get_object(), col_key, old_link, new_link, state);
745745
}
746746
// Used when removing a backlink, return true if CascadeState contains objects to remove
747747
bool remove_backlink(ColKey col_key, ObjLink old_link, CascadeState& state) const
748748
{
749749
check_parent();
750-
return m_parent->remove_backlink(col_key, old_link, state);
750+
return m_parent->remove_backlink(m_parent->get_object(), col_key, old_link, state);
751751
}
752752

753753
/// Reset the accessor's tracking of the content version. Derived classes

src/realm/collection_parent.cpp

Lines changed: 110 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,7 @@ bool StablePath::is_prefix_of(const StablePath& other) const noexcept
6666
{
6767
if (size() > other.size())
6868
return false;
69-
70-
auto it = other.begin();
71-
for (auto& p : *this) {
72-
if (!(p == *it))
73-
return false;
74-
++it;
75-
}
76-
return true;
69+
return std::equal(other.begin(), other.end(), begin());
7770
}
7871

7972
/***************************** CollectionParent ******************************/
@@ -86,212 +79,157 @@ void CollectionParent::check_level() const
8679
throw LogicError(ErrorCodes::LimitExceeded, "Max nesting level reached");
8780
}
8881
}
89-
void CollectionParent::set_backlink(ColKey col_key, ObjLink new_link) const
82+
void CollectionParent::set_backlink(const Obj& obj, ColKey col_key, ObjLink new_link)
9083
{
91-
if (new_link && new_link.get_obj_key()) {
92-
auto t = get_table();
93-
auto target_table = t->get_parent_group()->get_table(new_link.get_table_key());
94-
ColKey backlink_col_key;
95-
auto type = col_key.get_type();
96-
if (type == col_type_TypedLink || type == col_type_Mixed || col_key.is_dictionary()) {
97-
// This may modify the target table
98-
backlink_col_key = target_table->find_or_add_backlink_column(col_key, t->get_key());
99-
// it is possible that this was a link to the same table and that adding a backlink column has
100-
// caused the need to update this object as well.
101-
update_if_needed();
102-
}
103-
else {
104-
backlink_col_key = t->get_opposite_column(col_key);
105-
}
106-
auto obj_key = new_link.get_obj_key();
107-
auto target_obj = obj_key.is_unresolved() ? target_table->try_get_tombstone(obj_key)
108-
: target_table->try_get_object(obj_key);
109-
if (!target_obj) {
110-
throw InvalidArgument(ErrorCodes::KeyNotFound, "Target object not found");
111-
}
112-
target_obj.add_backlink(backlink_col_key, get_object().get_key());
84+
if (!new_link) {
85+
return;
11386
}
87+
88+
auto t = obj.get_table();
89+
auto target_table = t->get_parent_group()->get_table(new_link.get_table_key());
90+
ColKey backlink_col_key;
91+
auto type = col_key.get_type();
92+
if (type == col_type_TypedLink || type == col_type_Mixed || col_key.is_dictionary()) {
93+
// This may modify the target table
94+
backlink_col_key = target_table->find_or_add_backlink_column(col_key, t->get_key());
95+
// it is possible that this was a link to the same table and that adding a backlink column has
96+
// caused the need to update this object as well.
97+
obj.update_if_needed();
98+
}
99+
else {
100+
backlink_col_key = t->get_opposite_column(col_key);
101+
}
102+
auto obj_key = new_link.get_obj_key();
103+
auto target_obj =
104+
obj_key.is_unresolved() ? target_table->try_get_tombstone(obj_key) : target_table->try_get_object(obj_key);
105+
if (!target_obj) {
106+
throw InvalidArgument(ErrorCodes::KeyNotFound, "Target object not found");
107+
}
108+
target_obj.add_backlink(backlink_col_key, obj.get_key());
114109
}
115110

116-
bool CollectionParent::replace_backlink(ColKey col_key, ObjLink old_link, ObjLink new_link, CascadeState& state) const
111+
bool CollectionParent::replace_backlink(const Obj& obj, ColKey col_key, ObjLink old_link, ObjLink new_link,
112+
CascadeState& state)
117113
{
118-
bool recurse = remove_backlink(col_key, old_link, state);
119-
set_backlink(col_key, new_link);
120-
114+
bool recurse = remove_backlink(obj, col_key, old_link, state);
115+
set_backlink(obj, col_key, new_link);
121116
return recurse;
122117
}
123118

124-
bool CollectionParent::remove_backlink(ColKey col_key, ObjLink old_link, CascadeState& state) const
119+
bool CollectionParent::remove_backlink(const Obj& obj, ColKey col_key, ObjLink old_link, CascadeState& state)
125120
{
126-
if (old_link && old_link.get_obj_key()) {
127-
auto t = get_table();
128-
REALM_ASSERT(t->valid_column(col_key));
129-
ObjKey old_key = old_link.get_obj_key();
130-
auto target_obj = t->get_parent_group()->get_object(old_link);
131-
TableRef target_table = target_obj.get_table();
132-
ColKey backlink_col_key;
133-
auto type = col_key.get_type();
134-
if (type == col_type_TypedLink || type == col_type_Mixed || col_key.is_dictionary()) {
135-
backlink_col_key = target_table->find_or_add_backlink_column(col_key, t->get_key());
136-
}
137-
else {
138-
backlink_col_key = t->get_opposite_column(col_key);
139-
}
121+
if (!old_link) {
122+
return false;
123+
}
140124

141-
bool strong_links = target_table->is_embedded();
142-
bool is_unres = old_key.is_unresolved();
125+
auto t = obj.get_table();
126+
REALM_ASSERT(t->valid_column(col_key));
127+
ObjKey old_key = old_link.get_obj_key();
128+
auto target_obj = t->get_parent_group()->get_object(old_link);
129+
TableRef target_table = target_obj.get_table();
130+
ColKey backlink_col_key;
131+
auto type = col_key.get_type();
132+
if (type == col_type_TypedLink || type == col_type_Mixed || col_key.is_dictionary()) {
133+
backlink_col_key = target_table->find_or_add_backlink_column(col_key, t->get_key());
134+
}
135+
else {
136+
backlink_col_key = t->get_opposite_column(col_key);
137+
}
143138

144-
bool last_removed = target_obj.remove_one_backlink(backlink_col_key, get_object().get_key()); // Throws
145-
if (is_unres) {
146-
if (last_removed) {
147-
// Check is there are more backlinks
148-
if (!target_obj.has_backlinks(false)) {
149-
// Tombstones can be erased right away - there is no cascading effect
150-
target_table->m_tombstones->erase(old_key, state);
151-
}
139+
bool strong_links = target_table->is_embedded();
140+
bool is_unres = old_key.is_unresolved();
141+
142+
bool last_removed = target_obj.remove_one_backlink(backlink_col_key, obj.get_key()); // Throws
143+
if (is_unres) {
144+
if (last_removed) {
145+
// Check is there are more backlinks
146+
if (!target_obj.has_backlinks(false)) {
147+
// Tombstones can be erased right away - there is no cascading effect
148+
target_table->m_tombstones->erase(old_key, state);
152149
}
153150
}
154-
else {
155-
return state.enqueue_for_cascade(target_obj, strong_links, last_removed);
156-
}
151+
}
152+
else {
153+
return state.enqueue_for_cascade(target_obj, strong_links, last_removed);
157154
}
158155

159156
return false;
160157
}
161158

162-
LstBasePtr CollectionParent::get_listbase_ptr(ColKey col_key) const
159+
template <typename Base, template <typename> typename Collection, typename LinkCol>
160+
std::unique_ptr<Base> create_collection(ColKey col_key, size_t level)
163161
{
164-
auto table = get_table();
165-
auto attr = table->get_column_attr(col_key);
166-
REALM_ASSERT(attr.test(col_attr_List) || attr.test(col_attr_Nullable));
167-
bool nullable = attr.test(col_attr_Nullable);
168-
169-
switch (table->get_column_type(col_key)) {
170-
case type_Int: {
162+
bool nullable = col_key.get_attrs().test(col_attr_Nullable);
163+
switch (col_key.get_type()) {
164+
case col_type_Int:
171165
if (nullable)
172-
return std::make_unique<Lst<util::Optional<Int>>>(col_key);
173-
else
174-
return std::make_unique<Lst<Int>>(col_key);
175-
}
176-
case type_Bool: {
166+
return std::make_unique<Collection<util::Optional<Int>>>(col_key);
167+
return std::make_unique<Collection<Int>>(col_key);
168+
case col_type_Bool:
177169
if (nullable)
178-
return std::make_unique<Lst<util::Optional<Bool>>>(col_key);
179-
else
180-
return std::make_unique<Lst<Bool>>(col_key);
181-
}
182-
case type_Float: {
170+
return std::make_unique<Collection<util::Optional<Bool>>>(col_key);
171+
return std::make_unique<Collection<Bool>>(col_key);
172+
case col_type_Float:
183173
if (nullable)
184-
return std::make_unique<Lst<util::Optional<Float>>>(col_key);
185-
else
186-
return std::make_unique<Lst<Float>>(col_key);
187-
}
188-
case type_Double: {
174+
return std::make_unique<Collection<util::Optional<Float>>>(col_key);
175+
return std::make_unique<Collection<Float>>(col_key);
176+
case col_type_Double:
189177
if (nullable)
190-
return std::make_unique<Lst<util::Optional<Double>>>(col_key);
191-
else
192-
return std::make_unique<Lst<Double>>(col_key);
193-
}
194-
case type_String: {
195-
return std::make_unique<Lst<String>>(col_key);
196-
}
197-
case type_Binary: {
198-
return std::make_unique<Lst<Binary>>(col_key);
199-
}
200-
case type_Timestamp: {
201-
return std::make_unique<Lst<Timestamp>>(col_key);
202-
}
203-
case type_Decimal: {
204-
return std::make_unique<Lst<Decimal128>>(col_key);
205-
}
206-
case type_ObjectId: {
178+
return std::make_unique<Collection<util::Optional<Double>>>(col_key);
179+
return std::make_unique<Collection<Double>>(col_key);
180+
case col_type_String:
181+
return std::make_unique<Collection<String>>(col_key);
182+
case col_type_Binary:
183+
return std::make_unique<Collection<Binary>>(col_key);
184+
case col_type_Timestamp:
185+
return std::make_unique<Collection<Timestamp>>(col_key);
186+
case col_type_Decimal:
187+
return std::make_unique<Collection<Decimal128>>(col_key);
188+
case col_type_ObjectId:
207189
if (nullable)
208-
return std::make_unique<Lst<util::Optional<ObjectId>>>(col_key);
209-
else
210-
return std::make_unique<Lst<ObjectId>>(col_key);
211-
}
212-
case type_UUID: {
190+
return std::make_unique<Collection<util::Optional<ObjectId>>>(col_key);
191+
return std::make_unique<Collection<ObjectId>>(col_key);
192+
case col_type_UUID:
213193
if (nullable)
214-
return std::make_unique<Lst<util::Optional<UUID>>>(col_key);
215-
else
216-
return std::make_unique<Lst<UUID>>(col_key);
217-
}
218-
case type_TypedLink: {
219-
return std::make_unique<Lst<ObjLink>>(col_key);
220-
}
221-
case type_Mixed: {
222-
return std::make_unique<Lst<Mixed>>(col_key, get_level() + 1);
223-
}
224-
case type_Link:
225-
return std::make_unique<LnkLst>(col_key);
194+
return std::make_unique<Collection<util::Optional<UUID>>>(col_key);
195+
return std::make_unique<Collection<UUID>>(col_key);
196+
case col_type_TypedLink:
197+
return std::make_unique<Collection<ObjLink>>(col_key);
198+
case col_type_Mixed:
199+
return std::make_unique<Collection<Mixed>>(col_key, level + 1);
200+
case col_type_Link:
201+
return std::make_unique<LinkCol>(col_key);
202+
default:
203+
REALM_TERMINATE("Unsupported column type.");
226204
}
227-
REALM_TERMINATE("Unsupported column type");
228205
}
229206

230-
SetBasePtr CollectionParent::get_setbase_ptr(ColKey col_key) const
207+
LstBasePtr CollectionParent::get_listbase_ptr(ColKey col_key, size_t level)
231208
{
232-
auto table = get_table();
233-
auto attr = table->get_column_attr(col_key);
234-
REALM_ASSERT(attr.test(col_attr_Set));
235-
bool nullable = attr.test(col_attr_Nullable);
209+
REALM_ASSERT(col_key.get_attrs().test(col_attr_List) || col_key.get_type() == col_type_Mixed);
210+
return create_collection<LstBase, Lst, LnkLst>(col_key, level);
211+
}
236212

237-
switch (table->get_column_type(col_key)) {
238-
case type_Int:
239-
if (nullable)
240-
return std::make_unique<Set<util::Optional<Int>>>(col_key);
241-
return std::make_unique<Set<Int>>(col_key);
242-
case type_Bool:
243-
if (nullable)
244-
return std::make_unique<Set<util::Optional<Bool>>>(col_key);
245-
return std::make_unique<Set<Bool>>(col_key);
246-
case type_Float:
247-
if (nullable)
248-
return std::make_unique<Set<util::Optional<Float>>>(col_key);
249-
return std::make_unique<Set<Float>>(col_key);
250-
case type_Double:
251-
if (nullable)
252-
return std::make_unique<Set<util::Optional<Double>>>(col_key);
253-
return std::make_unique<Set<Double>>(col_key);
254-
case type_String:
255-
return std::make_unique<Set<String>>(col_key);
256-
case type_Binary:
257-
return std::make_unique<Set<Binary>>(col_key);
258-
case type_Timestamp:
259-
return std::make_unique<Set<Timestamp>>(col_key);
260-
case type_Decimal:
261-
return std::make_unique<Set<Decimal128>>(col_key);
262-
case type_ObjectId:
263-
if (nullable)
264-
return std::make_unique<Set<util::Optional<ObjectId>>>(col_key);
265-
return std::make_unique<Set<ObjectId>>(col_key);
266-
case type_UUID:
267-
if (nullable)
268-
return std::make_unique<Set<util::Optional<UUID>>>(col_key);
269-
return std::make_unique<Set<UUID>>(col_key);
270-
case type_TypedLink:
271-
return std::make_unique<Set<ObjLink>>(col_key);
272-
case type_Mixed:
273-
return std::make_unique<Set<Mixed>>(col_key);
274-
case type_Link:
275-
return std::make_unique<LnkSet>(col_key);
276-
}
277-
REALM_TERMINATE("Unsupported column type.");
213+
SetBasePtr CollectionParent::get_setbase_ptr(ColKey col_key, size_t level)
214+
{
215+
REALM_ASSERT(col_key.get_attrs().test(col_attr_Set));
216+
return create_collection<SetBase, Set, LnkSet>(col_key, level);
278217
}
279218

280-
CollectionBasePtr CollectionParent::get_collection_ptr(ColKey col_key) const
219+
CollectionBasePtr CollectionParent::get_collection_ptr(ColKey col_key, size_t level)
281220
{
282221
if (col_key.is_list()) {
283-
return get_listbase_ptr(col_key);
222+
return get_listbase_ptr(col_key, level);
284223
}
285224
else if (col_key.is_set()) {
286-
return get_setbase_ptr(col_key);
225+
return get_setbase_ptr(col_key, level);
287226
}
288227
else if (col_key.is_dictionary()) {
289-
return std::make_unique<Dictionary>(col_key, get_level() + 1);
228+
return std::make_unique<Dictionary>(col_key, level + 1);
290229
}
291230
return {};
292231
}
293232

294-
295233
int64_t CollectionParent::generate_key(size_t sz)
296234
{
297235
static std::mt19937 gen32;

0 commit comments

Comments
 (0)