1 /*************************************************************************
3 * Copyright 2016 Realm Inc.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 **************************************************************************/
19 #ifndef REALM_COLUMN_LINK_HPP
20 #define REALM_COLUMN_LINK_HPP
22 #include <realm/column.hpp>
23 #include <realm/column_linkbase.hpp>
24 #include <realm/column_backlink.hpp>
28 /// A link column is an extension of an integer column (Column) and maintains
29 /// its node structure.
31 /// The individual values in a link column are indexes of rows in the target
32 /// table (offset with one to allow zero to indicate null links.) The target
33 /// table is specified by the table descriptor.
34 class LinkColumn : public LinkColumnBase {
36 using LinkColumnBase::LinkColumnBase;
37 ~LinkColumn() noexcept override;
39 static ref_type create(Allocator&, size_t size = 0);
41 bool is_nullable() const noexcept override;
45 /// is_null_link() is shorthand for `get_link() == realm::npos`,
46 /// nullify_link() is shorthand foe `set_link(realm::npos)`, and
47 /// insert_null_link() is shorthand for
48 /// `insert_link(realm::npos)`. set_link() returns the original link, with
49 /// `realm::npos` indicating that it was null.
51 size_t get_link(size_t row_ndx) const noexcept;
52 bool is_null(size_t row_ndx) const noexcept override;
53 bool is_null_link(size_t row_ndx) const noexcept;
54 size_t set_link(size_t row_ndx, size_t target_row_ndx);
55 void set_null(size_t row_ndx) override;
56 void nullify_link(size_t row_ndx);
57 void insert_link(size_t row_ndx, size_t target_row_ndx);
58 void insert_null_link(size_t row_ndx);
62 void insert_rows(size_t, size_t, size_t, bool) override;
63 void erase_rows(size_t, size_t, size_t, bool) override;
64 void move_last_row_over(size_t, size_t, bool) override;
65 void swap_rows(size_t, size_t) override;
66 void clear(size_t, bool) override;
67 void cascade_break_backlinks_to(size_t, CascadeState&) override;
68 void cascade_break_backlinks_to_all_rows(size_t, CascadeState&) override;
70 void verify(const Table&, size_t) const override;
73 friend class BacklinkColumn;
74 void do_nullify_link(size_t row_ndx, size_t old_target_row_ndx) override;
75 void do_update_link(size_t row_ndx, size_t old_target_row_ndx, size_t new_target_row_ndx) override;
76 void do_swap_link(size_t row_ndx, size_t target_row_ndx_1, size_t target_row_ndx_2) override;
79 void remove_backlinks(size_t row_ndx);
85 inline LinkColumn::~LinkColumn() noexcept
89 inline bool LinkColumn::is_nullable() const noexcept
94 inline ref_type LinkColumn::create(Allocator& alloc, size_t size)
96 return IntegerColumn::create(alloc, Array::type_Normal, size); // Throws
99 inline bool LinkColumn::is_null(size_t row_ndx) const noexcept
101 // Null is represented by zero
102 return LinkColumnBase::get(row_ndx) == 0;
105 inline size_t LinkColumn::get_link(size_t row_ndx) const noexcept
107 // Map zero to realm::npos, and `n+1` to `n`, where `n` is a target row index.
108 return to_size_t(LinkColumnBase::get(row_ndx)) - size_t(1);
111 inline bool LinkColumn::is_null_link(size_t row_ndx) const noexcept
113 return is_null(row_ndx);
116 inline size_t LinkColumn::set_link(size_t row_ndx, size_t target_row_ndx)
118 int_fast64_t old_value = LinkColumnBase::get(row_ndx);
119 size_t old_target_row_ndx = to_size_t(old_value) - size_t(1);
121 m_backlink_column->remove_one_backlink(old_target_row_ndx, row_ndx); // Throws
123 int_fast64_t new_value = int_fast64_t(size_t(1) + target_row_ndx);
124 LinkColumnBase::set(row_ndx, new_value); // Throws
126 if (target_row_ndx != realm::npos)
127 m_backlink_column->add_backlink(target_row_ndx, row_ndx); // Throws
129 return old_target_row_ndx;
132 inline void LinkColumn::set_null(size_t row_ndx)
134 set_link(row_ndx, realm::npos); // Throws
137 inline void LinkColumn::nullify_link(size_t row_ndx)
139 set_null(row_ndx); // Throws
142 inline void LinkColumn::insert_link(size_t row_ndx, size_t target_row_ndx)
144 int_fast64_t value = int_fast64_t(size_t(1) + target_row_ndx);
145 LinkColumnBase::insert(row_ndx, value); // Throws
147 if (target_row_ndx != realm::npos)
148 m_backlink_column->add_backlink(target_row_ndx, row_ndx); // Throws
151 inline void LinkColumn::insert_null_link(size_t row_ndx)
153 insert_link(row_ndx, realm::npos); // Throws
156 inline void LinkColumn::do_update_link(size_t row_ndx, size_t, size_t new_target_row_ndx)
158 // Row pos is offset by one, to allow null refs
159 LinkColumnBase::set(row_ndx, new_target_row_ndx + 1);
162 inline void LinkColumn::do_swap_link(size_t row_ndx, size_t target_row_ndx_1, size_t target_row_ndx_2)
164 // Row pos is offset by one, to allow null refs
168 uint64_t value = LinkColumnBase::get_uint(row_ndx);
169 if (value == target_row_ndx_1) {
170 LinkColumnBase::set_uint(row_ndx, target_row_ndx_2);
172 else if (value == target_row_ndx_2) {
173 LinkColumnBase::set_uint(row_ndx, target_row_ndx_1);
179 #endif // REALM_COLUMN_LINK_HPP