@@ -66,14 +66,7 @@ bool StablePath::is_prefix_of(const StablePath& other) const noexcept
66
66
{
67
67
if (size () > other.size ())
68
68
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 ());
77
70
}
78
71
79
72
/* **************************** CollectionParent ******************************/
@@ -86,212 +79,157 @@ void CollectionParent::check_level() const
86
79
throw LogicError (ErrorCodes::LimitExceeded, " Max nesting level reached" );
87
80
}
88
81
}
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)
90
83
{
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 ;
113
86
}
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 ());
114
109
}
115
110
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)
117
113
{
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);
121
116
return recurse;
122
117
}
123
118
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)
125
120
{
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
+ }
140
124
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
+ }
143
138
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);
152
149
}
153
150
}
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);
157
154
}
158
155
159
156
return false ;
160
157
}
161
158
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)
163
161
{
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:
171
165
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:
177
169
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:
183
173
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:
189
177
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:
207
189
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:
213
193
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." );
226
204
}
227
- REALM_TERMINATE (" Unsupported column type" );
228
205
}
229
206
230
- SetBasePtr CollectionParent::get_setbase_ptr (ColKey col_key) const
207
+ LstBasePtr CollectionParent::get_listbase_ptr (ColKey col_key, size_t level)
231
208
{
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
+ }
236
212
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);
278
217
}
279
218
280
- CollectionBasePtr CollectionParent::get_collection_ptr (ColKey col_key) const
219
+ CollectionBasePtr CollectionParent::get_collection_ptr (ColKey col_key, size_t level)
281
220
{
282
221
if (col_key.is_list ()) {
283
- return get_listbase_ptr (col_key);
222
+ return get_listbase_ptr (col_key, level );
284
223
}
285
224
else if (col_key.is_set ()) {
286
- return get_setbase_ptr (col_key);
225
+ return get_setbase_ptr (col_key, level );
287
226
}
288
227
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 );
290
229
}
291
230
return {};
292
231
}
293
232
294
-
295
233
int64_t CollectionParent::generate_key (size_t sz)
296
234
{
297
235
static std::mt19937 gen32;
0 commit comments