@@ -89,7 +89,7 @@ const Table* ClusterNode::get_owning_table() const noexcept
8989
9090void ClusterNode::get (ObjKey k, ClusterNode::State& state) const
9191{
92- if (!k || !try_get (k , state)) {
92+ if (!k || !try_get (RowKey (k) , state)) {
9393 throw KeyNotFound (util::format (" No object with key '%1' in '%2'" , k.value , get_owning_table ()->get_name ()));
9494 }
9595}
@@ -225,7 +225,7 @@ void Cluster::update_from_parent() noexcept
225225 }
226226}
227227
228- MemRef Cluster::ensure_writeable (ObjKey )
228+ MemRef Cluster::ensure_writeable (RowKey )
229229{
230230 // By specifying the minimum size, we ensure that the array has a capacity
231231 // to hold m_size 64 bit refs.
@@ -234,7 +234,7 @@ MemRef Cluster::ensure_writeable(ObjKey)
234234 return get_mem ();
235235}
236236
237- void Cluster::update_ref_in_parent (ObjKey , ref_type)
237+ void Cluster::update_ref_in_parent (RowKey , ref_type)
238238{
239239 REALM_UNREACHABLE ();
240240}
@@ -343,13 +343,13 @@ inline void Cluster::do_insert_link(size_t ndx, ColKey col_key, Mixed init_val,
343343 }
344344}
345345
346- void Cluster::insert_row (size_t ndx, ObjKey k , const FieldValues& init_values)
346+ void Cluster::insert_row (size_t ndx, RowKey row_key , const FieldValues& init_values)
347347{
348348 // Ensure the cluster array is big enough to hold 64 bit values.
349349 copy_on_write (m_size * 8 );
350350
351351 if (m_keys.is_attached ()) {
352- m_keys.insert (ndx, k .value );
352+ m_keys.insert (ndx, row_key .value );
353353 }
354354 else {
355355 Array::set (s_key_ref_or_size_index, Array::get (s_key_ref_or_size_index) + 2 ); // Increments size by 1
@@ -377,6 +377,7 @@ void Cluster::insert_row(size_t ndx, ObjKey k, const FieldValues& init_values)
377377 }
378378
379379 bool nullable = attr.test (col_attr_Nullable);
380+ ObjKey obj_key (int64_t (row_key.value + get_offset ()));
380381 switch (type) {
381382 case col_type_Int:
382383 if (attr.test (col_attr_Nullable)) {
@@ -402,7 +403,7 @@ void Cluster::insert_row(size_t ndx, ObjKey k, const FieldValues& init_values)
402403 do_insert_row<ArrayBinary>(ndx, col_key, init_value, nullable);
403404 break ;
404405 case col_type_Mixed: {
405- do_insert_mixed (ndx, col_key, init_value, ObjKey (k. value + get_offset ()) );
406+ do_insert_mixed (ndx, col_key, init_value, obj_key );
406407 break ;
407408 }
408409 case col_type_Timestamp:
@@ -418,10 +419,10 @@ void Cluster::insert_row(size_t ndx, ObjKey k, const FieldValues& init_values)
418419 do_insert_row<ArrayUUIDNull>(ndx, col_key, init_value, nullable);
419420 break ;
420421 case col_type_Link:
421- do_insert_key (ndx, col_key, init_value, ObjKey (k. value + get_offset ()) );
422+ do_insert_key (ndx, col_key, init_value, obj_key );
422423 break ;
423424 case col_type_TypedLink:
424- do_insert_link (ndx, col_key, init_value, ObjKey (k. value + get_offset ()) );
425+ do_insert_link (ndx, col_key, init_value, obj_key );
425426 break ;
426427 case col_type_BackLink: {
427428 ArrayBacklink arr (m_alloc);
@@ -664,7 +665,7 @@ void Cluster::remove_column(ColKey col_key)
664665 Array::set (idx, 0 );
665666}
666667
667- ref_type Cluster::insert (ObjKey k , const FieldValues& init_values, ClusterNode::State& state)
668+ ref_type Cluster::insert (RowKey row_key , const FieldValues& init_values, ClusterNode::State& state)
668669{
669670 int64_t current_key_value = -1 ;
670671 size_t sz;
@@ -673,34 +674,34 @@ ref_type Cluster::insert(ObjKey k, const FieldValues& init_values, ClusterNode::
673674
674675 auto on_error = [&] {
675676 throw KeyAlreadyUsed (
676- util::format (" When inserting key '%1' in '%2'" , k .value , get_owning_table ()->get_name ()));
677+ util::format (" When inserting key '%1' in '%2'" , row_key .value , get_owning_table ()->get_name ()));
677678 };
678679
679680 if (m_keys.is_attached ()) {
680681 sz = m_keys.size ();
681- ndx = m_keys.lower_bound (uint64_t (k .value ) );
682+ ndx = m_keys.lower_bound (row_key .value );
682683 if (ndx < sz) {
683684 current_key_value = m_keys.get (ndx);
684- if (k .value == current_key_value) {
685+ if (row_key .value == uint64_t ( current_key_value) ) {
685686 on_error ();
686687 }
687688 }
688689 }
689690 else {
690691 sz = size_t (Array::get (s_key_ref_or_size_index)) >> 1 ; // Size is stored as tagged integer
691- if (uint64_t (k .value ) < sz) {
692+ if (row_key .value < sz) {
692693 on_error ();
693694 }
694695 // Key value is bigger than all other values, should be put last
695696 ndx = sz;
696- if (uint64_t (k .value ) > sz && sz < cluster_node_size) {
697+ if (row_key .value > sz && sz < cluster_node_size) {
697698 ensure_general_form ();
698699 }
699700 }
700701
701702 REALM_ASSERT_DEBUG (sz <= cluster_node_size);
702703 if (REALM_LIKELY (sz < cluster_node_size)) {
703- insert_row (ndx, k , init_values); // Throws
704+ insert_row (ndx, row_key , init_values); // Throws
704705 state.mem = get_mem ();
705706 state.index = ndx;
706707 }
@@ -709,8 +710,8 @@ ref_type Cluster::insert(ObjKey k, const FieldValues& init_values, ClusterNode::
709710 Cluster new_leaf (0 , m_alloc, m_tree_top);
710711 new_leaf.create ();
711712 if (ndx == sz) {
712- new_leaf.insert_row (0 , ObjKey (0 ), init_values); // Throws
713- state.split_key = k .value ;
713+ new_leaf.insert_row (0 , RowKey (0 ), init_values); // Throws
714+ state.split_key = int64_t (row_key .value ) ;
714715 state.mem = new_leaf.get_mem ();
715716 state.index = 0 ;
716717 }
@@ -719,7 +720,7 @@ ref_type Cluster::insert(ObjKey k, const FieldValues& init_values, ClusterNode::
719720 REALM_ASSERT_DEBUG (m_keys.is_attached ());
720721 new_leaf.ensure_general_form ();
721722 move (ndx, &new_leaf, current_key_value);
722- insert_row (ndx, k , init_values); // Throws
723+ insert_row (ndx, row_key , init_values); // Throws
723724 state.mem = get_mem ();
724725 state.split_key = current_key_value;
725726 state.index = ndx;
@@ -730,15 +731,15 @@ ref_type Cluster::insert(ObjKey k, const FieldValues& init_values, ClusterNode::
730731 return ret;
731732}
732733
733- bool Cluster::try_get (ObjKey k, ClusterNode::State& state) const noexcept
734+ bool Cluster::try_get (RowKey k, ClusterNode::State& state) const noexcept
734735{
735736 state.mem = get_mem ();
736737 if (m_keys.is_attached ()) {
737- state.index = m_keys.lower_bound (uint64_t ( k.value ) );
738- return state.index != m_keys.size () && m_keys.get (state.index ) == uint64_t ( k.value ) ;
738+ state.index = m_keys.lower_bound (k.value );
739+ return state.index != m_keys.size () && m_keys.get (state.index ) == k.value ;
739740 }
740741 else {
741- if (uint64_t ( k.value ) < uint64_t (Array::get (s_key_ref_or_size_index) >> 1 )) {
742+ if (k.value < uint64_t (Array::get (s_key_ref_or_size_index) >> 1 )) {
742743 state.index = size_t (k.value );
743744 return true ;
744745 }
@@ -776,7 +777,7 @@ inline void Cluster::do_erase(size_t ndx, ColKey col_key)
776777 values.erase (ndx);
777778}
778779
779- inline void Cluster::do_erase_mixed (size_t ndx, ColKey col_key, ObjKey key, CascadeState& state)
780+ inline void Cluster::do_erase_mixed (size_t ndx, ColKey col_key, CascadeState& state)
780781{
781782 const Table* origin_table = m_tree_top.get_owning_table ();
782783 auto col_ndx = col_key.get_index ();
@@ -788,19 +789,16 @@ inline void Cluster::do_erase_mixed(size_t ndx, ColKey col_key, ObjKey key, Casc
788789 Mixed value = values.get (ndx);
789790 if (value.is_type (type_TypedLink)) {
790791 ObjLink link = value.get <ObjLink>();
791- auto target_obj = origin_table->get_parent_group ()->get_object (link);
792-
793- ColKey backlink_col_key = target_obj.get_table ()->find_backlink_column (col_key, origin_table->get_key ());
794- REALM_ASSERT (backlink_col_key);
795- target_obj.remove_one_backlink (backlink_col_key, get_real_key (ndx)); // Throws
792+ Obj obj (origin_table->m_own_ref , get_mem (), get_real_key (ndx), ndx);
793+ obj.remove_backlink (col_key, link, state);
796794 }
797795 if (value.is_type (type_List)) {
798- Obj obj (origin_table->m_own_ref , get_mem (), key , ndx);
796+ Obj obj (origin_table->m_own_ref , get_mem (), get_real_key (ndx) , ndx);
799797 Lst<Mixed> list (obj, col_key);
800798 list.remove_backlinks (state);
801799 }
802800 if (value.is_type (type_Dictionary)) {
803- Obj obj (origin_table->m_own_ref , get_mem (), key , ndx);
801+ Obj obj (origin_table->m_own_ref , get_mem (), get_real_key (ndx) , ndx);
804802 Dictionary dict (obj, col_key);
805803 dict.remove_backlinks (state);
806804 }
@@ -821,12 +819,12 @@ inline void Cluster::do_erase_key(size_t ndx, ColKey col_key, CascadeState& stat
821819 values.erase (ndx);
822820}
823821
824- size_t Cluster::get_ndx (ObjKey k, size_t ndx) const noexcept
822+ size_t Cluster::get_ndx (RowKey k, size_t ndx) const noexcept
825823{
826824 size_t index;
827825 if (m_keys.is_attached ()) {
828- index = m_keys.lower_bound (uint64_t ( k.value ) );
829- if (index == m_keys.size () || m_keys.get (index) != uint64_t ( k.value ) ) {
826+ index = m_keys.lower_bound (k.value );
827+ if (index == m_keys.size () || m_keys.get (index) != k.value ) {
830828 return realm::npos;
831829 }
832830 }
@@ -839,11 +837,14 @@ size_t Cluster::get_ndx(ObjKey k, size_t ndx) const noexcept
839837 return index + ndx;
840838}
841839
842- size_t Cluster::erase (ObjKey key , CascadeState& state)
840+ size_t Cluster::erase (RowKey row_key , CascadeState& state)
843841{
844- size_t ndx = get_ndx (key , 0 );
842+ size_t ndx = get_ndx (row_key , 0 );
845843 if (ndx == realm::npos)
846- throw KeyNotFound (util::format (" When erasing key '%1' in '%2'" , key.value , get_owning_table ()->get_name ()));
844+ throw KeyNotFound (util::format (" When erasing key '%1' (offset '%2') in '%3'" , row_key.value , m_offset,
845+ get_owning_table ()->get_name ()));
846+
847+ ObjKey real_key = get_real_key (ndx);
847848 std::vector<ColKey> backlink_column_keys;
848849
849850 auto erase_in_column = [&](ColKey col_key) {
@@ -860,7 +861,7 @@ size_t Cluster::erase(ObjKey key, CascadeState& state)
860861 const Table* origin_table = m_tree_top.get_owning_table ();
861862 if (attr.test (col_attr_Dictionary)) {
862863 if (col_type == col_type_Mixed || col_type == col_type_Link) {
863- Obj obj (origin_table->m_own_ref , get_mem (), key , ndx);
864+ Obj obj (origin_table->m_own_ref , get_mem (), real_key , ndx);
864865 Dictionary dict (obj, col_key);
865866 dict.remove_backlinks (state);
866867 }
@@ -869,7 +870,7 @@ size_t Cluster::erase(ObjKey key, CascadeState& state)
869870 BPlusTree<ObjKey> links (m_alloc);
870871 links.init_from_ref (ref);
871872 if (links.size () > 0 ) {
872- do_remove_backlinks (ObjKey (key. value + m_offset) , col_key, links.get_all (), state);
873+ do_remove_backlinks (real_key , col_key, links.get_all (), state);
873874 }
874875 }
875876 else if (col_type == col_type_TypedLink) {
@@ -880,11 +881,11 @@ size_t Cluster::erase(ObjKey key, CascadeState& state)
880881 auto target_obj = origin_table->get_parent_group ()->get_object (link);
881882 ColKey backlink_col_key =
882883 target_obj.get_table ()->find_backlink_column (col_key, origin_table->get_key ());
883- target_obj.remove_one_backlink (backlink_col_key, ObjKey (key. value + m_offset) );
884+ target_obj.remove_one_backlink (backlink_col_key, real_key );
884885 }
885886 }
886887 else if (col_type == col_type_Mixed) {
887- Obj obj (origin_table->m_own_ref , get_mem (), key , ndx);
888+ Obj obj (origin_table->m_own_ref , get_mem (), real_key , ndx);
888889 Lst<Mixed> list (obj, col_key);
889890 list.remove_backlinks (state);
890891 }
@@ -921,7 +922,7 @@ size_t Cluster::erase(ObjKey key, CascadeState& state)
921922 do_erase<ArrayBinary>(ndx, col_key);
922923 break ;
923924 case col_type_Mixed:
924- do_erase_mixed (ndx, col_key, key, state);
925+ do_erase_mixed (ndx, col_key, state);
925926 break ;
926927 case col_type_Timestamp:
927928 do_erase<ArrayTimestamp>(ndx, col_key);
@@ -983,7 +984,7 @@ size_t Cluster::erase(ObjKey key, CascadeState& state)
983984 return node_size ();
984985}
985986
986- void Cluster::nullify_incoming_links (ObjKey key, CascadeState& state)
987+ void Cluster::nullify_incoming_links (RowKey key, CascadeState& state)
987988{
988989 size_t ndx = get_ndx (key, 0 );
989990 if (ndx == realm::npos)
@@ -1541,7 +1542,7 @@ void Cluster::remove_backlinks(const Table* origin_table, ObjKey origin_key, Col
15411542 bool last_removed = target_obj.remove_one_backlink (backlink_col_key, origin_key); // Throws
15421543 if (is_unres) {
15431544 if (last_removed) {
1544- // Check is there are more backlinks
1545+ // Check if there are more backlinks
15451546 if (!target_obj.has_backlinks (false )) {
15461547 // Tombstones can be erased right away - there is no cascading effect
15471548 target_table->m_tombstones ->erase (link.get_obj_key (), state);
0 commit comments