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

realm / realm-core / nicola.cabiddu_1042

27 Sep 2023 06:04PM UTC 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

93.33
/src/realm/object-store/c_api/query.cpp
1
#include "realm/sort_descriptor.hpp"
2
#include "realm/util/scope_exit.hpp"
3
#include <realm/object-store/c_api/types.hpp>
4
#include <realm/object-store/c_api/util.hpp>
5

6
#include <realm/object-store/keypath_helpers.hpp>
7
#include <realm/parser/query_parser.hpp>
8
#include <realm/parser/keypath_mapping.hpp>
9

10
namespace realm::c_api {
11

12
namespace {
13
struct QueryArgumentsAdapter : query_parser::Arguments {
14
    const realm_query_arg_t* m_args = nullptr;
15

16
    QueryArgumentsAdapter(size_t num_args, const realm_query_arg_t* args) noexcept
17
        : Arguments(num_args)
18
        , m_args(args)
19
    {
186✔
20
    }
186✔
21

22
    bool bool_for_argument(size_t i) final
23
    {
2✔
24
        verify_ndx(i);
2✔
25
        REALM_ASSERT(m_args[i].arg[0].type == RLM_TYPE_BOOL);
2✔
26
        return m_args[i].arg[0].boolean;
2✔
27
    }
2✔
28

29
    long long long_for_argument(size_t i) final
30
    {
8✔
31
        verify_ndx(i);
8✔
32
        REALM_ASSERT(m_args[i].arg[0].type == RLM_TYPE_INT);
8✔
33
        return m_args[i].arg[0].integer;
8✔
34
    }
8✔
35

36
    float float_for_argument(size_t i) final
37
    {
2✔
38
        verify_ndx(i);
2✔
39
        REALM_ASSERT(m_args[i].arg[0].type == RLM_TYPE_FLOAT);
2✔
40
        return m_args[i].arg[0].fnum;
2✔
41
    }
2✔
42

43
    double double_for_argument(size_t i) final
44
    {
2✔
45
        verify_ndx(i);
2✔
46
        REALM_ASSERT(m_args[i].arg[0].type == RLM_TYPE_DOUBLE);
2✔
47
        return m_args[i].arg[0].dnum;
2✔
48
    }
2✔
49

50
    StringData string_for_argument(size_t i) final
51
    {
100✔
52
        verify_ndx(i);
100✔
53
        REALM_ASSERT(m_args[i].arg[0].type == RLM_TYPE_STRING);
100✔
54
        return from_capi(m_args[i].arg[0].string);
100✔
55
    }
100✔
56

57
    BinaryData binary_for_argument(size_t i) final
58
    {
2✔
59
        verify_ndx(i);
2✔
60
        REALM_ASSERT(m_args[i].arg[0].type == RLM_TYPE_BINARY);
2✔
61
        return from_capi(m_args[i].arg[0].binary);
2✔
62
    }
2✔
63

64
    Timestamp timestamp_for_argument(size_t i) final
65
    {
2✔
66
        verify_ndx(i);
2✔
67
        REALM_ASSERT(m_args[i].arg[0].type == RLM_TYPE_TIMESTAMP);
2✔
68
        return from_capi(m_args[i].arg[0].timestamp);
2✔
69
    }
2✔
70

71
    ObjKey object_index_for_argument(size_t i) final
72
    {
4✔
73
        verify_ndx(i);
4✔
74
        REALM_ASSERT(m_args[i].arg[0].type == RLM_TYPE_LINK);
4✔
75
        // FIXME: Somehow check the target table type?
2✔
76
        return from_capi(m_args[i].arg[0].link).get_obj_key();
4✔
77
    }
4✔
78

79
    ObjectId objectid_for_argument(size_t i) final
80
    {
2✔
81
        verify_ndx(i);
2✔
82
        REALM_ASSERT(m_args[i].arg[0].type == RLM_TYPE_OBJECT_ID);
2✔
83
        return from_capi(m_args[i].arg[0].object_id);
2✔
84
    }
2✔
85

86
    Decimal128 decimal128_for_argument(size_t i) final
87
    {
6✔
88
        verify_ndx(i);
6✔
89
        REALM_ASSERT(m_args[i].arg[0].type == RLM_TYPE_DECIMAL128);
6✔
90
        return from_capi(m_args[i].arg[0].decimal128);
6✔
91
    }
6✔
92

93
    UUID uuid_for_argument(size_t i) final
94
    {
2✔
95
        verify_ndx(i);
2✔
96
        REALM_ASSERT(m_args[i].arg[0].type == RLM_TYPE_UUID);
2✔
97
        return from_capi(m_args[i].arg[0].uuid);
2✔
98
    }
2✔
99

100
    ObjLink objlink_for_argument(size_t i) final
101
    {
×
102
        verify_ndx(i);
×
103
        REALM_ASSERT(m_args[i].arg[0].type == RLM_TYPE_LINK);
×
104
        return from_capi(m_args[i].arg[0].link);
×
105
    }
×
106

107
#if REALM_ENABLE_GEOSPATIAL
108
    Geospatial geospatial_for_argument(size_t i) final
109
    {
×
110
        verify_ndx(i);
×
111
        // FIXME: implement this
112
        throw LogicError{
×
113
            ErrorCodes::RuntimeError,
×
114
            util::format("geospatial in the C-API is not yet implemented (for argument %1)", i)}; // LCOV_EXCL_LINE
×
115
    }
×
116
#endif
117

118
    bool is_argument_null(size_t i) final
119
    {
142✔
120
        verify_ndx(i);
142✔
121
        return !m_args[i].is_list && m_args[i].arg[0].type == RLM_TYPE_NULL;
142✔
122
    }
142✔
123

124
    bool is_argument_list(size_t i) final
125
    {
144✔
126
        verify_ndx(i);
144✔
127
        return m_args[i].is_list;
144✔
128
    }
144✔
129

130
    std::vector<Mixed> list_for_argument(size_t ndx) final
131
    {
8✔
132
        verify_ndx(ndx);
8✔
133
        REALM_ASSERT(m_args[ndx].is_list);
8✔
134
        std::vector<Mixed> list;
8✔
135
        list.reserve(m_args[ndx].nb_args);
8✔
136
        for (size_t i = 0; i < m_args[ndx].nb_args; ++i) {
20✔
137
            list.push_back(from_capi(m_args[ndx].arg[i]));
12✔
138
        }
12✔
139
        return list;
8✔
140
    }
8✔
141
    DataType type_for_argument(size_t i) override
142
    {
132✔
143
        verify_ndx(i);
132✔
144
        switch (m_args[i].arg[0].type) {
132✔
145
            case RLM_TYPE_NULL:                                                  // LCOV_EXCL_LINE
✔
146
                REALM_TERMINATE("Query parser did not call is_argument_null()"); // LCOV_EXCL_LINE
×
147
            case RLM_TYPE_INT:
8✔
148
                return type_Int;
8✔
149
            case RLM_TYPE_STRING:
100✔
150
                return type_String;
100✔
151
            case RLM_TYPE_BOOL:
2✔
152
                return type_Bool;
2✔
153
            case RLM_TYPE_FLOAT:
2✔
154
                return type_Float;
2✔
155
            case RLM_TYPE_DOUBLE:
2✔
156
                return type_Double;
2✔
157
            case RLM_TYPE_BINARY:
2✔
158
                return type_Binary;
2✔
159
            case RLM_TYPE_TIMESTAMP:
2✔
160
                return type_Timestamp;
2✔
161
            case RLM_TYPE_LINK:
4✔
162
                return type_Link;
4✔
163
            case RLM_TYPE_OBJECT_ID:
2✔
164
                return type_ObjectId;
2✔
165
            case RLM_TYPE_DECIMAL128:
6✔
166
                return type_Decimal;
6✔
167
            case RLM_TYPE_UUID:
2✔
168
                return type_UUID;
2✔
169
            case RLM_TYPE_LIST:
✔
170
                return type_List;
×
171
            case RLM_TYPE_SET:
✔
172
                return type_Set;
×
UNCOV
173
            case RLM_TYPE_DICTIONARY:
✔
UNCOV
174
                return type_Dictionary;
×
UNCOV
175
        }
×
UNCOV
176
        throw LogicError{ErrorCodes::TypeMismatch, "Unsupported type"}; // LCOV_EXCL_LINE
×
UNCOV
177
        return type_Int;
×
UNCOV
178
    }
×
179
};
180
} // namespace
181

182
static Query parse_and_apply_query(const std::shared_ptr<Realm>& realm, ConstTableRef table, const char* query_string,
183
                                   size_t num_args, const realm_query_arg_t* args)
184
{
186✔
185
    query_parser::KeyPathMapping mapping;
186✔
186
    realm::populate_keypath_mapping(mapping, *realm);
186✔
187
    QueryArgumentsAdapter arguments{num_args, args};
186✔
188
    Query query = table->query(query_string, arguments, mapping);
186✔
189
    return query;
186✔
190
}
186✔
191

192
RLM_API realm_query_t* realm_query_parse(const realm_t* realm, realm_class_key_t target_table_key,
193
                                         const char* query_string, size_t num_args, const realm_query_arg_t* args)
194
{
156✔
195
    return wrap_err([&]() {
156✔
196
        auto table = (*realm)->read_group().get_table(TableKey(target_table_key));
156✔
197
        Query query = parse_and_apply_query(*realm, table, query_string, num_args, args);
156✔
198
        auto ordering = query.get_ordering();
156✔
199
        return new realm_query_t{std::move(query), std::move(ordering), *realm};
156✔
200
    });
156✔
201
}
156✔
202

203
RLM_API const char* realm_query_get_description(realm_query_t* query)
204
{
2✔
205
    return wrap_err([&]() {
2✔
206
        return query->get_description();
2✔
207
    });
2✔
208
}
2✔
209

210
RLM_API realm_query_t* realm_query_append_query(const realm_query_t* existing_query, const char* query_string,
211
                                                size_t num_args, const realm_query_arg_t* args)
212
{
14✔
213
    return wrap_err([&]() {
14✔
214
        auto realm = existing_query->weak_realm.lock();
14✔
215
        auto table = existing_query->query.get_table();
14✔
216
        auto query = parse_and_apply_query(realm, table, query_string, num_args, args);
14✔
217
        auto combined = Query(existing_query->query).and_query(query);
14✔
218
        auto ordering_copy = util::make_bind<DescriptorOrdering>();
14✔
219
        *ordering_copy = existing_query->get_ordering();
14✔
220
        if (auto ordering = query.get_ordering())
14✔
221
            ordering_copy->append(*ordering);
10✔
222
        return new realm_query_t{std::move(combined), std::move(ordering_copy), realm};
14✔
223
    });
14✔
224
}
14✔
225

226
RLM_API realm_query_t* realm_query_parse_for_list(const realm_list_t* list, const char* query_string, size_t num_args,
227
                                                  const realm_query_arg_t* args)
228
{
4✔
229
    return wrap_err([&]() {
4✔
230
        auto existing_query = list->get_query();
4✔
231
        auto realm = list->get_realm();
4✔
232
        auto table = list->get_table();
4✔
233
        auto query = parse_and_apply_query(realm, table, query_string, num_args, args);
4✔
234
        auto combined = existing_query.and_query(query);
4✔
235
        auto ordering_copy = util::make_bind<DescriptorOrdering>();
4✔
236
        if (auto ordering = query.get_ordering())
4✔
UNCOV
237
            ordering_copy->append(*ordering);
×
238
        return new realm_query_t{std::move(combined), std::move(ordering_copy), realm};
4✔
239
    });
4✔
240
}
4✔
241

242
RLM_API realm_query_t* realm_query_parse_for_set(const realm_set_t* set, const char* query_string, size_t num_args,
243
                                                 const realm_query_arg_t* args)
244
{
2✔
245
    return wrap_err([&]() {
2✔
246
        auto existing_query = set->get_query();
2✔
247
        auto realm = set->get_realm();
2✔
248
        auto table = set->get_table();
2✔
249
        auto query = parse_and_apply_query(realm, table, query_string, num_args, args);
2✔
250
        auto combined = existing_query.and_query(query);
2✔
251
        auto ordering_copy = util::make_bind<DescriptorOrdering>();
2✔
252
        if (auto ordering = query.get_ordering())
2✔
UNCOV
253
            ordering_copy->append(*ordering);
×
254
        return new realm_query_t{std::move(combined), std::move(ordering_copy), realm};
2✔
255
    });
2✔
256
}
2✔
257

258
RLM_API realm_query_t* realm_query_parse_for_results(const realm_results_t* results, const char* query_string,
259
                                                     size_t num_args, const realm_query_arg_t* args)
260
{
12✔
261
    return wrap_err([&]() {
12✔
262
        auto existing_query = results->get_query();
12✔
263
        auto realm = results->get_realm();
12✔
264
        auto table = results->get_table();
12✔
265
        auto query = parse_and_apply_query(realm, table, query_string, num_args, args);
12✔
266
        auto combined = existing_query.and_query(query);
12✔
267
        auto ordering_copy = util::make_bind<DescriptorOrdering>();
12✔
268
        if (auto ordering = query.get_ordering())
12✔
UNCOV
269
            ordering_copy->append(*ordering);
×
270
        return new realm_query_t{std::move(combined), std::move(ordering_copy), realm};
12✔
271
    });
12✔
272
}
12✔
273

274
RLM_API bool realm_query_count(const realm_query_t* query, size_t* out_count)
275
{
28✔
276
    return wrap_err([&]() {
28✔
277
        *out_count = Query(query->query).count(query->get_ordering());
28✔
278
        return true;
28✔
279
    });
28✔
280
}
28✔
281

282
RLM_API bool realm_query_find_first(realm_query_t* query, realm_value_t* out_value, bool* out_found)
283
{
8✔
284
    return wrap_err([&]() {
8✔
285
        const auto& realm_query_ordering = query->get_ordering();
8✔
286
        if (realm_query_ordering.size() > 0) {
8✔
287
            auto orderding = util::make_bind<DescriptorOrdering>();
6✔
288
            orderding->append(realm_query_ordering);
6✔
289
            query->query.set_ordering(orderding);
6✔
290
        }
6✔
291
        auto key = query->query.find();
8✔
292
        if (out_found)
8✔
293
            *out_found = bool(key);
8✔
294
        if (key && out_value) {
8✔
295
            ObjLink link{query->query.get_table()->get_key(), key};
8✔
296
            out_value->type = RLM_TYPE_LINK;
8✔
297
            out_value->link = to_capi(link);
8✔
298
        }
8✔
299
        return true;
8✔
300
    });
8✔
301
}
8✔
302

303
RLM_API realm_results_t* realm_query_find_all(realm_query_t* query)
304
{
104✔
305
    return wrap_err([&]() {
104✔
306
        auto shared_realm = query->weak_realm.lock();
104✔
307
        REALM_ASSERT_RELEASE(shared_realm);
104✔
308
        return new realm_results{Results{shared_realm, query->query, query->get_ordering()}};
104✔
309
    });
104✔
310
}
104✔
311

312
RLM_API realm_results_t* realm_list_to_results(realm_list_t* list)
313
{
6✔
314
    return wrap_err([&]() {
6✔
315
        return new realm_results_t{list->as_results()};
6✔
316
    });
6✔
317
}
6✔
318

319
RLM_API realm_results_t* realm_set_to_results(realm_set_t* set)
UNCOV
320
{
×
321
    return wrap_err([&]() {
×
322
        return new realm_results_t{set->as_results()};
×
323
    });
×
324
}
×
325

326
RLM_API realm_results_t* realm_dictionary_to_results(realm_dictionary_t* dictionary)
327
{
2✔
328
    return wrap_err([&]() {
2✔
329
        return new realm_results_t{dictionary->as_results()};
2✔
330
    });
2✔
331
}
2✔
332

333
RLM_API realm_results_t* realm_get_backlinks(realm_object_t* object, realm_class_key_t source_table_key,
334
                                             realm_property_key_t property_key)
335
{
8✔
336
    return wrap_err([&]() {
8✔
337
        object->verify_attached();
8✔
338
        auto realm = object->realm();
8✔
339
        auto source_table = realm->read_group().get_table(TableKey{source_table_key});
8✔
340
        auto backlink_view = object->get_obj().get_backlink_view(source_table, ColKey{property_key});
8✔
341
        return new realm_results_t{Results{realm, backlink_view}};
8✔
342
    });
8✔
343
}
8✔
344

345
RLM_API bool realm_results_is_valid(const realm_results_t* results, bool* is_valid)
346
{
8✔
347
    return wrap_err([&]() {
8✔
348
        if (is_valid)
8✔
349
            *is_valid = results->is_valid();
8✔
350
        return true;
8✔
351
    });
8✔
352
}
8✔
353

354
RLM_API bool realm_results_count(realm_results_t* results, size_t* out_count)
355
{
60✔
356
    return wrap_err([&]() {
60✔
357
        auto count = results->size();
60✔
358
        if (out_count) {
60✔
359
            *out_count = count;
58✔
360
        }
58✔
361
        return true;
60✔
362
    });
60✔
363
}
60✔
364

365
RLM_API realm_results_t* realm_results_filter(realm_results_t* results, realm_query_t* query)
366
{
4✔
367
    return wrap_err([&]() {
4✔
368
        return new realm_results{results->filter(std::move(query->query))};
4✔
369
    });
4✔
370
}
4✔
371

372
namespace {
373
realm_results_t* realm_results_ordering(realm_results_t* results, const char* op, const char* ordering)
374
{
4✔
375
    return wrap_err([&]() -> realm_results_t* {
4✔
376
        std::string str = "TRUEPREDICATE " + std::string(op) + "(" + std::string(ordering) + ")";
4✔
377
        auto q = results->get_table()->query(str);
4✔
378
        auto ordering{q.get_ordering()};
4✔
379
        return new realm_results{results->apply_ordering(std::move(*ordering))};
4✔
380
        return nullptr;
2✔
381
    });
4✔
382
}
4✔
383
} // namespace
384

385
RLM_API realm_results_t* realm_results_sort(realm_results_t* results, const char* sort_string)
386
{
2✔
387
    return realm_results_ordering(results, "SORT", sort_string);
2✔
388
}
2✔
389

390
RLM_API realm_results_t* realm_results_distinct(realm_results_t* results, const char* distinct_string)
391
{
2✔
392
    return realm_results_ordering(results, "DISTINCT", distinct_string);
2✔
393
}
2✔
394

395
RLM_API realm_results_t* realm_results_limit(realm_results_t* results, size_t max_count)
396
{
2✔
397
    return wrap_err([&]() {
2✔
398
        return new realm_results{results->limit(max_count)};
2✔
399
    });
2✔
400
}
2✔
401

402

403
RLM_API bool realm_results_get(realm_results_t* results, size_t index, realm_value_t* out_value)
404
{
18✔
405
    return wrap_err([&]() {
18✔
406
        auto mixed = results->get_any(index);
18✔
407
        if (out_value) {
18✔
408
            *out_value = to_capi(mixed);
14✔
409
        }
14✔
410
        return true;
18✔
411
    });
18✔
412
}
18✔
413

414
RLM_API realm_list_t* realm_results_get_list(realm_results_t* results, size_t index)
415
{
4✔
416
    return wrap_err([&]() {
4✔
417
        realm_list_t* out = nullptr;
4✔
418
        auto result_list = results->get_list(index);
4✔
419
        if (result_list.is_valid())
4✔
420
            out = new realm_list_t{result_list};
4✔
421
        return out;
4✔
422
    });
4✔
423
}
4✔
424

425
RLM_API realm_set_t* realm_results_get_set(realm_results_t* results, size_t index)
426
{
4✔
427
    return wrap_err([&]() {
4✔
428
        realm_set_t* out = nullptr;
4✔
429
        auto result_set = results->get_set(index);
4✔
430
        if (result_set.is_valid())
4✔
431
            out = new realm_set_t{result_set};
4✔
432
        return out;
4✔
433
    });
4✔
434
}
4✔
435

436
RLM_API realm_dictionary_t* realm_results_get_dictionary(realm_results_t* results, size_t index)
437
{
4✔
438
    return wrap_err([&]() {
4✔
439
        realm_dictionary_t* out = nullptr;
4✔
440
        auto result_dictionary = results->get_dictionary(index);
4✔
441
        if (result_dictionary.is_valid())
4✔
442
            out = new realm_dictionary_t{result_dictionary};
4✔
443
        return out;
4✔
444
    });
4✔
445
}
4✔
446

447
RLM_API bool realm_results_find(realm_results_t* results, realm_value_t* value, size_t* out_index, bool* out_found)
448
{
12✔
449
    if (out_index)
12✔
450
        *out_index = realm::not_found;
12✔
451
    if (out_found)
12✔
452
        *out_found = false;
12✔
453

6✔
454
    return wrap_err([&]() {
12✔
455
        auto val = from_capi(*value);
12✔
456
        if (out_index) {
12✔
457
            *out_index = results->index_of(val);
12✔
458
            if (out_found && *out_index != realm::not_found) {
12✔
459
                *out_found = true;
8✔
460
            }
8✔
461
        }
12✔
462
        return true;
12✔
463
    });
12✔
464
}
12✔
465

466
RLM_API realm_object_t* realm_results_get_object(realm_results_t* results, size_t index)
467
{
14✔
468
    return wrap_err([&]() {
14✔
469
        auto shared_realm = results->get_realm();
14✔
470
        auto obj = results->get<Obj>(index);
14✔
471
        return new realm_object_t{Object{shared_realm, std::move(obj)}};
14✔
472
    });
14✔
473
}
14✔
474

475
RLM_API realm_query_t* realm_results_get_query(realm_results_t* results)
476
{
2✔
477
    return wrap_err([&]() {
2✔
478
        auto query = results->get_query();
2✔
479
        auto shared_realm = results->get_realm();
2✔
480
        auto ordering = query.get_ordering();
2✔
481
        return new realm_query_t{std::move(query), std::move(ordering), shared_realm};
2✔
482
    });
2✔
483
}
2✔
484

485
RLM_API bool realm_results_find_object(realm_results_t* results, realm_object_t* value, size_t* out_index,
486
                                       bool* out_found)
487
{
4✔
488
    if (out_index)
4✔
489
        *out_index = realm::not_found;
4✔
490
    if (out_found)
4✔
491
        *out_found = false;
4✔
492

2✔
493
    return wrap_err([&]() {
4✔
494
        if (out_index) {
4✔
495
            *out_index = results->index_of(value->get_obj());
4✔
496
            if (out_found && *out_index != realm::not_found)
4✔
497
                *out_found = true;
2✔
498
        }
4✔
499
        return true;
4✔
500
    });
4✔
501
}
4✔
502

503
RLM_API bool realm_results_delete_all(realm_results_t* results)
504
{
10✔
505
    return wrap_err([&]() {
10✔
506
        // Note: This method is very confusingly named. It actually does erase
5✔
507
        // all the objects.
5✔
508
        results->clear();
10✔
509
        return true;
10✔
510
    });
10✔
511
}
10✔
512

513
RLM_API realm_results_t* realm_results_snapshot(const realm_results_t* results)
514
{
2✔
515
    return wrap_err([&]() {
2✔
516
        return new realm_results{results->snapshot()};
2✔
517
    });
2✔
518
}
2✔
519

520
RLM_API bool realm_results_min(realm_results_t* results, realm_property_key_t col, realm_value_t* out_value,
521
                               bool* out_found)
522
{
6✔
523
    return wrap_err([&]() {
6✔
524
        if (auto x = results->min(ColKey(col))) {
6✔
525
            if (out_found) {
2✔
526
                *out_found = true;
2✔
527
            }
2✔
528
            if (out_value) {
2✔
529
                *out_value = to_capi(*x);
2✔
530
            }
2✔
531
        }
2✔
532
        else {
4✔
533
            if (out_found) {
4✔
534
                *out_found = false;
2✔
535
            }
2✔
536
            if (out_value) {
4✔
537
                out_value->type = RLM_TYPE_NULL;
2✔
538
            }
2✔
539
        }
4✔
540
        return true;
6✔
541
    });
6✔
542
}
6✔
543

544
RLM_API bool realm_results_max(realm_results_t* results, realm_property_key_t col, realm_value_t* out_value,
545
                               bool* out_found)
546
{
6✔
547
    return wrap_err([&]() {
6✔
548
        if (auto x = results->max(ColKey(col))) {
6✔
549
            if (out_found) {
2✔
550
                *out_found = true;
2✔
551
            }
2✔
552
            if (out_value) {
2✔
553
                *out_value = to_capi(*x);
2✔
554
            }
2✔
555
        }
2✔
556
        else {
4✔
557
            if (out_found) {
4✔
558
                *out_found = false;
2✔
559
            }
2✔
560
            if (out_value) {
4✔
561
                out_value->type = RLM_TYPE_NULL;
2✔
562
            }
2✔
563
        }
4✔
564
        return true;
6✔
565
    });
6✔
566
}
6✔
567

568
RLM_API bool realm_results_sum(realm_results_t* results, realm_property_key_t col, realm_value_t* out_value,
569
                               bool* out_found)
570
{
6✔
571
    return wrap_err([&]() {
6✔
572
        if (out_found) {
6✔
573
            *out_found = results->size() != 0;
4✔
574
        }
4✔
575

3✔
576
        if (auto x = results->sum(ColKey(col))) {
6✔
577
            if (out_value)
4✔
578
                *out_value = to_capi(*x);
4✔
579
        }
4✔
580
        else {
2✔
581
            // Note: This can only be hit when the `m_table` and `m_collection`
1✔
582
            // pointers in `Results` are NULL.
1✔
583
            //
1✔
584
            // FIXME: It is unclear when that happens.
1✔
585

1✔
586
            // LCOV_EXCL_START
1✔
587
            if (out_value) {
2✔
UNCOV
588
                out_value->type = RLM_TYPE_NULL;
×
UNCOV
589
            }
×
590
            // LCOV_EXCL_STOP
1✔
591
        }
2✔
592
        return true;
6✔
593
    });
6✔
594
}
6✔
595

596
RLM_API bool realm_results_average(realm_results_t* results, realm_property_key_t col, realm_value_t* out_value,
597
                                   bool* out_found)
598
{
6✔
599
    return wrap_err([&]() {
6✔
600
        if (auto x = results->average(ColKey(col))) {
6✔
601
            if (out_found) {
2✔
602
                *out_found = true;
2✔
603
            }
2✔
604
            if (out_value) {
2✔
605
                *out_value = to_capi(*x);
2✔
606
            }
2✔
607
        }
2✔
608
        else {
4✔
609
            if (out_found) {
4✔
610
                *out_found = false;
2✔
611
            }
2✔
612
            if (out_value) {
4✔
613
                out_value->type = RLM_TYPE_NULL;
2✔
614
            }
2✔
615
        }
4✔
616
        return true;
6✔
617
    });
6✔
618
}
6✔
619

620
RLM_API realm_results_t* realm_results_from_thread_safe_reference(const realm_t* realm,
621
                                                                  realm_thread_safe_reference_t* tsr)
622
{
4✔
623
    return wrap_err([&]() {
4✔
624
        auto rtsr = dynamic_cast<realm_results::thread_safe_reference*>(tsr);
4✔
625
        if (!rtsr) {
4✔
626
            throw LogicError{ErrorCodes::IllegalOperation, "Thread safe reference type mismatch"};
2✔
627
        }
2✔
628

1✔
629
        auto results = rtsr->resolve<Results>(*realm);
2✔
630
        return new realm_results_t{std::move(results)};
2✔
631
    });
2✔
632
}
4✔
633

634
RLM_API realm_results_t* realm_results_resolve_in(realm_results_t* from_results, const realm_t* target_realm)
635
{
6✔
636
    return wrap_err([&]() {
6✔
637
        const auto& realm = *target_realm;
6✔
638
        auto resolved_results = from_results->freeze(realm);
6✔
639
        return new realm_results_t{std::move(resolved_results)};
6✔
640
    });
6✔
641
}
6✔
642

643
} // 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