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

realm / realm-core / jorgen.edelbo_335

02 Jul 2024 08:47AM UTC coverage: 91.611% (+0.8%) from 90.829%
jorgen.edelbo_335

Pull #7858

Evergreen

jedelbo
Remove enum string feature
Pull Request #7858: Remove enum string feature

109846 of 188418 branches covered (58.3%)

32 of 32 new or added lines in 9 files covered. (100.0%)

16 existing lines in 8 files now uncovered.

225717 of 246386 relevant lines covered (91.61%)

7132264.59 hits per line

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

98.36
/src/realm/array_string.cpp
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
#include <realm/array_string.hpp>
20
#include <realm/impl/array_writer.hpp>
21
#include <realm/table.hpp>
22
#include <realm/string_interner.hpp>
23
#include <realm/mixed.hpp>
24

25
using namespace realm;
26

27
ArrayString::ArrayString(Allocator& a)
28
    : m_alloc(a)
35,299,188✔
29
{
74,784,294✔
30
    m_arr = new (&m_storage) ArrayStringShort(a, true);
74,784,294✔
31
}
74,784,294✔
32

33
void ArrayString::create()
34
{
260,760✔
35
    static_cast<ArrayStringShort*>(m_arr)->create();
260,760✔
36
}
260,760✔
37

38
void ArrayString::init_from_mem(MemRef mem) noexcept
39
{
73,147,308✔
40
    char* header = mem.get_addr();
73,147,308✔
41

42
    ArrayParent* parent = m_arr->get_parent();
73,147,308✔
43
    size_t ndx_in_parent = m_arr->get_ndx_in_parent();
73,147,308✔
44

45
    bool long_strings = Array::get_hasrefs_from_header(header);
73,147,308✔
46
    if (!long_strings) {
73,147,308✔
47
        // Small strings
48
        bool is_small = Array::get_wtype_from_header(header) == Array::wtype_Multiply;
68,498,994✔
49
        if (is_small) {
68,498,994✔
50
            auto arr = new (&m_storage) ArrayStringShort(m_alloc, m_nullable);
64,838,760✔
51
            arr->init_from_mem(mem);
64,838,760✔
52
            m_type = Type::small_strings;
64,838,760✔
53
        }
64,838,760✔
54
        else {
3,660,234✔
55
            auto arr = new (&m_storage) Array(m_alloc);
3,660,234✔
56
            arr->init_from_mem(mem);
3,660,234✔
57
            // The context flag is used to indicate interned strings vs old enum strings
58
            // (in conjunction with has_refs() == false)
852,036✔
59
            if (arr->get_context_flag_from_header(arr->get_header())) {
2,808,198✔
60
                // init for new interned strings (replacing old enum strings)
852,036✔
61
                m_type = Type::interned_strings;
33,558,729✔
62
                // consider if we want this invariant: REALM_ASSERT_DEBUG(m_string_interner);
1,956,441✔
63
            }
2,939,499✔
64
            else {
3,781,581✔
65
                // init for old enum strings
390,447✔
66
                m_string_enum_values = std::make_unique<ArrayString>(m_alloc);
2,215,587✔
67
                ArrayParent* p;
2,215,587✔
68
                REALM_ASSERT(m_spec != nullptr);
2,215,587✔
69
                REALM_ASSERT(m_col_ndx != realm::npos);
3,391,134✔
70
                ref_type r = m_spec->get_enumkeys_ref(m_col_ndx, p);
3,391,134✔
71
                m_string_enum_values->init_from_ref(r);
3,391,134✔
72
                m_string_enum_values->set_parent(p, m_col_ndx);
3,391,134✔
73
                m_type = Type::enum_strings;
3,391,134✔
74
            }
3,781,581✔
75
        }
37,340,310✔
76
    }
70,455,435✔
77
    else {
2,691,873✔
78
        bool is_big = Array::get_context_flag_from_header(header);
2,691,873✔
79
        if (!is_big) {
4,467,531✔
80
            auto arr = new (&m_storage) ArraySmallBlobs(m_alloc);
2,176,794✔
81
            arr->init_from_mem(mem);
2,176,794✔
82
            m_type = Type::medium_strings;
2,176,794✔
83
        }
401,136✔
84
        else {
2,290,737✔
85
            auto arr = new (&m_storage) ArrayBigBlobs(m_alloc, m_nullable);
2,291,259✔
86
            arr->init_from_mem(mem);
2,291,259✔
87
            m_type = Type::big_strings;
2,290,971✔
88
        }
2,290,971✔
89
    }
2,692,107✔
90
    m_arr->set_parent(parent, ndx_in_parent);
38,615,718✔
91
}
38,615,196✔
92

93
void ArrayString::init_from_parent()
248,010✔
94
{
3,525,252✔
95
    ref_type ref = m_arr->get_ref_from_parent();
3,277,242✔
96
    init_from_ref(ref);
3,277,242✔
97
}
3,525,252✔
98

248,010✔
99
void ArrayString::destroy() noexcept
248,010✔
100
{
522✔
101
    if (m_arr->is_attached()) {
522✔
102
        Array::destroy_deep(m_arr->get_ref(), m_alloc);
5,301,102✔
103
        detach();
5,301,102✔
104
    }
778,644✔
105
}
778,932✔
106

173,259✔
107
void ArrayString::detach() noexcept
173,259✔
108
{
4,419,966✔
109
    m_arr->detach();
4,419,966✔
110
    // Make sure the object is in a state like right after construction
177,480✔
111
    // Next call must be to create()
177,480✔
112
    m_arr = new (&m_storage) ArrayStringShort(m_alloc, true);
5,549,004✔
113
    m_type = Type::small_strings;
248,136✔
114
}
5,549,004✔
115

116
size_t ArrayString::size() const
117
{
6,925,023✔
118
    switch (m_type) {
6,925,023✔
119
        case Type::small_strings:
2,305,884✔
120
            return static_cast<ArrayStringShort*>(m_arr)->size();
2,305,884✔
121
        case Type::medium_strings:
239,274✔
122
            return static_cast<ArraySmallBlobs*>(m_arr)->size();
229,893✔
123
        case Type::big_strings:
4,193,394✔
124
            return static_cast<ArrayBigBlobs*>(m_arr)->size();
4,193,394✔
125
        case Type::enum_strings:
11,457✔
126
        case Type::interned_strings:
209,454✔
127
            return static_cast<Array*>(m_arr)->size();
209,454✔
128
    }
6,878,211✔
129
    return {};
1,788✔
130
}
6,878,211✔
131

1,788✔
132
void ArrayString::add(StringData value)
1,788✔
133
{
84,543✔
134
    switch (upgrade_leaf(value.size())) {
82,755✔
135
        case Type::small_strings:
102,036✔
136
            static_cast<ArrayStringShort*>(m_arr)->add(value);
102,036✔
137
            break;
53,436✔
138
        case Type::medium_strings:
13,692✔
139
            static_cast<ArraySmallBlobs*>(m_arr)->add_string(value);
995,112✔
140
            break;
995,112✔
141
        case Type::big_strings:
233,373✔
142
            static_cast<ArrayBigBlobs*>(m_arr)->add_string(value);
233,373✔
143
            break;
233,373✔
144
        case Type::enum_strings:
110,487✔
145
        case Type::interned_strings: {
112,275✔
146
            auto a = static_cast<Array*>(m_arr);
112,275✔
147
            size_t ndx = a->size();
386,295✔
148
            a->add(0);
386,295✔
149
            set(ndx, value);
386,295✔
150
            break;
268,965✔
151
        }
267,177✔
152
    }
349,932✔
153
}
349,932✔
154

155
void ArrayString::set(size_t ndx, StringData value)
981,420✔
156
{
3,407,472✔
157
    switch (upgrade_leaf(value.size())) {
2,426,052✔
158
        case Type::small_strings:
240,303✔
159
            static_cast<ArrayStringShort*>(m_arr)->set(ndx, value);
1,563,267✔
160
            break;
1,563,267✔
161
        case Type::medium_strings:
544,155✔
162
            static_cast<ArraySmallBlobs*>(m_arr)->set_string(ndx, value);
544,155✔
163
            break;
544,155✔
164
        case Type::big_strings:
545,586✔
165
            static_cast<ArrayBigBlobs*>(m_arr)->set_string(ndx, value);
545,586✔
166
            break;
545,586✔
167
        case Type::interned_strings: {
977,232✔
168
            auto id = m_string_interner->intern(value);
977,232✔
169
            static_cast<Array*>(m_arr)->set(ndx, id);
977,232✔
170
            break;
482,937✔
171
        }
129,636✔
172
        case Type::enum_strings: {
1,442,451✔
173
            size_t sz = m_string_enum_values->size();
1,442,451✔
174
            size_t res = m_string_enum_values->find_first(value, 0, sz);
1,312,815✔
175
            if (res == realm::not_found) {
2,635,779✔
176
                m_string_enum_values->add(value);
1,327,818✔
177
                res = sz;
4,854✔
178
            }
4,854✔
179
            static_cast<Array*>(m_arr)->set(ndx, res);
42,385,752✔
180
            break;
42,385,752✔
181
        }
31,593,945✔
182
    }
34,019,997✔
183
}
2,929,611✔
184

503,559✔
185
void ArrayString::insert(size_t ndx, StringData value)
4,485,102✔
186
{
6,588,234✔
187
    switch (upgrade_leaf(value.size())) {
6,627,543✔
188
        case Type::small_strings:
4,989,690✔
189
            static_cast<ArrayStringShort*>(m_arr)->insert(ndx, value);
4,989,690✔
190
            break;
465,279✔
191
        case Type::medium_strings:
41,207,163✔
192
            static_cast<ArraySmallBlobs*>(m_arr)->insert_string(ndx, value);
134,226✔
193
            break;
41,207,163✔
194
        case Type::big_strings:
649,797✔
195
            static_cast<ArrayBigBlobs*>(m_arr)->insert_string(ndx, value);
649,797✔
196
            break;
713,916✔
197
        case Type::enum_strings: {
720,495✔
198
            static_cast<Array*>(m_arr)->insert(ndx, 0);
720,495✔
199
            set(ndx, value);
656,376✔
200
            break;
656,376✔
201
        }
1,970,859✔
202
        case Type::interned_strings: {
2,168,589✔
203
            static_cast<Array*>(m_arr)->insert(ndx, 0);
342,891✔
204
            set(ndx, value);
342,891✔
205
            break;
206,712✔
206
        }
8,982✔
207
    }
3,801,795✔
208
}
3,801,795✔
209

118,824✔
210
StringData ArrayString::get(size_t ndx) const
118,824✔
211
{
42,454,020✔
212
    switch (m_type) {
42,335,196✔
213
        case Type::small_strings:
33,683,091✔
214
            return static_cast<ArrayStringShort*>(m_arr)->get(ndx);
31,712,232✔
215
        case Type::medium_strings:
2,536,476✔
216
            return static_cast<ArraySmallBlobs*>(m_arr)->get_string(ndx);
565,617✔
217
        case Type::big_strings:
5,038,995✔
218
            return static_cast<ArrayBigBlobs*>(m_arr)->get_string(ndx);
5,100,033✔
219
        case Type::enum_strings: {
625,755✔
220
            size_t index = size_t(static_cast<Array*>(m_arr)->get(ndx));
572,040✔
221
            return m_string_enum_values->get(index);
572,040✔
222
        }
7,323✔
223
        case Type::interned_strings: {
4,584,426✔
224
            size_t id = size_t(static_cast<Array*>(m_arr)->get(ndx));
4,584,426✔
225
            return m_string_interner->get(id);
4,584,426✔
226
        }
12,084✔
227
    }
42,347,280✔
228
    return {};
12,084✔
229
}
42,349,401✔
230

14,205✔
231
StringData ArrayString::get_legacy(size_t ndx) const
14,205✔
232
{
61,038✔
233
    switch (m_type) {
61,038!
234
        case Type::small_strings:
×
235
            return static_cast<ArrayStringShort*>(m_arr)->get(ndx);
236
        case Type::medium_strings:
33!
237
            return static_cast<ArraySmallBlobs*>(m_arr)->get_string_legacy(ndx);
33✔
238
        case Type::big_strings:
10,365✔
239
            return static_cast<ArrayBigBlobs*>(m_arr)->get_string(ndx);
10,332✔
240
        case Type::enum_strings: {
10,332!
241
            size_t index = size_t(static_cast<Array*>(m_arr)->get(ndx));
242
            return m_string_enum_values->get(index);
33✔
243
        }
✔
244
        case Type::interned_strings: {
×
245
            size_t id = size_t(static_cast<Array*>(m_arr)->get(ndx));
×
246
            return m_string_interner->get(id);
30✔
247
        }
30✔
248
    }
30✔
249
    return {};
3✔
250
}
3✔
251

3✔
252
Mixed ArrayString::get_any(size_t ndx) const
2✔
253
{
66,342✔
254
    return Mixed(get(ndx));
66,342✔
255
}
66,375✔
256

33✔
257
bool ArrayString::is_null(size_t ndx) const
258
{
1,934,103✔
259
    switch (m_type) {
1,934,280✔
260
        case Type::small_strings:
245,328✔
261
            return static_cast<ArrayStringShort*>(m_arr)->is_null(ndx);
245,238✔
262
        case Type::medium_strings:
8,160✔
263
            return static_cast<ArraySmallBlobs*>(m_arr)->is_null(ndx);
8,160✔
264
        case Type::big_strings:
1,561,575✔
265
            return static_cast<ArrayBigBlobs*>(m_arr)->is_null(ndx);
1,561,575✔
266
        case Type::enum_strings: {
3✔
267
            size_t id = size_t(static_cast<Array*>(m_arr)->get(ndx));
24✔
268
            return m_string_enum_values->is_null(id);
24✔
269
        }
24✔
270
        case Type::interned_strings: {
119,370✔
271
            size_t id = size_t(static_cast<Array*>(m_arr)->get(ndx));
119,370✔
272
            return id == 0;
119,370✔
273
        }
177✔
274
    }
1,934,280✔
275
    return {};
276
}
1,934,103✔
277

182,475✔
278
void ArrayString::erase(size_t ndx)
182,475✔
279
{
166,482✔
280
    switch (m_type) {
166,482✔
281
        case Type::small_strings:
46,980✔
282
            static_cast<ArrayStringShort*>(m_arr)->erase(ndx);
46,980✔
283
            break;
46,980✔
284
        case Type::medium_strings:
27,318✔
285
            static_cast<ArraySmallBlobs*>(m_arr)->erase(ndx);
27,318✔
286
            break;
36,024✔
287
        case Type::big_strings:
19,983✔
288
            static_cast<ArrayBigBlobs*>(m_arr)->erase(ndx);
19,983✔
289
            break;
11,277✔
290
        case Type::interned_strings:
14,031✔
291
        case Type::enum_strings:
49,698✔
292
            static_cast<Array*>(m_arr)->erase(ndx);
18,135✔
293
            break;
18,135✔
294
    }
95,556✔
295
}
95,556✔
296

29,970✔
297
void ArrayString::move(ArrayString& dst, size_t ndx)
29,970✔
298
{
1,626✔
299
    size_t sz = size();
31,596✔
300
    for (size_t i = ndx; i < sz; i++) {
192,840✔
301
        dst.add(get(i));
11,925✔
302
    }
192,807✔
303

304
    switch (m_type) {
33✔
305
        case Type::small_strings:
2✔
306
            static_cast<ArrayStringShort*>(m_arr)->truncate(ndx);
307
            break;
308
        case Type::medium_strings:
30✔
309
            static_cast<ArraySmallBlobs*>(m_arr)->truncate(ndx);
30✔
310
            break;
30✔
311
        case Type::big_strings:
3✔
312
            static_cast<ArrayBigBlobs*>(m_arr)->truncate(ndx);
3✔
313
            break;
3✔
UNCOV
314
        case Type::enum_strings:
✔
315
            // this operation will never be called for enumerated columns
316
            REALM_UNREACHABLE();
317
            break;
318
        case Type::interned_strings:
2✔
319
            m_arr->truncate(ndx);
UNCOV
320
            break;
×
321
    }
33✔
322
}
33✔
323

×
324
void ArrayString::clear()
325
{
189✔
326
    switch (m_type) {
189✔
327
        case Type::small_strings:
87!
328
            static_cast<ArrayStringShort*>(m_arr)->clear();
87✔
329
            break;
87✔
330
        case Type::medium_strings:
3✔
331
            static_cast<ArraySmallBlobs*>(m_arr)->clear();
3✔
332
            break;
3✔
333
        case Type::big_strings:
24✔
334
            static_cast<ArrayBigBlobs*>(m_arr)->clear();
24✔
335
            break;
24✔
UNCOV
336
        case Type::enum_strings:
✔
337
        case Type::interned_strings:
75✔
338
            static_cast<Array*>(m_arr)->clear();
75✔
339
            break;
75✔
340
    }
189✔
341
}
189!
342

×
343
size_t ArrayString::find_first(StringData value, size_t begin, size_t end) const noexcept
344
{
2,033,373!
345
    switch (m_type) {
2,033,373✔
346
        case Type::small_strings:
1,545,426✔
347
            return static_cast<ArrayStringShort*>(m_arr)->find_first(value, begin, end);
1,545,426✔
348
        case Type::medium_strings: {
36,933✔
349
            BinaryData as_binary(value.data(), value.size());
36,933✔
350
            return static_cast<ArraySmallBlobs*>(m_arr)->find_first(as_binary, true, begin, end);
36,933✔
UNCOV
351
            break;
×
352
        }
×
353
        case Type::big_strings: {
128,256✔
354
            BinaryData as_binary(value.data(), value.size());
128,256✔
355
            return static_cast<ArrayBigBlobs*>(m_arr)->find_first(as_binary, true, begin, end);
128,256✔
356
            break;
2,352,390✔
357
        }
2,352,390✔
358
        case Type::enum_strings: {
1,307,658✔
359
            size_t sz = m_string_enum_values->size();
290,526✔
360
            size_t res = m_string_enum_values->find_first(value, 0, sz);
1,625,784✔
361
            if (res != realm::not_found) {
689,127✔
362
                return static_cast<Array*>(m_arr)->find_first(res, begin, end);
290,526✔
363
            }
1,227,183✔
364
            break;
250,713✔
365
        }
541,032✔
366
        case Type::interned_strings: {
32,271✔
367
            // we need a way to avoid this lookup for each leaf array. The lookup must appear
368
            // higher up the call stack and passed down.
207✔
369
            auto id = m_string_interner->lookup(value);
32,478✔
370
            if (id) {
32,478✔
371
                return static_cast<Array*>(m_arr)->find_first(*id, begin, end);
30,648✔
372
            }
30,855✔
373
            break;
4,977✔
374
        }
35,418✔
375
    }
2,036,520✔
376
    return not_found;
1,830✔
377
}
2,033,580✔
378

207✔
379
namespace {
380

207✔
381
template <class T>
207✔
382
inline StringData get_string(const T* arr, size_t ndx)
207✔
383
{
217,143✔
384
    return arr->get_string(ndx);
216,936✔
385
}
217,143✔
386

207✔
387
template <>
250,713✔
388
inline StringData get_string(const ArrayStringShort* arr, size_t ndx)
389
{
48,297✔
390
    return arr->get(ndx);
734,241✔
391
}
724,659✔
392

393
template <class T, class U>
9,582✔
394
size_t lower_bound_string(const T* arr, U value)
395
{
125,691✔
396
    size_t i = 0;
125,691✔
397
    size_t sz = arr->size();
125,691✔
398
    while (0 < sz) {
382,689✔
399
        size_t half = sz / 2;
273,468✔
400
        size_t mid = i + half;
284,016✔
401
        auto probe = get_string(arr, mid);
275,781✔
402
        if (probe < value) {
275,781✔
403
            i = mid + 1;
106,371✔
404
            sz -= half + 1;
106,371✔
405
        }
106,371✔
406
        else {
167,097✔
407
            sz = half;
175,332✔
408
        }
175,332✔
409
    }
273,468✔
410
    return i;
125,691✔
411
}
117,456✔
412
} // namespace
8,235✔
413

8,235✔
414
size_t ArrayString::lower_bound(StringData value)
1,347✔
415
{
117,456✔
416
    switch (m_type) {
118,803✔
417
        case Type::small_strings:
30,975✔
418
            return lower_bound_string(static_cast<ArrayStringShort*>(m_arr), value);
30,975✔
419
        case Type::medium_strings:
33,798✔
420
            return lower_bound_string(static_cast<ArraySmallBlobs*>(m_arr), value);
35,145✔
421
        case Type::big_strings:
57,735✔
422
            return lower_bound_string(static_cast<ArrayBigBlobs*>(m_arr), value);
56,388✔
423
        case Type::enum_strings:
2,358✔
424
            break;
1,347✔
425
        case Type::interned_strings:
1,347✔
426
            REALM_UNREACHABLE();
1,347✔
427
            break;
428
    }
118,803✔
429
    return realm::npos;
1,347✔
430
}
118,803✔
431

1,347✔
432
ArrayString::Type ArrayString::upgrade_leaf(size_t value_size)
433
{
4,612,443✔
434
    if (m_type == Type::big_strings)
4,612,443✔
435
        return Type::big_strings;
1,071,036✔
436

9,582✔
437
    if (m_type == Type::enum_strings)
4,226,004✔
438
        return Type::enum_strings;
1,969,191✔
439

440
    if (m_type == Type::interned_strings)
1,650,609✔
441
        return Type::interned_strings;
632,541✔
442

79,740✔
443
    if (m_type == Type::medium_strings) {
1,027,740✔
444
        if (value_size <= medium_string_max_size)
259,236✔
445
            return Type::medium_strings;
258,981✔
446

228✔
447
        // Upgrade root leaf from medium to big strings
228✔
448
        auto string_medium = static_cast<ArraySmallBlobs*>(m_arr);
483✔
449
        ArrayBigBlobs big_blobs(m_alloc, true);
3,054✔
450
        big_blobs.create(); // Throws
3,054✔
451

2,799✔
452
        size_t n = string_medium->size();
67,305✔
453
        for (size_t i = 0; i < n; i++) {
71,865✔
454
            big_blobs.add_string(string_medium->get_string(i)); // Throws
71,610✔
455
        }
84,300✔
456
        auto parent = string_medium->get_parent();
79,995✔
457
        auto ndx_in_parent = string_medium->get_ndx_in_parent();
79,995✔
458
        string_medium->destroy();
255✔
459

460
        auto arr = new (&m_storage) ArrayBigBlobs(m_alloc, true);
255✔
461
        arr->init_from_mem(big_blobs.get_mem());
121,746✔
462
        arr->set_parent(parent, ndx_in_parent);
121,746✔
463
        arr->update_parent();
121,746✔
464

121,491✔
465
        m_type = Type::big_strings;
121,746✔
466
        return Type::big_strings;
121,746✔
467
    }
371,055✔
468

469
    // m_type == Type::small
68,202✔
470
    if (value_size <= small_string_max_size)
836,706✔
471
        return Type::small_strings;
827,208✔
472

68,202✔
473
    if (value_size <= medium_string_max_size) {
77,700✔
474
        // Upgrade root leaf from small to medium strings
68,202✔
475
        auto string_short = static_cast<ArrayStringShort*>(m_arr);
790,233✔
476
        ArraySmallBlobs string_long(m_alloc);
722,031✔
477
        string_long.create(); // Throws
722,031✔
478

68,202✔
479
        size_t n = string_short->size();
76,533✔
480
        for (size_t i = 0; i < n; i++) {
19,029✔
481
            string_long.add_string(string_short->get(i)); // Throws
10,698✔
482
        }
10,698✔
483
        auto parent = string_short->get_parent();
8,331✔
484
        auto ndx_in_parent = string_short->get_ndx_in_parent();
8,331✔
485
        string_short->destroy();
76,533✔
486

68,163✔
487
        auto arr = new (&m_storage) ArraySmallBlobs(m_alloc);
76,533✔
488
        arr->init_from_mem(string_long.get_mem());
61,620✔
489
        arr->set_parent(parent, ndx_in_parent);
8,331✔
490
        arr->update_parent();
61,620✔
491

53,289✔
492
        m_type = Type::medium_strings;
129,822✔
493
    }
129,822✔
494
    else {
1,167✔
495
        // Upgrade root leaf from small to big strings
496
        auto string_short = static_cast<ArrayStringShort*>(m_arr);
1,167✔
497
        ArrayBigBlobs big_blobs(m_alloc, true);
1,167✔
498
        big_blobs.create(); // Throws
1,167✔
499

500
        size_t n = string_short->size();
1,167✔
501
        for (size_t i = 0; i < n; i++) {
3,852✔
502
            big_blobs.add_string(string_short->get(i)); // Throws
2,685✔
503
        }
2,685✔
504
        auto parent = string_short->get_parent();
1,167✔
505
        auto ndx_in_parent = string_short->get_ndx_in_parent();
1,167✔
506
        string_short->destroy();
1,167✔
507

508
        auto arr = new (&m_storage) ArrayBigBlobs(m_alloc, true);
1,167✔
509
        arr->init_from_mem(big_blobs.get_mem());
1,167✔
510
        arr->set_parent(parent, ndx_in_parent);
1,167✔
511
        arr->update_parent();
1,167✔
512

513
        m_type = Type::big_strings;
1,167✔
514
    }
1,167✔
515

516
    return m_type;
9,498✔
517
}
768,504✔
518

519
void ArrayString::verify() const
520
{
96,468✔
521
#ifdef REALM_DEBUG
96,468✔
522
    switch (m_type) {
96,468✔
523
        case Type::small_strings:
7,446✔
524
            static_cast<ArrayStringShort*>(m_arr)->verify();
7,446✔
525
            break;
7,446✔
526
        case Type::medium_strings:
450✔
527
            static_cast<ArraySmallBlobs*>(m_arr)->verify();
450✔
528
            break;
450✔
529
        case Type::big_strings:
2,619✔
530
            static_cast<ArrayBigBlobs*>(m_arr)->verify();
2,619✔
531
            break;
2,619✔
532
        case Type::enum_strings:
126✔
533
        case Type::interned_strings:
85,953✔
534
            static_cast<Array*>(m_arr)->verify();
85,953✔
535
            break;
85,953✔
536
    }
96,468✔
537
#endif
96,468✔
538
}
96,468✔
539

540
template <>
541
ref_type ArrayString::typed_write(ref_type ref, _impl::ArrayWriterBase& out, Allocator& alloc)
542
{
188,802✔
543
    Array leaf(alloc);
188,802✔
544
    leaf.init_from_ref(ref);
188,802✔
545
    ref_type ret_val;
188,802✔
546
    auto header = leaf.get_header();
188,802✔
547
    if (NodeHeader::get_hasrefs_from_header(header) ||
188,802✔
548
        NodeHeader::get_wtype_from_header(header) == NodeHeader::wtype_Multiply) {
188,802✔
549
        // We're interning these strings
550
        ArrayString as(alloc);
105,582✔
551
        as.init_from_ref(ref);
105,582✔
552
        StringInterner* interner = out.table->get_string_interner(out.col_key);
105,582✔
553
        auto sz = as.size();
105,582✔
554
        Array interned(Allocator::get_default());
105,582✔
555
        interned.create(NodeHeader::type_Normal, true, sz);
105,582✔
556
        for (size_t i = 0; i < sz; ++i) {
860,007✔
557
            interned.set(i, interner->intern(as.get(i)));
754,425✔
558
        }
754,425✔
559
        ret_val = interned.write(out, false, false, out.compress);
105,582✔
560
        interned.destroy();
105,582✔
561
        // in a transactional setting:
562
        // Destroy all sub-arrays if present, in order to release memory in file
563
        // This is contrary to the rest of the handling in this function, but needed
564
        // here since sub-arrays may not have been COW'ed and therefore not freed in file.
565
        // We rely on 'only_modified' to indicate that we're in a transactional setting.
566
        if (out.only_modified)
105,582✔
567
            leaf.destroy_deep(true);
105,543✔
568
    }
105,582✔
569
    else {
83,220✔
570
        // whether it's the old enum strings or the new interned strings,
571
        // just write out the array using integer leaf compression
572
        ret_val = leaf.write(out, false, out.only_modified, out.compress);
83,220✔
573
    }
83,220✔
574
    return ret_val;
188,802✔
575
}
188,802✔
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