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

realm / realm-core / daniel.tabacaru_887

07 Aug 2024 08:36PM UTC coverage: 91.108% (+0.02%) from 91.087%
daniel.tabacaru_887

Pull #7963

Evergreen

danieltabacaru
Unregister SyncSession callbacks when SyncManager is destroyed
Pull Request #7963: RJS-2784 Fix callback crashes when reloading with React Native

102796 of 181584 branches covered (56.61%)

35 of 37 new or added lines in 2 files covered. (94.59%)

294 existing lines in 9 files now uncovered.

217072 of 238259 relevant lines covered (91.11%)

5903576.39 hits per line

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

69.04
/src/realm/query_conditions.hpp
1
/*************************************************************************
2
 *
3
 * Copyright 2016 Realm Inc.
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 **************************************************************************/
18

19
#ifndef REALM_QUERY_CONDITIONS_HPP
20
#define REALM_QUERY_CONDITIONS_HPP
21

22
#include <cstdint>
23
#include <string>
24

25
#include <realm/query_state.hpp>
26
#include <realm/unicode.hpp>
27
#include <realm/binary_data.hpp>
28
#include <realm/query_value.hpp>
29
#include <realm/mixed.hpp>
30
#include <realm/utilities.hpp>
31

32
namespace realm {
33

34
// Quick hack to make "Queries with Integer null columns" able to compile in Visual Studio 2015 which doesn't full
35
// support sfinae
36
// (real cause hasn't been investigated yet, cannot exclude that we don't obey c++11 standard)
37
struct HackClass {
38
    template <class A, class B, class C>
39
    bool can_match(A, B, C)
40
    {
41
        REALM_ASSERT(false);
42
        return false;
43
    }
44
    template <class A, class B, class C>
45
    bool will_match(A, B, C)
46
    {
47
        REALM_ASSERT(false);
48
        return false;
49
    }
50
};
51

52
// Does v2 contain v1?
53
struct Contains : public HackClass {
54
    bool operator()(StringData v1, const char*, const char*, StringData v2, bool = false, bool = false) const
UNCOV
55
    {
×
UNCOV
56
        return v2.contains(v1);
×
UNCOV
57
    }
×
58
    bool operator()(StringData v1, StringData v2, bool = false, bool = false) const
59
    {
10,146✔
60
        return v2.contains(v1);
10,146✔
61
    }
10,146✔
62
    bool operator()(BinaryData v1, BinaryData v2, bool = false, bool = false) const
63
    {
5,370✔
64
        return v2.contains(v1);
5,370✔
65
    }
5,370✔
66
    bool operator()(StringData v1, const std::array<uint8_t, 256>& charmap, StringData v2) const
67
    {
33,384✔
68
        return v2.contains(v1, charmap);
33,384✔
69
    }
33,384✔
70

71
    bool operator()(const QueryValue& m1, const QueryValue& m2) const
72
    {
15,324✔
73
        if (m1.is_null())
15,324✔
74
            return !m2.is_null();
36✔
75
        if (m1.is_type(type_String) && m2.is_type(type_String)) {
15,288✔
76
            return operator()(m1.get<StringData>(), m2.get<StringData>(), false, false);
10,146✔
77
        }
10,146✔
78
        if (m1.is_type(type_Binary) && m2.is_type(type_Binary)) {
5,142✔
79
            return operator()(m1.get<BinaryData>(), m2.get<BinaryData>(), false, false);
648✔
80
        }
648✔
81
        return false;
4,494✔
82
    }
5,142✔
83

84
    template <class A, class B>
85
    bool operator()(A, B) const
86
    {
87
        REALM_ASSERT(false);
88
        return false;
89
    }
90
    template <class A, class B, class C, class D>
91
    bool operator()(A, B, C, D) const
UNCOV
92
    {
×
UNCOV
93
        REALM_ASSERT(false);
×
UNCOV
94
        return false;
×
UNCOV
95
    }
×
96
    bool operator()(int64_t, int64_t, bool, bool) const
UNCOV
97
    {
×
UNCOV
98
        REALM_ASSERT(false);
×
99
        return false;
×
100
    }
×
101

102
    static std::string description()
103
    {
276✔
104
        return "CONTAINS";
276✔
105
    }
276✔
106

107
    static const int condition = -1;
108
};
109

110
// Does v2 contain something like v1 (wildcard matching)?
111
struct Like : public HackClass {
112
    bool operator()(StringData v1, const char*, const char*, StringData v2, bool = false, bool = false) const
113
    {
32,964✔
114
        return v2.like(v1);
32,964✔
115
    }
32,964✔
116
    bool operator()(BinaryData b1, const char*, const char*, BinaryData b2, bool = false, bool = false) const
UNCOV
117
    {
×
UNCOV
118
        StringData s1(b1.data(), b1.size());
×
UNCOV
119
        StringData s2(b2.data(), b2.size());
×
UNCOV
120
        return s2.like(s1);
×
UNCOV
121
    }
×
122
    bool operator()(StringData v1, StringData v2, bool = false, bool = false) const
123
    {
9,546✔
124
        return v2.like(v1);
9,546✔
125
    }
9,546✔
126
    bool operator()(BinaryData b1, BinaryData b2, bool = false, bool = false) const
127
    {
768✔
128
        StringData s1(b1.data(), b1.size());
768✔
129
        StringData s2(b2.data(), b2.size());
768✔
130
        return s2.like(s1);
768✔
131
    }
768✔
132

133
    bool operator()(const QueryValue& m1, const QueryValue& m2) const
134
    {
14,586✔
135
        if (m1.is_null() && m2.is_null())
14,586✔
136
            return true;
36✔
137
        if (m1.is_type(type_String) && m2.is_type(type_String)) {
14,550✔
138
            return operator()(m1.get<StringData>(), m2.get<StringData>(), false, false);
9,546✔
139
        }
9,546✔
140
        if (m1.is_type(type_Binary) && m2.is_type(type_Binary)) {
5,004✔
141
            return operator()(m1.get<BinaryData>(), m2.get<BinaryData>(), false, false);
648✔
142
        }
648✔
143
        return false;
4,356✔
144
    }
5,004✔
145

146
    template <class A, class B>
147
    bool operator()(A, B) const
148
    {
149
        REALM_ASSERT(false);
150
        return false;
151
    }
152

153
    template <class A, class B, class C, class D>
154
    bool operator()(A, B, C, D) const
UNCOV
155
    {
×
UNCOV
156
        REALM_ASSERT(false);
×
UNCOV
157
        return false;
×
UNCOV
158
    }
×
159

160
    bool operator()(int64_t, int64_t, bool, bool) const
UNCOV
161
    {
×
UNCOV
162
        REALM_ASSERT(false);
×
163
        return false;
×
164
    }
×
165

166
    static std::string description()
167
    {
156✔
168
        return "LIKE";
156✔
169
    }
156✔
170

171
    static const int condition = -1;
172
};
173

174
// Does v2 begin with v1?
175
struct BeginsWith : public HackClass {
176
    bool operator()(StringData v1, const char*, const char*, StringData v2, bool = false, bool = false) const
177
    {
32,970✔
178
        return v2.begins_with(v1);
32,970✔
179
    }
32,970✔
180
    bool operator()(StringData v1, StringData v2, bool = false, bool = false) const
UNCOV
181
    {
×
UNCOV
182
        return v2.begins_with(v1);
×
UNCOV
183
    }
×
184
    bool operator()(BinaryData v1, BinaryData v2, bool = false, bool = false) const
185
    {
4,578✔
186
        return v2.begins_with(v1);
4,578✔
187
    }
4,578✔
188

189
    bool operator()(const QueryValue& m1, const QueryValue& m2) const
190
    {
19,806✔
191
        if (m1.is_type(type_String) && m2.is_type(type_String)) {
19,806✔
192
            StringData s1 = m1.get<StringData>();
11,292✔
193
            StringData s2 = m2.get<StringData>();
11,292✔
194
            return s2.begins_with(s1);
11,292✔
195
        }
11,292✔
196
        if (m1.is_type(type_Binary) && m2.is_type(type_Binary)) {
8,514✔
197
            BinaryData b1 = m1.get<BinaryData>();
672✔
198
            BinaryData b2 = m2.get<BinaryData>();
672✔
199
            return b2.begins_with(b1);
672✔
200
        }
672✔
201
        return false;
7,842✔
202
    }
8,514✔
203

204
    template <class A, class B, class C, class D>
205
    bool operator()(A, B, C, D) const
UNCOV
206
    {
×
UNCOV
207
        REALM_ASSERT(false);
×
UNCOV
208
        return false;
×
UNCOV
209
    }
×
210
    template <class A, class B>
211
    bool operator()(A, B) const
212
    {
213
        REALM_ASSERT(false);
214
        return false;
215
    }
216

217
    static std::string description()
218
    {
168✔
219
        return "BEGINSWITH";
168✔
220
    }
168✔
221

222
    static const int condition = -1;
223
};
224

225
// Does v2 end with v1?
226
struct EndsWith : public HackClass {
227
    bool operator()(StringData v1, const char*, const char*, StringData v2, bool = false, bool = false) const
228
    {
32,970✔
229
        return v2.ends_with(v1);
32,970✔
230
    }
32,970✔
231
    bool operator()(StringData v1, StringData v2, bool = false, bool = false) const
232
    {
10,224✔
233
        return v2.ends_with(v1);
10,224✔
234
    }
10,224✔
235
    bool operator()(BinaryData v1, BinaryData v2, bool = false, bool = false) const
236
    {
5,274✔
237
        return v2.ends_with(v1);
5,274✔
238
    }
5,274✔
239

240
    bool operator()(const QueryValue& m1, const QueryValue& m2) const
241
    {
21,810✔
242

243
        if (m1.is_type(type_String) && m2.is_type(type_String)) {
21,810✔
244
            return operator()(m1.get<StringData>(), m2.get<StringData>(), false, false);
10,224✔
245
        }
10,224✔
246
        if (m1.is_type(type_Binary) && m2.is_type(type_Binary)) {
11,586✔
247
            return operator()(m1.get<BinaryData>(), m2.get<BinaryData>(), false, false);
696✔
248
        }
696✔
249
        return false;
10,890✔
250
    }
11,586✔
251

252
    template <class A, class B>
253
    bool operator()(A, B) const
254
    {
255
        REALM_ASSERT(false);
256
        return false;
257
    }
258
    template <class A, class B, class C, class D>
259
    bool operator()(A, B, C, D) const
260
    {
×
261
        REALM_ASSERT(false);
×
262
        return false;
×
UNCOV
263
    }
×
264

265
    static std::string description()
266
    {
174✔
267
        return "ENDSWITH";
174✔
268
    }
174✔
269

270
    static const int condition = -1;
271
};
272

273
struct Equal {
274
    static const int avx = 0x00; // _CMP_EQ_OQ
275
    //    bool operator()(const bool v1, const bool v2, bool v1null = false, bool v2null = false) const { return v1 ==
276
    //    v2; }
277
    bool operator()(StringData v1, const char*, const char*, StringData v2, bool = false, bool = false) const
UNCOV
278
    {
×
UNCOV
279
        return v1 == v2;
×
UNCOV
280
    }
×
281
    bool operator()(BinaryData v1, BinaryData v2, bool = false, bool = false) const
282
    {
2,481,528✔
283
        return v1 == v2;
2,481,528✔
284
    }
2,481,528✔
285

286
    bool operator()(const QueryValue& m1, const QueryValue& m2) const
287
    {
8,038,077✔
288
        return (m1.is_null() && m2.is_null()) || (Mixed::types_are_comparable(m1, m2) && (m1 == m2));
8,038,077✔
289
    }
8,038,077✔
290

291
    template <class T>
292
    bool operator()(const T& v1, const T& v2, bool v1null = false, bool v2null = false) const
293
    {
4,633,709✔
294
        return (v1null && v2null) || (!v1null && !v2null && v1 == v2);
4,633,709✔
295
    }
4,633,709✔
296
    static const int condition = cond_Equal;
297
    bool can_match(int64_t v, int64_t lbound, int64_t ubound)
298
    {
17,124,951✔
299
        return (v >= lbound && v <= ubound);
17,401,851✔
300
    }
17,124,951✔
301
    bool will_match(int64_t v, int64_t lbound, int64_t ubound)
302
    {
17,333,925✔
303
        return (v == 0 && ubound == 0 && lbound == 0);
17,333,925✔
304
    }
17,333,925✔
305

306
    static std::string description()
307
    {
37,167✔
308
        return "==";
37,167✔
309
    }
37,167✔
310
};
311

312
struct NotEqual {
313
    static const int avx = 0x0B; // _CMP_FALSE_OQ
314
    bool operator()(StringData v1, const char*, const char*, StringData v2, bool = false, bool = false) const
315
    {
118,764✔
316
        return v1 != v2;
118,764✔
317
    }
118,764✔
318
    // bool operator()(BinaryData v1, BinaryData v2, bool = false, bool = false) const { return v1 != v2; }
319

320
    template <class T>
321
    bool operator()(const T& v1, const T& v2, bool v1null = false, bool v2null = false) const
322
    {
19,774,428✔
323
        if (!v1null && !v2null)
19,774,428✔
324
            return v1 != v2;
19,721,529✔
325

326
        if (v1null && v2null)
52,899✔
327
            return false;
20,458✔
328

329
        return true;
32,441✔
330
    }
52,899✔
331

332
    bool operator()(const QueryValue& m1, const Mixed& m2) const
UNCOV
333
    {
×
UNCOV
334
        return !Equal()(m1, m2);
×
UNCOV
335
    }
×
336

337

338
    static const int condition = cond_NotEqual;
339
    bool can_match(int64_t v, int64_t lbound, int64_t ubound)
340
    {
301,674✔
341
        return !(v == 0 && ubound == 0 && lbound == 0);
301,674✔
342
    }
301,674✔
343
    bool will_match(int64_t v, int64_t lbound, int64_t ubound)
344
    {
300,087✔
345
        return (v > ubound || v < lbound);
300,087✔
346
    }
300,087✔
347

348
    template <class A, class B, class C, class D>
349
    bool operator()(A, B, C, D) const = delete;
350

351
    static std::string description()
352
    {
2,856✔
353
        return "!=";
2,856✔
354
    }
2,856✔
355
};
356

357
// Does v2 contain v1?
358
struct ContainsIns : public HackClass {
359
    bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2, bool = false,
360
                    bool = false) const
UNCOV
361
    {
×
UNCOV
362
        if (v2.is_null() && !v1.is_null())
×
UNCOV
363
            return false;
×
UNCOV
364

×
UNCOV
365
        if (v1.size() == 0 && !v2.is_null())
×
UNCOV
366
            return true;
×
UNCOV
367

×
UNCOV
368
        return search_case_fold(v2, v1_upper, v1_lower, v1.size()) != v2.size();
×
UNCOV
369
    }
×
370

371
    // Slow version, used if caller hasn't stored an upper and lower case version
372
    bool operator()(StringData v1, StringData v2, bool = false, bool = false) const
373
    {
17,562✔
374
        if (v2.is_null() && !v1.is_null())
17,562✔
375
            return false;
24✔
376

377
        if (v1.size() == 0 && !v2.is_null())
17,538✔
378
            return true;
8,220✔
379

380
        std::string v1_upper = case_map(v1, true, IgnoreErrors);
9,318✔
381
        std::string v1_lower = case_map(v1, false, IgnoreErrors);
9,318✔
382
        return search_case_fold(v2, v1_upper.c_str(), v1_lower.c_str(), v1.size()) != v2.size();
9,318✔
383
    }
17,538✔
384
    bool operator()(BinaryData b1, BinaryData b2, bool = false, bool = false) const
385
    {
192✔
386
        StringData s1(b1.data(), b1.size());
192✔
387
        StringData s2(b2.data(), b2.size());
192✔
388
        return this->operator()(s1, s2, false, false);
192✔
389
    }
192✔
390

391
    // Case insensitive Boyer-Moore version
392
    bool operator()(StringData v1, const char* v1_upper, const char* v1_lower,
393
                    const std::array<uint8_t, 256>& charmap, StringData v2) const
394
    {
7,470✔
395
        if (v2.is_null() && !v1.is_null())
7,470✔
396
            return false;
24✔
397

398
        if (v1.size() == 0 && !v2.is_null())
7,446✔
399
            return true;
24✔
400

401
        return contains_ins(v2, v1_upper, v1_lower, v1.size(), charmap);
7,422✔
402
    }
7,446✔
403

404
    bool operator()(const QueryValue& m1, const QueryValue& m2) const
405
    {
23,202✔
406
        if (m1.is_null())
23,202✔
407
            return !m2.is_null();
66✔
408
        if (m1.is_type(type_String) && m2.is_type(type_String)) {
23,136✔
409
            return operator()(m1.get<StringData>(), m2.get<StringData>(), false, false);
17,370✔
410
        }
17,370✔
411
        if (m1.is_type(type_Binary) && m2.is_type(type_Binary)) {
5,766✔
412
            return operator()(m1.get<BinaryData>(), m2.get<BinaryData>(), false, false);
72✔
413
        }
72✔
414
        return false;
5,694✔
415
    }
5,766✔
416

417
    template <class A, class B>
418
    bool operator()(A, B) const
419
    {
420
        REALM_ASSERT(false);
421
        return false;
422
    }
423
    template <class A, class B, class C, class D>
424
    bool operator()(A, B, C, D) const
UNCOV
425
    {
×
UNCOV
426
        REALM_ASSERT(false);
×
UNCOV
427
        return false;
×
UNCOV
428
    }
×
429
    bool operator()(int64_t, int64_t, bool, bool) const
UNCOV
430
    {
×
UNCOV
431
        REALM_ASSERT(false);
×
UNCOV
432
        return false;
×
UNCOV
433
    }
×
434

435
    static std::string description()
436
    {
402✔
437
        return "CONTAINS[c]";
402✔
438
    }
402✔
439

440
    static const int condition = -1;
441
};
442

443
// Does v2 contain something like v1 (wildcard matching)?
444
struct LikeIns : public HackClass {
445
    bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2, bool = false,
446
                    bool = false) const
447
    {
24,858✔
448
        if (v2.is_null() || v1.is_null()) {
24,858✔
449
            return (v2.is_null() && v1.is_null());
24,612✔
450
        }
24,612✔
451

452
        return string_like_ins(v2, v1_lower, v1_upper);
246✔
453
    }
24,858✔
454
    bool operator()(BinaryData b1, const char* b1_upper, const char* b1_lower, BinaryData b2, bool = false,
455
                    bool = false) const
UNCOV
456
    {
×
UNCOV
457
        if (b2.is_null() || b1.is_null()) {
×
UNCOV
458
            return (b2.is_null() && b1.is_null());
×
UNCOV
459
        }
×
UNCOV
460
        StringData s2(b2.data(), b2.size());
×
UNCOV
461

×
UNCOV
462
        return string_like_ins(s2, b1_lower, b1_upper);
×
UNCOV
463
    }
×
464

465
    // Slow version, used if caller hasn't stored an upper and lower case version
466
    bool operator()(StringData v1, StringData v2, bool = false, bool = false) const
467
    {
11,952✔
468
        if (v2.is_null() || v1.is_null()) {
11,952✔
UNCOV
469
            return (v2.is_null() && v1.is_null());
×
UNCOV
470
        }
×
471

472
        std::string v1_upper = case_map(v1, true, IgnoreErrors);
11,952✔
473
        std::string v1_lower = case_map(v1, false, IgnoreErrors);
11,952✔
474
        return string_like_ins(v2, v1_lower, v1_upper);
11,952✔
475
    }
11,952✔
476
    bool operator()(BinaryData b1, BinaryData b2, bool = false, bool = false) const
477
    {
180✔
478
        if (b2.is_null() || b1.is_null()) {
180✔
479
            return (b2.is_null() && b1.is_null());
84✔
480
        }
84✔
481
        StringData s1(b1.data(), b1.size());
96✔
482
        StringData s2(b2.data(), b2.size());
96✔
483

484
        std::string s1_upper = case_map(s1, true, IgnoreErrors);
96✔
485
        std::string s1_lower = case_map(s1, false, IgnoreErrors);
96✔
486
        return string_like_ins(s2, s1_lower, s1_upper);
96✔
487
    }
180✔
488

489
    bool operator()(const QueryValue& m1, const QueryValue& m2) const
490
    {
14,028✔
491
        if (m1.is_null() && m2.is_null())
14,028✔
492
            return true;
42✔
493
        if (m1.is_type(type_String) && m2.is_type(type_String)) {
13,986✔
494
            return operator()(m1.get<StringData>(), m2.get<StringData>(), false, false);
11,952✔
495
        }
11,952✔
496
        if (m1.is_type(type_Binary) && m2.is_type(type_Binary)) {
2,034✔
497
            return operator()(m1.get<BinaryData>(), m2.get<BinaryData>(), false, false);
60✔
498
        }
60✔
499
        return false;
1,974✔
500
    }
2,034✔
501

502
    template <class A, class B>
503
    bool operator()(A, B) const
504
    {
505
        REALM_ASSERT(false);
506
        return false;
507
    }
508
    template <class A, class B, class C, class D>
509
    bool operator()(A, B, C, D) const
UNCOV
510
    {
×
UNCOV
511
        REALM_ASSERT(false);
×
UNCOV
512
        return false;
×
UNCOV
513
    }
×
514
    bool operator()(int64_t, int64_t, bool, bool) const
UNCOV
515
    {
×
UNCOV
516
        REALM_ASSERT(false);
×
UNCOV
517
        return false;
×
UNCOV
518
    }
×
519

520
    static std::string description()
521
    {
228✔
522
        return "LIKE[c]";
228✔
523
    }
228✔
524

525
    static const int condition = -1;
526
};
527

528
// Does v2 begin with v1?
529
struct BeginsWithIns : public HackClass {
530
    bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2, bool = false,
531
                    bool = false) const
532
    {
24,714✔
533
        if (v2.is_null() && !v1.is_null())
24,714✔
534
            return false;
18✔
535
        return v1.size() <= v2.size() && equal_case_fold(v2.prefix(v1.size()), v1_upper, v1_lower);
24,696✔
536
    }
24,714✔
537

538
    // Slow version, used if caller hasn't stored an upper and lower case version
539
    bool operator()(StringData v1, StringData v2, bool = false, bool = false) const
540
    {
12,336✔
541
        if (v2.is_null() && !v1.is_null())
12,336✔
542
            return false;
24✔
543

544
        if (v1.size() > v2.size())
12,312✔
545
            return false;
396✔
546
        std::string v1_upper = case_map(v1, true, IgnoreErrors);
11,916✔
547
        std::string v1_lower = case_map(v1, false, IgnoreErrors);
11,916✔
548
        return equal_case_fold(v2.prefix(v1.size()), v1_upper.c_str(), v1_lower.c_str());
11,916✔
549
    }
12,312✔
550
    bool operator()(BinaryData b1, BinaryData b2, bool = false, bool = false) const
551
    {
192✔
552
        StringData s1(b1.data(), b1.size());
192✔
553
        StringData s2(b2.data(), b2.size());
192✔
554
        return this->operator()(s1, s2, false, false);
192✔
555
    }
192✔
556

557
    bool operator()(const QueryValue& m1, const QueryValue& m2) const
558
    {
15,582✔
559
        if (m1.is_type(type_String) && m2.is_type(type_String)) {
15,582✔
560
            return operator()(m1.get<StringData>(), m2.get<StringData>(), false, false);
12,144✔
561
        }
12,144✔
562
        if (m1.is_type(type_Binary) && m2.is_type(type_Binary)) {
3,438✔
563
            return operator()(m1.get<BinaryData>(), m2.get<BinaryData>(), false, false);
72✔
564
        }
72✔
565
        return false;
3,366✔
566
    }
3,438✔
567

568
    template <class A, class B>
569
    bool operator()(A, B) const
570
    {
571
        REALM_ASSERT(false);
572
        return false;
573
    }
574
    template <class A, class B, class C, class D>
575
    bool operator()(A, B, C, D) const
UNCOV
576
    {
×
UNCOV
577
        REALM_ASSERT(false);
×
UNCOV
578
        return false;
×
UNCOV
579
    }
×
580
    bool operator()(int64_t, int64_t, bool, bool) const
UNCOV
581
    {
×
UNCOV
582
        REALM_ASSERT(false);
×
UNCOV
583
        return false;
×
UNCOV
584
    }
×
585

586
    static std::string description()
587
    {
252✔
588
        return "BEGINSWITH[c]";
252✔
589
    }
252✔
590

591
    static const int condition = -1;
592
};
593

594
// Does v2 end with v1?
595
struct EndsWithIns : public HackClass {
596
    bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2, bool = false,
597
                    bool = false) const
598
    {
24,792✔
599
        if (v2.is_null() && !v1.is_null())
24,792✔
600
            return false;
18✔
601

602
        return v1.size() <= v2.size() && equal_case_fold(v2.suffix(v1.size()), v1_upper, v1_lower);
24,774✔
603
    }
24,792✔
604

605
    // Slow version, used if caller hasn't stored an upper and lower case version
606
    bool operator()(StringData v1, StringData v2, bool = false, bool = false) const
607
    {
12,102✔
608
        if (v2.is_null() && !v1.is_null())
12,102✔
609
            return false;
24✔
610

611
        if (v1.size() > v2.size())
12,078✔
612
            return false;
336✔
613
        std::string v1_upper = case_map(v1, true, IgnoreErrors);
11,742✔
614
        std::string v1_lower = case_map(v1, false, IgnoreErrors);
11,742✔
615
        return equal_case_fold(v2.suffix(v1.size()), v1_upper.c_str(), v1_lower.c_str());
11,742✔
616
    }
12,078✔
617
    bool operator()(BinaryData b1, BinaryData b2, bool = false, bool = false) const
618
    {
180✔
619
        StringData s1(b1.data(), b1.size());
180✔
620
        StringData s2(b2.data(), b2.size());
180✔
621
        return this->operator()(s1, s2, false, false);
180✔
622
    }
180✔
623

624
    bool operator()(const QueryValue& m1, const QueryValue& m2) const
625
    {
13,812✔
626
        if (m1.is_type(type_String) && m2.is_type(type_String)) {
13,812✔
627
            return operator()(m1.get<StringData>(), m2.get<StringData>(), false, false);
11,922✔
628
        }
11,922✔
629
        if (m1.is_type(type_Binary) && m2.is_type(type_Binary)) {
1,890✔
630
            return operator()(m1.get<BinaryData>(), m2.get<BinaryData>(), false, false);
60✔
631
        }
60✔
632
        return false;
1,830✔
633
    }
1,890✔
634

635
    template <class A, class B>
636
    bool operator()(A, B) const
637
    {
638
        REALM_ASSERT(false);
639
        return false;
640
    }
641
    template <class A, class B, class C, class D>
642
    bool operator()(A, B, C, D) const
UNCOV
643
    {
×
UNCOV
644
        REALM_ASSERT(false);
×
UNCOV
645
        return false;
×
UNCOV
646
    }
×
647
    bool operator()(int64_t, int64_t, bool, bool) const
UNCOV
648
    {
×
UNCOV
649
        REALM_ASSERT(false);
×
UNCOV
650
        return false;
×
UNCOV
651
    }
×
652

653
    static std::string description()
654
    {
234✔
655
        return "ENDSWITH[c]";
234✔
656
    }
234✔
657

658
    static const int condition = -1;
659
};
660

661
struct EqualIns : public HackClass {
662
    bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2, bool = false,
663
                    bool = false) const
664
    {
25,674✔
665
        if (v1.is_null() != v2.is_null())
25,674✔
666
            return false;
24,582✔
667

668
        return v1.size() == v2.size() && equal_case_fold(v2, v1_upper, v1_lower);
1,092✔
669
    }
25,674✔
670

671
    // Slow version, used if caller hasn't stored an upper and lower case version
672
    bool operator()(StringData v1, StringData v2, bool = false, bool = false) const
673
    {
18,120✔
674
        if (v1.is_null() != v2.is_null())
18,120✔
UNCOV
675
            return false;
×
676

677
        if (v1.size() != v2.size())
18,120✔
678
            return false;
1,128✔
679
        std::string v1_upper = case_map(v1, true, IgnoreErrors);
16,992✔
680
        std::string v1_lower = case_map(v1, false, IgnoreErrors);
16,992✔
681
        return equal_case_fold(v2, v1_upper.c_str(), v1_lower.c_str());
16,992✔
682
    }
18,120✔
683
    bool operator()(BinaryData b1, BinaryData b2, bool = false, bool = false) const
684
    {
264✔
685
        StringData s1(b1.data(), b1.size());
264✔
686
        StringData s2(b2.data(), b2.size());
264✔
687
        return this->operator()(s1, s2, false, false);
264✔
688
    }
264✔
689

690
    bool operator()(const QueryValue& m1, const QueryValue& m2) const
691
    {
25,776✔
692
        if (m1.is_null() && m2.is_null()) {
25,776✔
693
            return true;
96✔
694
        }
96✔
695
        if (Mixed::types_are_comparable(m1, m2)) {
25,680✔
696
            if (m1.is_type(type_String) && m2.is_type(type_String)) {
18,564✔
697
                return operator()(m1.get<StringData>(), m2.get<StringData>(), false, false);
17,856✔
698
            }
17,856✔
699
            if (m1.is_type(type_Binary) && m2.is_type(type_Binary)) {
708✔
700
                return operator()(m1.get<BinaryData>(), m2.get<BinaryData>(), false, false);
264✔
701
            }
264✔
702
            return m1 == m2;
444✔
703
        }
708✔
704
        return false;
7,116✔
705
    }
25,680✔
706

707
    template <class A, class B>
708
    bool operator()(A, B) const
709
    {
710
        REALM_ASSERT(false);
711
        return false;
712
    }
713
    template <class A, class B, class C, class D>
714
    bool operator()(A, B, C, D) const
UNCOV
715
    {
×
UNCOV
716
        REALM_ASSERT(false);
×
UNCOV
717
        return false;
×
UNCOV
718
    }
×
719
    bool operator()(int64_t, int64_t, bool, bool) const
UNCOV
720
    {
×
UNCOV
721
        REALM_ASSERT(false);
×
UNCOV
722
        return false;
×
UNCOV
723
    }
×
724

725
    static std::string description()
726
    {
114✔
727
        return "==[c]";
114✔
728
    }
114✔
729

730
    static const int condition = -1;
731
};
732

733
struct NotEqualIns : public HackClass {
734
    bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2, bool = false,
735
                    bool = false) const
736
    {
24,624✔
737
        if (v1.is_null() != v2.is_null())
24,624✔
738
            return true;
24,522✔
739
        return v1.size() != v2.size() || !equal_case_fold(v2, v1_upper, v1_lower);
102✔
740
    }
24,624✔
741

742
    // Slow version, used if caller hasn't stored an upper and lower case version
743
    bool operator()(StringData v1, StringData v2, bool = false, bool = false) const
UNCOV
744
    {
×
UNCOV
745
        if (v1.is_null() != v2.is_null())
×
UNCOV
746
            return true;
×
747

UNCOV
748
        if (v1.size() != v2.size())
×
UNCOV
749
            return true;
×
UNCOV
750
        std::string v1_upper = case_map(v1, true, IgnoreErrors);
×
UNCOV
751
        std::string v1_lower = case_map(v1, false, IgnoreErrors);
×
UNCOV
752
        return !equal_case_fold(v2, v1_upper.c_str(), v1_lower.c_str());
×
UNCOV
753
    }
×
754
    bool operator()(BinaryData b1, BinaryData b2, bool = false, bool = false) const
UNCOV
755
    {
×
756
        StringData s1(b1.data(), b1.size());
×
757
        StringData s2(b2.data(), b2.size());
×
758
        return this->operator()(s1, s2, false, false);
×
759
    }
×
760

761
    bool operator()(const QueryValue& m1, const QueryValue& m2) const
762
    {
14,556✔
763
        return !EqualIns()(m1, m2);
14,556✔
764
    }
14,556✔
765

766
    template <class A, class B>
767
    bool operator()(A, B) const
768
    {
769
        REALM_ASSERT(false);
770
        return false;
771
    }
772
    template <class A, class B, class C, class D>
773
    bool operator()(A, B, C, D) const
UNCOV
774
    {
×
UNCOV
775
        REALM_ASSERT(false);
×
UNCOV
776
        return false;
×
UNCOV
777
    }
×
778

779
    static std::string description()
780
    {
54✔
781
        return "!=[c]";
54✔
782
    }
54✔
783

784
    static const int condition = -1;
785
};
786

787
struct Greater {
788
    static const int avx = 0x1E; // _CMP_GT_OQ
789
    template <class T>
790
    bool operator()(const T& v1, const T& v2, bool v1null = false, bool v2null = false) const
791
    {
232,761✔
792
        if (v1null || v2null)
232,761✔
793
            return false;
172✔
794

795
        return v1 > v2;
232,589✔
796
    }
232,761✔
797
    bool operator()(const QueryValue& m1, const QueryValue& m2) const
798
    {
1,336,305✔
799
        return Mixed::types_are_comparable(m1, m2) && (m1 > m2);
1,336,305✔
800
    }
1,336,305✔
801
    static const int condition = cond_Greater;
802
    template <class A, class B, class C, class D>
803
    bool operator()(A, B, C, D) const
804
    {
805
        REALM_ASSERT(false);
806
        return false;
807
    }
808

809
    bool can_match(int64_t v, int64_t lbound, int64_t ubound)
810
    {
427,503✔
811
        static_cast<void>(lbound);
427,503✔
812
        return ubound > v;
427,503✔
813
    }
427,503✔
814
    bool will_match(int64_t v, int64_t lbound, int64_t ubound)
815
    {
416,724✔
816
        static_cast<void>(ubound);
416,724✔
817
        return lbound > v;
416,724✔
818
    }
416,724✔
819

820
    static std::string description()
821
    {
2,517✔
822
        return ">";
2,517✔
823
    }
2,517✔
824
};
825

826
struct None {
827
    template <class T>
828
    bool operator()(const T&, const T&, bool = false, bool = false) const
829
    {
×
830
        return true;
×
831
    }
×
832
    static const int condition = cond_None;
833
    template <class A, class B, class C, class D>
834
    bool operator()(A, B, C, D) const
835
    {
836
        REALM_ASSERT(false);
837
        return false;
838
    }
839
    bool can_match(int64_t v, int64_t lbound, int64_t ubound)
UNCOV
840
    {
×
UNCOV
841
        static_cast<void>(lbound);
×
UNCOV
842
        static_cast<void>(ubound);
×
UNCOV
843
        static_cast<void>(v);
×
UNCOV
844
        return true;
×
845
    }
×
846
    bool will_match(int64_t v, int64_t lbound, int64_t ubound)
847
    {
×
UNCOV
848
        static_cast<void>(lbound);
×
UNCOV
849
        static_cast<void>(ubound);
×
UNCOV
850
        static_cast<void>(v);
×
UNCOV
851
        return true;
×
UNCOV
852
    }
×
853

854
    static std::string description()
UNCOV
855
    {
×
856
        return "none";
×
857
    }
×
858
};
859

860
struct NotNull {
861
    template <class T>
862
    bool operator()(const T&, const T&, bool v = false, bool = false) const
863
    {
×
864
        return !v;
×
865
    }
×
866
    static const int condition = cond_LeftNotNull;
867
    template <class A, class B, class C, class D>
868
    bool operator()(A, B, C, D) const
869
    {
870
        REALM_ASSERT(false);
871
        return false;
872
    }
873
    bool can_match(int64_t v, int64_t lbound, int64_t ubound)
UNCOV
874
    {
×
UNCOV
875
        static_cast<void>(lbound);
×
UNCOV
876
        static_cast<void>(ubound);
×
UNCOV
877
        static_cast<void>(v);
×
UNCOV
878
        return true;
×
UNCOV
879
    }
×
880
    bool will_match(int64_t v, int64_t lbound, int64_t ubound)
UNCOV
881
    {
×
UNCOV
882
        static_cast<void>(lbound);
×
UNCOV
883
        static_cast<void>(ubound);
×
UNCOV
884
        static_cast<void>(v);
×
UNCOV
885
        return true;
×
UNCOV
886
    }
×
887
    static std::string description()
UNCOV
888
    {
×
UNCOV
889
        return "!= NULL";
×
UNCOV
890
    }
×
891
};
892

893

894
struct Less {
895
    static const int avx = 0x11; // _CMP_LT_OQ
896
    template <class T>
897
    bool operator()(const T& v1, const T& v2, bool v1null = false, bool v2null = false) const
898
    {
101,916✔
899
        if (v1null || v2null)
101,916✔
900
            return false;
118✔
901

902
        return v1 < v2;
101,798✔
903
    }
101,916✔
904

905
    bool operator()(const QueryValue& m1, const QueryValue& m2) const
906
    {
373,650✔
907
        return Mixed::types_are_comparable(m1, m2) && (m1 < m2);
373,650✔
908
    }
373,650✔
909

910
    template <class A, class B, class C, class D>
911
    bool operator()(A, B, C, D) const
912
    {
913
        REALM_ASSERT(false);
914
        return false;
915
    }
916
    static const int condition = cond_Less;
917
    bool can_match(int64_t v, int64_t lbound, int64_t ubound)
918
    {
175,665✔
919
        static_cast<void>(ubound);
175,665✔
920
        return lbound < v;
175,665✔
921
    }
175,665✔
922
    bool will_match(int64_t v, int64_t lbound, int64_t ubound)
923
    {
172,389✔
924
        static_cast<void>(lbound);
172,389✔
925
        return ubound < v;
172,389✔
926
    }
172,389✔
927
    static std::string description()
928
    {
477✔
929
        return "<";
477✔
930
    }
477✔
931
};
932

933
struct LessEqual : public HackClass {
934
    static const int avx = 0x12; // _CMP_LE_OQ
935
    template <class T>
936
    bool operator()(const T& v1, const T& v2, bool v1null = false, bool v2null = false) const
937
    {
737,552✔
938
        if (v1null && v2null)
737,552!
939
            return true;
10✔
940

941
        return (!v1null && !v2null && v1 <= v2);
737,542✔
942
    }
737,552✔
943
    bool operator()(const util::Optional<bool>& v1, const util::Optional<bool>& v2, bool v1null, bool v2null) const
UNCOV
944
    {
×
UNCOV
945
        if (v1null && v2null)
×
UNCOV
946
            return false;
×
947

UNCOV
948
        return (!v1null && !v2null && *v1 <= *v2);
×
UNCOV
949
    }
×
950

951
    bool operator()(const QueryValue& m1, const QueryValue& m2) const
952
    {
60,540✔
953
        return (m1.is_null() && m2.is_null()) || (Mixed::types_are_comparable(m1, m2) && (m1 <= m2));
60,540✔
954
    }
60,540✔
955

956
    template <class A, class B, class C, class D>
957
    bool operator()(A, B, C, D) const
958
    {
959
        REALM_ASSERT(false);
960
        return false;
961
    }
962
    static std::string description()
963
    {
252✔
964
        return "<=";
252✔
965
    }
252✔
966
    static const int condition = -1;
967
};
968

969
struct GreaterEqual : public HackClass {
970
    static const int avx = 0x1D; // _CMP_GE_OQ
971
    template <class T>
972
    bool operator()(const T& v1, const T& v2, bool v1null = false, bool v2null = false) const
973
    {
183,218✔
974
        if (v1null && v2null)
183,218!
975
            return true;
10✔
976

977
        return (!v1null && !v2null && v1 >= v2);
183,208✔
978
    }
183,218✔
979
    bool operator()(const util::Optional<bool>& v1, const util::Optional<bool>& v2, bool v1null, bool v2null) const
UNCOV
980
    {
×
UNCOV
981
        if (v1null && v2null)
×
UNCOV
982
            return false;
×
983

UNCOV
984
        return (!v1null && !v2null && *v1 >= *v2);
×
UNCOV
985
    }
×
986

987
    bool operator()(const QueryValue& m1, const QueryValue& m2) const
988
    {
66,666✔
989
        return (m1.is_null() && m2.is_null()) || (Mixed::types_are_comparable(m1, m2) && (m1 >= m2));
66,666✔
990
    }
66,666✔
991

992
    template <class A, class B, class C, class D>
993
    bool operator()(A, B, C, D) const
994
    {
995
        REALM_ASSERT(false);
996
        return false;
997
    }
998
    static std::string description()
999
    {
564✔
1000
        return ">=";
564✔
1001
    }
564✔
1002
    static const int condition = -1;
1003
};
1004

1005
} // namespace realm
1006

1007
#endif // REALM_QUERY_CONDITIONS_HPP
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