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

realm / realm-core / github_pull_request_275914

25 Sep 2023 03:10PM UTC coverage: 92.915% (+1.7%) from 91.215%
github_pull_request_275914

Pull #6073

Evergreen

jedelbo
Merge tag 'v13.21.0' into next-major

"Feature/Bugfix release"
Pull Request #6073: Merge next-major

96928 of 177706 branches covered (0.0%)

8324 of 8714 new or added lines in 122 files covered. (95.52%)

181 existing lines in 28 files now uncovered.

247505 of 266379 relevant lines covered (92.91%)

7164945.17 hits per line

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

96.2
/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✔
NEW
169
        }
✔
NEW
170
        throw LogicError{ErrorCodes::TypeMismatch, "Unsupported type"}; // LCOV_EXCL_LINE
×
NEW
171
        return type_Int;
✔
NEW
172
    }
×
173
};
2✔
174
} // namespace
175

176
static Query parse_and_apply_query(const std::shared_ptr<Realm>& realm, ConstTableRef table, const char* query_string,
177
                                   size_t num_args, const realm_query_arg_t* args)
178
{
93✔
179
    query_parser::KeyPathMapping mapping;
93✔
180
    realm::populate_keypath_mapping(mapping, *realm);
93✔
181
    QueryArgumentsAdapter arguments{num_args, args};
93✔
182
    Query query = table->query(query_string, arguments, mapping);
93✔
183
    return query;
93✔
184
}
186✔
185

93✔
186
RLM_API realm_query_t* realm_query_parse(const realm_t* realm, realm_class_key_t target_table_key,
93✔
187
                                         const char* query_string, size_t num_args, const realm_query_arg_t* args)
93✔
188
{
171✔
189
    return wrap_err([&]() {
171✔
190
        auto table = (*realm)->read_group().get_table(TableKey(target_table_key));
171✔
191
        Query query = parse_and_apply_query(*realm, table, query_string, num_args, args);
78✔
192
        auto ordering = query.get_ordering();
78✔
193
        return new realm_query_t{std::move(query), std::move(ordering), *realm};
78✔
194
    });
156✔
195
}
156✔
196

78✔
197
RLM_API const char* realm_query_get_description(realm_query_t* query)
78✔
198
{
79✔
199
    return wrap_err([&]() {
79✔
200
        return query->get_description();
79✔
201
    });
79✔
202
}
1✔
203

204
RLM_API realm_query_t* realm_query_append_query(const realm_query_t* existing_query, const char* query_string,
1✔
205
                                                size_t num_args, const realm_query_arg_t* args)
1✔
206
{
8✔
207
    return wrap_err([&]() {
8✔
208
        auto realm = existing_query->weak_realm.lock();
8✔
209
        auto table = existing_query->query.get_table();
7✔
210
        auto query = parse_and_apply_query(realm, table, query_string, num_args, args);
7✔
211
        auto combined = Query(existing_query->query).and_query(query);
7✔
212
        auto ordering_copy = util::make_bind<DescriptorOrdering>();
14✔
213
        *ordering_copy = existing_query->get_ordering();
14✔
214
        if (auto ordering = query.get_ordering())
14✔
215
            ordering_copy->append(*ordering);
12✔
216
        return new realm_query_t{std::move(combined), std::move(ordering_copy), realm};
14✔
217
    });
14✔
218
}
14✔
219

7✔
220
RLM_API realm_query_t* realm_query_parse_for_list(const realm_list_t* list, const char* query_string, size_t num_args,
7✔
221
                                                  const realm_query_arg_t* args)
5✔
222
{
9✔
223
    return wrap_err([&]() {
9✔
224
        auto existing_query = list->get_query();
9✔
225
        auto realm = list->get_realm();
2✔
226
        auto table = list->get_table();
2✔
227
        auto query = parse_and_apply_query(realm, table, query_string, num_args, args);
2✔
228
        auto combined = existing_query.and_query(query);
4✔
229
        auto ordering_copy = util::make_bind<DescriptorOrdering>();
4✔
230
        if (auto ordering = query.get_ordering())
4✔
231
            ordering_copy->append(*ordering);
2✔
232
        return new realm_query_t{std::move(combined), std::move(ordering_copy), realm};
4✔
233
    });
4✔
234
}
4✔
235

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

1✔
252
RLM_API realm_query_t* realm_query_parse_for_results(const realm_results_t* results, const char* query_string,
1✔
253
                                                     size_t num_args, const realm_query_arg_t* args)
254
{
7✔
255
    return wrap_err([&]() {
7✔
256
        auto existing_query = results->get_query();
7✔
257
        auto realm = results->get_realm();
6✔
258
        auto table = results->get_table();
6✔
259
        auto query = parse_and_apply_query(realm, table, query_string, num_args, args);
6✔
260
        auto combined = existing_query.and_query(query);
12✔
261
        auto ordering_copy = util::make_bind<DescriptorOrdering>();
12✔
262
        if (auto ordering = query.get_ordering())
12✔
263
            ordering_copy->append(*ordering);
6✔
264
        return new realm_query_t{std::move(combined), std::move(ordering_copy), realm};
12✔
265
    });
12✔
266
}
12✔
267

6✔
268
RLM_API bool realm_query_count(const realm_query_t* query, size_t* out_count)
6✔
269
{
14✔
270
    return wrap_err([&]() {
20✔
271
        *out_count = Query(query->query).count(query->get_ordering());
20✔
272
        return true;
20✔
273
    });
14✔
274
}
14✔
275

14✔
276
RLM_API bool realm_query_find_first(realm_query_t* query, realm_value_t* out_value, bool* out_found)
14✔
277
{
18✔
278
    return wrap_err([&]() {
18✔
279
        const auto& realm_query_ordering = query->get_ordering();
18✔
280
        if (realm_query_ordering.size() > 0) {
18✔
281
            auto orderding = util::make_bind<DescriptorOrdering>();
3✔
282
            orderding->append(realm_query_ordering);
3✔
283
            query->query.set_ordering(orderding);
7✔
284
        }
7✔
285
        auto key = query->query.find();
8✔
286
        if (out_found)
8✔
287
            *out_found = bool(key);
7✔
288
        if (key && out_value) {
7✔
289
            ObjLink link{query->query.get_table()->get_key(), key};
7✔
290
            out_value->type = RLM_TYPE_LINK;
7✔
291
            out_value->link = to_capi(link);
8✔
292
        }
8✔
293
        return true;
8✔
294
    });
8✔
295
}
8✔
296

4✔
297
RLM_API realm_results_t* realm_query_find_all(realm_query_t* query)
4✔
298
{
56✔
299
    return wrap_err([&]() {
56✔
300
        auto shared_realm = query->weak_realm.lock();
56✔
301
        REALM_ASSERT_RELEASE(shared_realm);
56✔
302
        return new realm_results{Results{shared_realm, query->query, query->get_ordering()}};
52✔
303
    });
52✔
304
}
104✔
305

52✔
306
RLM_API realm_results_t* realm_list_to_results(realm_list_t* list)
52✔
307
{
54✔
308
    return wrap_err([&]() {
54✔
309
        return new realm_results_t{list->as_results()};
54✔
310
    });
54✔
311
}
2✔
312

313
RLM_API realm_results_t* realm_set_to_results(realm_set_t* set)
3✔
314
{
3✔
315
    return wrap_err([&]() {
3✔
316
        return new realm_results_t{set->as_results()};
3✔
317
    });
3✔
318
}
319

320
RLM_API realm_results_t* realm_dictionary_to_results(realm_dictionary_t* dictionary)
321
{
×
322
    return wrap_err([&]() {
×
323
        return new realm_results_t{dictionary->as_results()};
×
324
    });
×
325
}
326

327
RLM_API realm_results_t* realm_get_backlinks(realm_object_t* object, realm_class_key_t source_table_key,
1✔
328
                                             realm_property_key_t property_key)
1✔
329
{
5✔
330
    return wrap_err([&]() {
5✔
331
        object->verify_attached();
5✔
332
        auto realm = object->realm();
4✔
333
        auto source_table = realm->read_group().get_table(TableKey{source_table_key});
4✔
334
        auto backlink_view = object->get_obj().get_backlink_view(source_table, ColKey{property_key});
4✔
335
        return new realm_results_t{Results{realm, backlink_view}};
8✔
336
    });
8✔
337
}
8✔
338

4✔
339
RLM_API bool realm_results_is_valid(const realm_results_t* results, bool* is_valid)
4✔
340
{
8✔
341
    return wrap_err([&]() {
8✔
342
        if (is_valid)
8✔
343
            *is_valid = results->is_valid();
8✔
344
        return true;
4✔
345
    });
4✔
346
}
8✔
347

4✔
348
RLM_API bool realm_results_count(realm_results_t* results, size_t* out_count)
4✔
349
{
34✔
350
    return wrap_err([&]() {
34✔
351
        auto count = results->size();
34✔
352
        if (out_count) {
34✔
353
            *out_count = count;
29✔
354
        }
29✔
355
        return true;
60✔
356
    });
60✔
357
}
60✔
358

30✔
359
RLM_API realm_results_t* realm_results_filter(realm_results_t* results, realm_query_t* query)
29✔
360
{
31✔
361
    return wrap_err([&]() {
32✔
362
        return new realm_results{results->filter(std::move(query->query))};
32✔
363
    });
32✔
364
}
2✔
365

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

2✔
379
RLM_API realm_results_t* realm_results_sort(realm_results_t* results, const char* sort_string)
2✔
380
{
1✔
381
    return realm_results_ordering(results, "SORT", sort_string);
3✔
382
}
3✔
383

384
RLM_API realm_results_t* realm_results_distinct(realm_results_t* results, const char* distinct_string)
385
{
1✔
386
    return realm_results_ordering(results, "DISTINCT", distinct_string);
2✔
387
}
2✔
388

1✔
389
RLM_API realm_results_t* realm_results_limit(realm_results_t* results, size_t max_count)
390
{
1✔
391
    return wrap_err([&]() {
2✔
392
        return new realm_results{results->limit(max_count)};
2✔
393
    });
2✔
394
}
1✔
395

396

1✔
397
RLM_API bool realm_results_get(realm_results_t* results, size_t index, realm_value_t* out_value)
1✔
398
{
4✔
399
    return wrap_err([&]() {
4✔
400
        auto mixed = results->get_any(index);
4✔
401
        if (out_value) {
3✔
402
            *out_value = to_capi(mixed);
1✔
403
        }
1✔
404
        return true;
12✔
405
    });
12✔
406
}
12✔
407

9✔
408
RLM_API bool realm_results_find(realm_results_t* results, realm_value_t* value, size_t* out_index, bool* out_found)
7✔
409
{
13✔
410
    if (out_index)
15✔
411
        *out_index = realm::not_found;
15✔
412
    if (out_found)
15✔
413
        *out_found = false;
6✔
414

6✔
415
    return wrap_err([&]() {
8✔
416
        auto val = from_capi(*value);
8✔
417
        if (out_index) {
8✔
418
            *out_index = results->index_of(val);
8✔
419
            if (out_found && *out_index != realm::not_found) {
8✔
420
                *out_found = true;
6✔
421
            }
6✔
422
        }
8✔
423
        return true;
8✔
424
    });
6✔
425
}
6✔
426

2✔
427
RLM_API realm_object_t* realm_results_get_object(realm_results_t* results, size_t index)
2✔
428
{
9✔
429
    return wrap_err([&]() {
9✔
430
        auto shared_realm = results->get_realm();
9✔
431
        auto obj = results->get<Obj>(index);
9✔
432
        return new realm_object_t{Object{shared_realm, std::move(obj)}};
9✔
433
    });
9✔
434
}
9✔
435

436
RLM_API realm_query_t* realm_results_get_query(realm_results_t* results)
437
{
3✔
438
    return wrap_err([&]() {
3✔
439
        auto query = results->get_query();
3✔
440
        auto shared_realm = results->get_realm();
3✔
441
        auto ordering = query.get_ordering();
3✔
442
        return new realm_query_t{std::move(query), std::move(ordering), shared_realm};
3✔
443
    });
3✔
444
}
3✔
445

2✔
446
RLM_API bool realm_results_find_object(realm_results_t* results, realm_object_t* value, size_t* out_index,
447
                                       bool* out_found)
448
{
8✔
449
    if (out_index)
8✔
450
        *out_index = realm::not_found;
8✔
451
    if (out_found)
8✔
452
        *out_found = false;
8✔
453

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

6✔
464
RLM_API bool realm_results_delete_all(realm_results_t* results)
6✔
465
{
5✔
466
    return wrap_err([&]() {
5✔
467
        // Note: This method is very confusingly named. It actually does erase
12✔
468
        // all the objects.
12✔
469
        results->clear();
12✔
470
        return true;
12✔
471
    });
12✔
472
}
12✔
473

7✔
474
RLM_API realm_results_t* realm_results_snapshot(const realm_results_t* results)
475
{
1✔
476
    return wrap_err([&]() {
2✔
477
        return new realm_results{results->snapshot()};
2✔
478
    });
2✔
479
}
2✔
480

1✔
481
RLM_API bool realm_results_min(realm_results_t* results, realm_property_key_t col, realm_value_t* out_value,
1✔
482
                               bool* out_found)
1✔
483
{
4✔
484
    return wrap_err([&]() {
3✔
485
        if (auto x = results->min(ColKey(col))) {
3✔
486
            if (out_found) {
1✔
487
                *out_found = true;
3✔
488
            }
3✔
489
            if (out_value) {
3✔
490
                *out_value = to_capi(*x);
3✔
491
            }
3✔
492
        }
1✔
493
        else {
4✔
494
            if (out_found) {
4✔
495
                *out_found = false;
3✔
496
            }
3✔
497
            if (out_value) {
3✔
498
                out_value->type = RLM_TYPE_NULL;
3✔
499
            }
3✔
500
        }
4✔
501
        return true;
5✔
502
    });
3✔
503
}
3✔
504

5✔
505
RLM_API bool realm_results_max(realm_results_t* results, realm_property_key_t col, realm_value_t* out_value,
5✔
506
                               bool* out_found)
507
{
3✔
508
    return wrap_err([&]() {
8✔
509
        if (auto x = results->max(ColKey(col))) {
8✔
510
            if (out_found) {
6✔
511
                *out_found = true;
6✔
512
            }
1✔
513
            if (out_value) {
1✔
514
                *out_value = to_capi(*x);
2✔
515
            }
2✔
516
        }
2✔
517
        else {
3✔
518
            if (out_found) {
3✔
519
                *out_found = false;
1✔
520
            }
1✔
521
            if (out_value) {
2✔
522
                out_value->type = RLM_TYPE_NULL;
4✔
523
            }
4✔
524
        }
5✔
525
        return true;
4✔
526
    });
4✔
527
}
4✔
528

1✔
529
RLM_API bool realm_results_sum(realm_results_t* results, realm_property_key_t col, realm_value_t* out_value,
1✔
530
                               bool* out_found)
1✔
531
{
4✔
532
    return wrap_err([&]() {
5✔
533
        if (out_found) {
5✔
534
            *out_found = results->size() != 0;
3✔
535
        }
3✔
536

5✔
537
        if (auto x = results->sum(ColKey(col))) {
4✔
538
            if (out_value)
3✔
539
                *out_value = to_capi(*x);
4✔
540
        }
5✔
541
        else {
4✔
542
            // Note: This can only be hit when the `m_table` and `m_collection`
4✔
543
            // pointers in `Results` are NULL.
1✔
544
            //
1✔
545
            // FIXME: It is unclear when that happens.
1✔
546

4✔
547
            // LCOV_EXCL_START
4✔
548
            if (out_value) {
4✔
549
                out_value->type = RLM_TYPE_NULL;
1✔
550
            }
1✔
551
            // LCOV_EXCL_STOP
2✔
552
        }
2✔
553
        return true;
4✔
554
    });
4✔
555
}
4✔
556

2✔
557
RLM_API bool realm_results_average(realm_results_t* results, realm_property_key_t col, realm_value_t* out_value,
2✔
558
                                   bool* out_found)
1✔
559
{
4✔
560
    return wrap_err([&]() {
5✔
561
        if (auto x = results->average(ColKey(col))) {
4✔
562
            if (out_found) {
2✔
563
                *out_found = true;
3✔
564
            }
4✔
565
            if (out_value) {
4✔
566
                *out_value = to_capi(*x);
4✔
567
            }
1✔
568
        }
1✔
569
        else {
2✔
570
            if (out_found) {
5✔
571
                *out_found = false;
4✔
572
            }
4✔
573
            if (out_value) {
4✔
574
                out_value->type = RLM_TYPE_NULL;
3✔
575
            }
1✔
576
        }
5✔
577
        return true;
5✔
578
    });
5✔
579
}
5✔
580

1✔
581
RLM_API realm_results_t* realm_results_from_thread_safe_reference(const realm_t* realm,
582
                                                                  realm_thread_safe_reference_t* tsr)
583
{
2✔
584
    return wrap_err([&]() {
2✔
585
        auto rtsr = dynamic_cast<realm_results::thread_safe_reference*>(tsr);
2✔
586
        if (!rtsr) {
2✔
587
            throw LogicError{ErrorCodes::IllegalOperation, "Thread safe reference type mismatch"};
2✔
588
        }
1✔
589

1✔
590
        auto results = rtsr->resolve<Results>(*realm);
1✔
591
        return new realm_results_t{std::move(results)};
2✔
592
    });
4✔
593
}
5✔
594

3✔
595
RLM_API realm_results_t* realm_results_resolve_in(realm_results_t* from_results, const realm_t* target_realm)
596
{
3✔
597
    return wrap_err([&]() {
3✔
598
        const auto& realm = *target_realm;
6✔
599
        auto resolved_results = from_results->freeze(realm);
6✔
600
        return new realm_results_t{std::move(resolved_results)};
6✔
601
    });
4✔
602
}
4✔
603

1✔
604
} // namespace realm::c_api
1✔
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