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

realm / realm-core / 2295

06 May 2024 08:04AM UTC coverage: 90.739% (-0.02%) from 90.759%
2295

push

Evergreen

web-flow
RCORE-2115 Fix multiple backlinks created by dictionary (#7677)

* fix inserting a link multiple times to the same key in a dictionary of mixed creating multiple backlinks

101918 of 180246 branches covered (56.54%)

8 of 8 new or added lines in 2 files covered. (100.0%)

74 existing lines in 13 files now uncovered.

212515 of 234205 relevant lines covered (90.74%)

5761930.73 hits per line

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

93.08
/src/realm/collection_parent.cpp
1
/*************************************************************************
2
 *
3
 * Copyright 2023 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/collection_parent.hpp>
20
#include "realm/list.hpp"
21
#include "realm/set.hpp"
22
#include "realm/dictionary.hpp"
23
#include "realm/util/overload.hpp"
24

25
#include <random>
26
#include <mutex>
27

28
namespace realm {
29

30
std::ostream& operator<<(std::ostream& ostr, const PathElement& elem)
31
{
47,565✔
32
    if (elem.is_ndx()) {
47,565✔
33
        size_t ndx = elem.get_ndx();
10,752✔
34
        if (ndx == 0) {
10,752✔
35
            ostr << "FIRST";
3,918✔
36
        }
3,918✔
37
        else if (ndx == size_t(-1)) {
6,834✔
38
            ostr << "LAST";
330✔
39
        }
330✔
40
        else {
6,504✔
41
            ostr << elem.get_ndx();
6,504✔
42
        }
6,504✔
43
    }
10,752✔
44
    else if (elem.is_col_key()) {
36,813✔
45
        ostr << elem.get_col_key();
×
46
    }
×
47
    else if (elem.is_key()) {
36,813✔
48
        ostr << "'" << elem.get_key() << "'";
36,669✔
49
    }
36,669✔
50
    else if (elem.is_all()) {
144✔
51
        ostr << '*';
144✔
52
    }
144✔
53

54
    return ostr;
47,565✔
55
}
47,565✔
56

57
std::ostream& operator<<(std::ostream& ostr, const Path& path)
58
{
21,057✔
59
    for (auto& elem : path) {
46,509✔
60
        ostr << '[' << elem << ']';
46,509✔
61
    }
46,509✔
62
    return ostr;
21,057✔
63
}
21,057✔
64

65
bool StablePath::is_prefix_of(const StablePath& other) const noexcept
66
{
10,686✔
67
    if (size() > other.size())
10,686✔
68
        return false;
234✔
69
    return std::equal(begin(), end(), other.begin());
10,452✔
70
}
10,686✔
71

72
/***************************** CollectionParent ******************************/
73

74
CollectionParent::~CollectionParent() {}
2,708,199✔
75

76
void CollectionParent::check_level() const
77
{
4,290✔
78
    if (size_t(m_level) + 1 > s_max_level) {
4,290✔
79
        throw LogicError(ErrorCodes::LimitExceeded, "Max nesting level reached");
6✔
80
    }
6✔
81
}
4,290✔
82

83
template <typename Base, template <typename> typename Collection, typename LinkCol>
84
std::unique_ptr<Base> create_collection(ColKey col_key, uint8_t level)
85
{
439,851✔
86
    bool nullable = col_key.get_attrs().test(col_attr_Nullable);
439,851✔
87
    switch (col_key.get_type()) {
439,851✔
88
        case col_type_Int:
26,934✔
89
            if (nullable)
26,934✔
90
                return std::make_unique<Collection<util::Optional<Int>>>(col_key);
5,622✔
91
            return std::make_unique<Collection<Int>>(col_key);
21,312✔
92
        case col_type_Bool:
9,264✔
93
            if (nullable)
9,264✔
94
                return std::make_unique<Collection<util::Optional<Bool>>>(col_key);
4,812✔
95
            return std::make_unique<Collection<Bool>>(col_key);
4,452✔
96
        case col_type_Float:
10,056✔
97
            if (nullable)
10,056✔
98
                return std::make_unique<Collection<util::Optional<Float>>>(col_key);
5,226✔
99
            return std::make_unique<Collection<Float>>(col_key);
4,830✔
100
        case col_type_Double:
10,314✔
101
            if (nullable)
10,314✔
102
                return std::make_unique<Collection<util::Optional<Double>>>(col_key);
5,226✔
103
            return std::make_unique<Collection<Double>>(col_key);
5,088✔
104
        case col_type_String:
245,529✔
105
            return std::make_unique<Collection<String>>(col_key);
245,529✔
106
        case col_type_Binary:
9,882✔
107
            return std::make_unique<Collection<Binary>>(col_key);
9,882✔
108
        case col_type_Timestamp:
9,978✔
109
            return std::make_unique<Collection<Timestamp>>(col_key);
9,978✔
110
        case col_type_Decimal:
9,564✔
111
            return std::make_unique<Collection<Decimal128>>(col_key);
9,564✔
112
        case col_type_ObjectId:
18,414✔
113
            if (nullable)
18,414✔
114
                return std::make_unique<Collection<util::Optional<ObjectId>>>(col_key);
13,944✔
115
            return std::make_unique<Collection<ObjectId>>(col_key);
4,470✔
116
        case col_type_UUID:
9,306✔
117
            if (nullable)
9,306✔
118
                return std::make_unique<Collection<util::Optional<UUID>>>(col_key);
4,848✔
119
            return std::make_unique<Collection<UUID>>(col_key);
4,458✔
120
        case col_type_TypedLink:
✔
121
            return std::make_unique<Collection<ObjLink>>(col_key);
×
122
        case col_type_Mixed:
15,714✔
123
            return std::make_unique<Collection<Mixed>>(col_key, level + 1);
15,714✔
124
        case col_type_Link:
64,896✔
125
            return std::make_unique<LinkCol>(col_key);
64,896✔
126
        default:
✔
127
            REALM_TERMINATE("Unsupported column type.");
128
    }
439,851✔
129
}
439,851✔
130

131
LstBasePtr CollectionParent::get_listbase_ptr(ColKey col_key, uint8_t level)
132
{
322,032✔
133
    REALM_ASSERT(col_key.get_attrs().test(col_attr_List) || col_key.get_type() == col_type_Mixed);
322,032✔
134
    return create_collection<LstBase, Lst, LnkLst>(col_key, level);
322,032✔
135
}
322,032✔
136

137
SetBasePtr CollectionParent::get_setbase_ptr(ColKey col_key, uint8_t level)
138
{
117,819✔
139
    REALM_ASSERT(col_key.get_attrs().test(col_attr_Set));
117,819✔
140
    return create_collection<SetBase, Set, LnkSet>(col_key, level);
117,819✔
141
}
117,819✔
142

143
CollectionBasePtr CollectionParent::get_collection_ptr(ColKey col_key, uint8_t level)
144
{
127,461✔
145
    if (col_key.is_list()) {
127,461✔
146
        return get_listbase_ptr(col_key, level);
23,451✔
147
    }
23,451✔
148
    else if (col_key.is_set()) {
104,010✔
149
        return get_setbase_ptr(col_key, level);
74,271✔
150
    }
74,271✔
151
    else if (col_key.is_dictionary()) {
29,739✔
152
        return std::make_unique<Dictionary>(col_key, level + 1);
29,739✔
153
    }
29,739✔
154
    return {};
×
155
}
127,461✔
156

157
int64_t CollectionParent::generate_key(size_t sz)
158
{
6,636✔
159
    static std::mt19937 gen32;
6,636✔
160
    static std::mutex mutex;
6,636✔
161

162
    int64_t key;
6,636✔
163
    const std::lock_guard<std::mutex> lock(mutex);
6,636✔
164
    do {
6,636✔
165
        if (sz < 0x10) {
6,636✔
166
            key = int8_t(gen32());
4,038✔
167
        }
4,038✔
168
        else if (sz < 0x1000) {
2,598✔
169
            key = int16_t(gen32());
2,598✔
170
        }
2,598✔
UNCOV
171
        else {
×
UNCOV
172
            key = int32_t(gen32());
×
UNCOV
173
        }
×
174
    } while (key == 0);
6,636✔
175

176
    return key;
6,636✔
177
}
6,636✔
178

179
void CollectionParent::set_key(BPlusTreeMixed& tree, size_t index)
180
{
4,038✔
181
    int64_t key = generate_key(tree.size());
4,038✔
182
    while (tree.find_key(key) != realm::not_found) {
4,053✔
183
        key++;
15✔
184
    }
15✔
185
    tree.set_key(index, key);
4,038✔
186
}
4,038✔
187

188
} // namespace realm
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

© 2026 Coveralls, Inc