• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

realm / realm-core / nicola.cabiddu_1042

27 Sep 2023 06:04PM CUT coverage: 91.085% (-1.8%) from 92.915%
nicola.cabiddu_1042

Pull #6766

Evergreen

nicola-cab
Fix logic for dictionaries
Pull Request #6766: Client Reset for collections in mixed / nested collections

97276 of 178892 branches covered (0.0%)

1994 of 2029 new or added lines in 7 files covered. (98.28%)

4556 existing lines in 112 files now uncovered.

237059 of 260260 relevant lines covered (91.09%)

6321099.55 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.37
/src/realm/object-store/c_api/object.cpp
1
#include <realm/object-store/c_api/types.hpp>
2
#include <realm/object-store/c_api/util.hpp>
3

4
#include <realm/util/overload.hpp>
5

6
namespace realm::c_api {
7

8
RLM_API bool realm_get_num_objects(const realm_t* realm, realm_class_key_t key, size_t* out_count)
9
{
430✔
10
    return wrap_err([&]() {
430✔
11
        auto& rlm = **realm;
430✔
12
        auto table = rlm.read_group().get_table(TableKey(key));
430✔
13
        if (out_count)
430✔
14
            *out_count = table->size();
426✔
15
        return true;
430✔
16
    });
430✔
17
}
430✔
18

19
RLM_API realm_object_t* realm_get_object(const realm_t* realm, realm_class_key_t tbl_key, realm_object_key_t obj_key)
20
{
6✔
21
    return wrap_err([&]() {
6✔
22
        auto& shared_realm = *realm;
6✔
23
        auto table_key = TableKey(tbl_key);
6✔
24
        auto table = shared_realm->read_group().get_table(table_key);
6✔
25
        auto obj = table->get_object(ObjKey(obj_key));
6✔
26
        auto object = Object{shared_realm, std::move(obj)};
6✔
27
        return new realm_object_t{std::move(object)};
6✔
28
    });
6✔
29
}
6✔
30

31
RLM_API bool realm_object_get_parent(const realm_object_t* object, realm_object_t** parent,
32
                                     realm_class_key_t* class_key)
33
{
×
34
    return wrap_err([&]() {
×
35
        const auto& obj = object->get_obj().get_parent_object();
×
36
        if (class_key)
×
37
            *class_key = obj.get_table()->get_key().value;
×
38

39
        if (parent)
×
40
            *parent = new realm_object_t{Object{object->realm(), std::move(obj)}};
×
41

42
        return true;
×
43
    });
×
44
}
×
45

46

47
RLM_API realm_object_t* realm_object_find_with_primary_key(const realm_t* realm, realm_class_key_t class_key,
48
                                                           realm_value_t pk, bool* out_found)
49
{
14✔
50
    return wrap_err([&]() -> realm_object_t* {
14✔
51
        auto& shared_realm = *realm;
14✔
52
        auto table_key = TableKey(class_key);
14✔
53
        auto table = shared_realm->read_group().get_table(table_key);
14✔
54
        auto pk_val = from_capi(pk);
14✔
55

7✔
56
        auto pk_col = table->get_primary_key_column();
14✔
57
        if (pk_val.is_null() && !pk_col.is_nullable()) {
14✔
58
            if (out_found)
2✔
59
                *out_found = false;
2✔
60
            return nullptr;
2✔
61
        }
2✔
62
        if (!pk_val.is_null() && ColumnType(pk_val.get_type()) != pk_col.get_type() &&
12✔
63
            pk_col.get_type() != col_type_Mixed) {
8✔
64
            if (out_found)
4✔
65
                *out_found = false;
2✔
66
            return nullptr;
4✔
67
        }
4✔
68

4✔
69
        auto obj_key = table->find_primary_key(pk_val);
8✔
70
        if (obj_key) {
8✔
71
            if (out_found)
2✔
72
                *out_found = true;
2✔
73
            auto obj = table->get_object(obj_key);
2✔
74
            return new realm_object_t{Object{shared_realm, std::move(obj)}};
2✔
75
        }
2✔
76
        else {
6✔
77
            if (out_found)
6✔
78
                *out_found = false;
2✔
79
            return static_cast<realm_object_t*>(nullptr);
6✔
80
        }
6✔
81
    });
8✔
82
}
14✔
83

84
RLM_API realm_results_t* realm_object_find_all(const realm_t* realm, realm_class_key_t key)
85
{
34✔
86
    return wrap_err([&]() {
34✔
87
        auto& shared_realm = *realm;
34✔
88
        auto table = shared_realm->read_group().get_table(TableKey(key));
34✔
89
        return new realm_results{Results{shared_realm, table}};
34✔
90
    });
34✔
91
}
34✔
92

93
RLM_API realm_object_t* realm_object_create(realm_t* realm, realm_class_key_t table_key)
94
{
640✔
95
    return wrap_err([&]() {
640✔
96
        auto& shared_realm = *realm;
640✔
97
        auto tblkey = TableKey(table_key);
640✔
98
        auto table = shared_realm->read_group().get_table(tblkey);
640✔
99

320✔
100
        if (table->get_primary_key_column()) {
640✔
101
            auto& object_schema = schema_for_table(*realm, tblkey);
2✔
102
            throw MissingPrimaryKeyException{object_schema.name};
2✔
103
        }
2✔
104

319✔
105
        auto obj = table->create_object();
638✔
106
        auto object = Object{shared_realm, std::move(obj)};
638✔
107
        return new realm_object_t{std::move(object)};
638✔
108
    });
638✔
109
}
640✔
110

111
RLM_API realm_object_t* realm_object_create_with_primary_key(realm_t* realm, realm_class_key_t table_key,
112
                                                             realm_value_t pk)
113
{
246✔
114
    bool did_create;
246✔
115
    realm_object_t* object = realm_object_get_or_create_with_primary_key(realm, table_key, pk, &did_create);
246✔
116
    if (object && !did_create) {
246✔
117
        delete object;
2✔
118
        object = wrap_err([&]() {
2✔
119
            auto& shared_realm = *realm;
2✔
120
            throw ObjectAlreadyExists(shared_realm->read_group().get_class_name(TableKey(table_key)), from_capi(pk));
2✔
121
            return nullptr;
1✔
122
        });
2✔
123
    }
2✔
124
    return object;
246✔
125
}
246✔
126

127
RLM_API realm_object_t* realm_object_get_or_create_with_primary_key(realm_t* realm, realm_class_key_t table_key,
128
                                                                    realm_value_t pk, bool* did_create)
129
{
248✔
130
    return wrap_err([&]() {
248✔
131
        auto& shared_realm = *realm;
248✔
132
        auto tblkey = TableKey(table_key);
248✔
133
        auto table = shared_realm->read_group().get_table(tblkey);
248✔
134
        auto pkval = from_capi(pk);
248✔
135
        if (did_create)
248✔
136
            *did_create = false;
248✔
137

124✔
138
        auto obj = table->create_object_with_primary_key(pkval, did_create);
248✔
139
        auto object = Object{shared_realm, std::move(obj)};
248✔
140
        return new realm_object_t{std::move(object)};
248✔
141
    });
248✔
142
}
248✔
143

144
RLM_API bool realm_object_delete(realm_object_t* obj)
145
{
26✔
146
    return wrap_err([&]() {
26✔
147
        obj->verify_attached();
26✔
148
        obj->get_obj().remove();
26✔
149
        return true;
26✔
150
    });
26✔
151
}
26✔
152

153
RLM_API realm_object_t* _realm_object_from_native_copy(const void* pobj, size_t n)
154
{
2✔
155
    REALM_ASSERT_RELEASE(n == sizeof(Object));
2✔
156

1✔
157
    return wrap_err([&]() {
2✔
158
        auto pobject = static_cast<const Object*>(pobj);
2✔
159
        return new realm_object_t{*pobject};
2✔
160
    });
2✔
161
}
2✔
162

163
RLM_API realm_object_t* _realm_object_from_native_move(void* pobj, size_t n)
164
{
2✔
165
    REALM_ASSERT_RELEASE(n == sizeof(Object));
2✔
166

1✔
167
    return wrap_err([&]() {
2✔
168
        auto pobject = static_cast<Object*>(pobj);
2✔
169
        return new realm_object_t{std::move(*pobject)};
2✔
170
    });
2✔
171
}
2✔
172

173
RLM_API const void* _realm_object_get_native_ptr(realm_object_t* obj)
174
{
2✔
175
    return static_cast<const Object*>(obj);
2✔
176
}
2✔
177

178
RLM_API bool realm_object_resolve_in(const realm_object_t* from_object, const realm_t* target_realm,
179
                                     realm_object_t** resolved)
180
{
6✔
181
    return wrap_err([&]() {
6✔
182
        try {
6✔
183
            const auto& realm = *target_realm;
6✔
184
            auto new_obj = from_object->freeze(realm);
6✔
185
            // clients of the C-API adhere to a different error handling strategy than Core.
3✔
186
            // Core represents lack of resolution as a new object which is invalid.
3✔
187
            // But clients of the C-API instead wants NO object to be produced.
3✔
188
            if (new_obj.is_valid()) {
6✔
189
                *resolved = new realm_object_t{std::move(new_obj)};
4✔
190
            }
4✔
191
            else {
2✔
192
                *resolved = nullptr;
2✔
193
            }
2✔
194
            return true;
6✔
195
        }
6✔
196
        catch (NoSuchTable&) {
×
197
            *resolved = nullptr;
×
198
            return true;
×
199
        }
×
200
        catch (KeyNotFound&) {
×
201
            *resolved = nullptr;
×
202
            return true;
×
203
        }
×
204
    });
6✔
205
}
6✔
206

207
RLM_API bool realm_object_add_int(realm_object_t* object, realm_property_key_t property_key, int64_t value)
208
{
4✔
209
    REALM_ASSERT(object);
4✔
210
    return wrap_err([&]() {
4✔
211
        object->verify_attached();
4✔
212
        object->get_obj().add_int(ColKey(property_key), value);
4✔
213
        return true;
4✔
214
    });
4✔
215
}
4✔
216

217

218
RLM_API bool realm_object_is_valid(const realm_object_t* obj)
219
{
10✔
220
    return obj->is_valid();
10✔
221
}
10✔
222

223
RLM_API realm_object_key_t realm_object_get_key(const realm_object_t* obj)
224
{
32✔
225
    return obj->get_obj().get_key().value;
32✔
226
}
32✔
227

228
RLM_API realm_class_key_t realm_object_get_table(const realm_object_t* obj)
229
{
2✔
230
    return obj->get_obj().get_table()->get_key().value;
2✔
231
}
2✔
232

233
RLM_API realm_link_t realm_object_as_link(const realm_object_t* object)
234
{
34✔
235
    const auto& obj = object->get_obj();
34✔
236
    auto table = obj.get_table();
34✔
237
    auto table_key = table->get_key();
34✔
238
    auto obj_key = obj.get_key();
34✔
239
    return realm_link_t{table_key.value, obj_key.value};
34✔
240
}
34✔
241

242
RLM_API realm_object_t* realm_object_from_thread_safe_reference(const realm_t* realm,
243
                                                                realm_thread_safe_reference_t* tsr)
244
{
8✔
245
    return wrap_err([&]() {
8✔
246
        auto otsr = dynamic_cast<realm_object::thread_safe_reference*>(tsr);
8✔
247
        if (!otsr) {
8✔
248
            throw LogicError{ErrorCodes::IllegalOperation, "Thread safe reference type mismatch"};
2✔
249
        }
2✔
250

3✔
251
        auto obj = otsr->resolve<Object>(*realm);
6✔
252
        return new realm_object_t{std::move(obj)};
6✔
253
    });
6✔
254
}
8✔
255

256
RLM_API bool realm_get_value(const realm_object_t* obj, realm_property_key_t col, realm_value_t* out_value)
257
{
120✔
258
    return realm_get_values(obj, 1, &col, out_value);
120✔
259
}
120✔
260

261
RLM_API bool realm_get_values(const realm_object_t* obj, size_t num_values, const realm_property_key_t* properties,
262
                              realm_value_t* out_values)
263
{
126✔
264
    return wrap_err([&]() {
126✔
265
        obj->verify_attached();
126✔
266

63✔
267
        auto o = obj->get_obj();
126✔
268

63✔
269
        for (size_t i = 0; i < num_values; ++i) {
250✔
270
            auto col_key = ColKey(properties[i]);
126✔
271

63✔
272
            if (col_key.is_collection()) {
126✔
273
                auto table = o.get_table();
2✔
274
                auto& schema = schema_for_table(obj->get_realm(), table->get_key());
2✔
275
                throw PropertyTypeMismatch{schema.name, table->get_column_name(col_key)};
2✔
276
            }
2✔
277

62✔
278
            auto val = o.get_any(col_key);
124✔
279
            if (out_values) {
124✔
280
                auto converted = objkey_to_typed_link(val, col_key, *o.get_table());
116✔
281
                out_values[i] = to_capi(converted);
116✔
282
            }
116✔
283
        }
124✔
284

63✔
285
        return true;
125✔
286
    });
126✔
287
}
126✔
288

289
RLM_API bool realm_set_value(realm_object_t* obj, realm_property_key_t col, realm_value_t new_value, bool is_default)
290
{
914✔
291
    return realm_set_values(obj, 1, &col, &new_value, is_default);
914✔
292
}
914✔
293

294
RLM_API bool realm_set_values(realm_object_t* obj, size_t num_values, const realm_property_key_t* properties,
295
                              const realm_value_t* values, bool is_default)
296
{
922✔
297
    return wrap_err([&]() {
922✔
298
        obj->verify_attached();
922✔
299
        auto o = obj->get_obj();
922✔
300
        auto table = o.get_table();
922✔
301

461✔
302
        // Perform validation up front to avoid partial updates. This is
461✔
303
        // unlikely to incur performance overhead because the object itself is
461✔
304
        // not accessed here, just the bits of the column key and the input type.
461✔
305

461✔
306
        for (size_t i = 0; i < num_values; ++i) {
1,852✔
307
            auto col_key = ColKey(properties[i]);
930✔
308
            table->check_column(col_key);
930✔
309

465✔
310
            if (col_key.is_collection()) {
930✔
311
                auto& schema = schema_for_table(obj->get_realm(), table->get_key());
×
312
                throw PropertyTypeMismatch{schema.name, table->get_column_name(col_key)};
×
313
            }
×
314

465✔
315
            auto val = from_capi(values[i]);
930✔
316
            check_value_assignable(obj->get_realm(), *table, col_key, val);
930✔
317
        }
930✔
318

461✔
319
        // Actually write the properties.
461✔
320

461✔
321
        for (size_t i = 0; i < num_values; ++i) {
1,836✔
322
            auto col_key = ColKey(properties[i]);
914✔
323
            auto val = from_capi(values[i]);
914✔
324
            o.set_any(col_key, val, is_default);
914✔
325
        }
914✔
326

461✔
327
        return true;
922✔
328
    });
922✔
329
}
922✔
330

331
RLM_API bool realm_set_json(realm_object_t* obj, realm_property_key_t col, const char* json_string)
332
{
2✔
333
    return wrap_err([&]() {
2✔
334
        obj->verify_attached();
2✔
335
        auto o = obj->get_obj();
2✔
336
        ColKey col_key(col);
2✔
337
        if (col_key.get_type() != col_type_Mixed) {
2✔
UNCOV
338
            auto table = o.get_table();
×
UNCOV
339
            auto& schema = schema_for_table(obj->get_realm(), table->get_key());
×
UNCOV
340
            throw PropertyTypeMismatch{schema.name, table->get_column_name(col_key)};
×
UNCOV
341
        }
×
342
        o.set_json(ColKey(col), json_string);
2✔
343
        return true;
2✔
344
    });
2✔
345
}
2✔
346

347

348
RLM_API realm_object_t* realm_set_embedded(realm_object_t* obj, realm_property_key_t col)
349
{
2✔
350
    return wrap_err([&]() {
2✔
351
        obj->verify_attached();
2✔
352
        auto& o = obj->get_obj();
2✔
353
        return new realm_object_t({obj->get_realm(), o.create_and_set_linked_object(ColKey(col))});
2✔
354
    });
2✔
355
}
2✔
356

357
RLM_API bool realm_set_list(realm_object_t* obj, realm_property_key_t col)
358
{
6✔
359
    return wrap_err([&]() {
6✔
360
        obj->verify_attached();
6✔
361
        obj->get_obj().set_collection(ColKey(col), CollectionType::List);
6✔
362
        return true;
6✔
363
    });
6✔
364
}
6✔
365

366
RLM_API bool realm_set_set(realm_object_t* obj, realm_property_key_t col)
367
{
2✔
368
    return wrap_err([&]() {
2✔
369
        obj->verify_attached();
2✔
370
        obj->get_obj().set_collection(ColKey(col), CollectionType::Set);
2✔
371
        return true;
2✔
372
    });
2✔
373
}
2✔
374

375
RLM_API bool realm_set_dictionary(realm_object_t* obj, realm_property_key_t col)
376
{
6✔
377
    return wrap_err([&]() {
6✔
378
        obj->verify_attached();
6✔
379
        obj->get_obj().set_collection(ColKey(col), CollectionType::Dictionary);
6✔
380
        return true;
6✔
381
    });
6✔
382
}
6✔
383

384
RLM_API realm_object_t* realm_get_linked_object(realm_object_t* obj, realm_property_key_t col)
385
{
4✔
386
    return wrap_err([&]() {
4✔
387
        obj->verify_attached();
4✔
388
        const auto& o = obj->get_obj().get_linked_object(ColKey(col));
4✔
389
        return o ? new realm_object_t({obj->get_realm(), o}) : nullptr;
3✔
390
    });
4✔
391
}
4✔
392

393
RLM_API realm_list_t* realm_get_list(realm_object_t* object, realm_property_key_t key)
394
{
108✔
395
    return wrap_err([&]() {
108✔
396
        object->verify_attached();
108✔
397

54✔
398
        const auto& obj = object->get_obj();
108✔
399
        auto table = obj.get_table();
108✔
400

54✔
401
        auto col_key = ColKey(key);
108✔
402
        table->check_column(col_key);
108✔
403

54✔
404
        if (!(col_key.is_list() || col_key.get_type() == col_type_Mixed)) {
108✔
405
            report_type_mismatch(object->get_realm(), *table, col_key);
2✔
406
        }
2✔
407

54✔
408
        return new realm_list_t{List{object->get_realm(), std::move(obj), col_key}};
108✔
409
    });
108✔
410
}
108✔
411

412
RLM_API realm_set_t* realm_get_set(realm_object_t* object, realm_property_key_t key)
413
{
86✔
414
    return wrap_err([&]() {
86✔
415
        object->verify_attached();
86✔
416

43✔
417
        const auto& obj = object->get_obj();
86✔
418
        auto table = obj.get_table();
86✔
419

43✔
420
        auto col_key = ColKey(key);
86✔
421
        table->check_column(col_key);
86✔
422

43✔
423
        if (!(col_key.is_set() || col_key.get_type() == col_type_Mixed)) {
86✔
424
            report_type_mismatch(object->get_realm(), *table, col_key);
2✔
425
        }
2✔
426

43✔
427
        return new realm_set_t{object_store::Set{object->get_realm(), std::move(obj), col_key}};
86✔
428
    });
86✔
429
}
86✔
430

431
RLM_API realm_dictionary_t* realm_get_dictionary(realm_object_t* object, realm_property_key_t key)
432
{
90✔
433
    return wrap_err([&]() {
90✔
434
        object->verify_attached();
90✔
435

45✔
436
        const auto& obj = object->get_obj();
90✔
437
        auto table = obj.get_table();
90✔
438
        auto col_key = ColKey(key);
90✔
439
        table->check_column(col_key);
90✔
440

45✔
441
        if (!(col_key.is_dictionary() || col_key.get_type() == col_type_Mixed)) {
90✔
442
            report_type_mismatch(object->get_realm(), *table, col_key);
2✔
443
        }
2✔
444

45✔
445
        return new realm_dictionary_t{object_store::Dictionary{object->get_realm(), std::move(obj), col_key}};
90✔
446
    });
90✔
447
}
90✔
448

449
RLM_API char* realm_object_to_string(realm_object_t* object)
UNCOV
450
{
×
UNCOV
451
    return wrap_err([&]() {
×
UNCOV
452
        object->verify_attached();
×
453

UNCOV
454
        const auto& obj = object->get_obj();
×
UNCOV
455
        return duplicate_string(obj.to_string());
×
UNCOV
456
    });
×
UNCOV
457
}
×
458

459
} // namespace realm::c_api
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc