Skip to content

Commit

Permalink
Fix index lookup
Browse files Browse the repository at this point in the history
Constructing a ObjKey from a value read in the index went wrong.
  • Loading branch information
jedelbo committed Sep 30, 2020
1 parent ca40980 commit a327790
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 18 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

### Fixed
* <How to hit and notice issue? what was the impact?> ([#????](https://github.com/realm/realm-core/issues/????), since v?.?.?)
* None.
* Making a query in an indexed property may give a "Key not found" exception. ([#2025](https://github.com/realm/realm-dotnet/issues/2025), since v6.0.0)

### Breaking changes
* None.
Expand Down
28 changes: 14 additions & 14 deletions src/realm/index_string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ void IndexArray::index_string_all_ins(StringData value, std::vector<ObjKey>& res

// Get entry under key
const size_t pos_refs = pos + 1; // first entry in refs points to offsets
const int64_t ref = get_direct(data, width, pos_refs);
const uint64_t ref = get_direct(data, width, pos_refs);

if (is_inner_node) {
// Set vars for next iteration
Expand All @@ -525,7 +525,7 @@ void IndexArray::index_string_all_ins(StringData value, std::vector<ObjKey>& res

// Literal row index (tagged)
if (ref & 1) {
ObjKey k = ObjKey(ref >> 1);
ObjKey k(int64_t(ref >> 1));

// The buffer is needed when for when this is an integer index.
StringConversionBuffer buffer;
Expand All @@ -537,12 +537,12 @@ void IndexArray::index_string_all_ins(StringData value, std::vector<ObjKey>& res
continue;
}

const char* const sub_header = m_alloc.translate(to_ref(ref));
const char* const sub_header = m_alloc.translate(ref_type(ref));
const bool sub_isindex = get_context_flag_from_header(sub_header);

// List of row indices with common prefix up to this point, in sorted order.
if (!sub_isindex) {
const IntegerColumn sub(m_alloc, to_ref(ref));
const IntegerColumn sub(m_alloc, ref_type(ref));
from_list_all_ins(upper_value, result, sub, column);
continue;
}
Expand Down Expand Up @@ -583,11 +583,11 @@ void IndexArray::index_string_all(StringData value, std::vector<ObjKey>& result,

// Get entry under key
size_t pos_refs = pos + 1; // first entry in refs points to offsets
int64_t ref = get_direct(data, width, pos_refs);
uint64_t ref = get_direct(data, width, pos_refs);

if (is_inner_node) {
// Set vars for next iteration
header = m_alloc.translate(to_ref(ref));
header = m_alloc.translate(ref_type(ref));
data = get_data_from_header(header);
width = get_width_from_header(header);
is_inner_node = get_is_inner_bptree_node_from_header(header);
Expand All @@ -601,7 +601,7 @@ void IndexArray::index_string_all(StringData value, std::vector<ObjKey>& result,

// Literal row index (tagged)
if (ref & 1) {
ObjKey k = ObjKey(ref >> 1);
ObjKey k(int64_t(ref >> 1));

// The buffer is needed when for when this is an integer index.
StringConversionBuffer buffer;
Expand All @@ -613,12 +613,12 @@ void IndexArray::index_string_all(StringData value, std::vector<ObjKey>& result,
return;
}

const char* sub_header = m_alloc.translate(to_ref(ref));
const char* sub_header = m_alloc.translate(ref_type(ref));
const bool sub_isindex = get_context_flag_from_header(sub_header);

// List of row indices with common prefix up to this point, in sorted order.
if (!sub_isindex) {
const IntegerColumn sub(m_alloc, to_ref(ref));
const IntegerColumn sub(m_alloc, ref_type(ref));
return from_list_all(value, result, sub, column);
}

Expand Down Expand Up @@ -1182,22 +1182,22 @@ void StringIndex::distinct(BPlusTree<ObjKey>& result) const
}
else {
for (size_t i = 1; i < array_size; ++i) {
int64_t ref = m_array->get(i);
uint64_t ref = m_array->get(i);

// low bit set indicate literal ref (shifted)
if (ref & 1) {
ObjKey k = ObjKey((uint64_t(ref) >> 1));
ObjKey k(int64_t(ref >> 1));
result.add(k);
}
else {
// A real ref either points to a list or a subindex
char* header = alloc.translate(to_ref(ref));
char* header = alloc.translate(ref_type(ref));
if (Array::get_context_flag_from_header(header)) {
StringIndex ndx(to_ref(ref), m_array.get(), i, m_target_column, alloc);
StringIndex ndx(ref_type(ref), m_array.get(), i, m_target_column, alloc);
ndx.distinct(result);
}
else {
IntegerColumn sub(alloc, to_ref(ref)); // Throws
IntegerColumn sub(alloc, ref_type(ref)); // Throws
if (sub.size() == 1) { // Optimization.
ObjKey k = ObjKey(sub.get(0)); // get first match
result.add(k);
Expand Down
2 changes: 0 additions & 2 deletions src/realm/index_string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ class IndexArray : public Array {
}

ObjKey index_string_find_first(StringData value, const ClusterColumn& column) const;
void index_string_find_all(IntegerColumn& result, StringData value, const ClusterColumn& column,
bool case_insensitive = false) const;
void index_string_find_all(std::vector<ObjKey>& result, StringData value, const ClusterColumn& column,
bool case_insensitive = false) const;
FindRes index_string_find_all_no_copy(StringData value, const ClusterColumn& column,
Expand Down
6 changes: 6 additions & 0 deletions src/realm/obj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,12 @@ std::string ConstObj::to_string() const
return ostr.str();
}

std::ostream& operator<<(std::ostream& ostr, const ConstObj& obj)
{
obj.to_json(ostr, -1, nullptr);
return ostr;
}

/*********************************** Obj *************************************/

bool Obj::ensure_writeable()
Expand Down
2 changes: 1 addition & 1 deletion src/realm/obj.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ class ConstObj {
std::vector<ObjKey> get_all_backlinks(ColKey backlink_col) const;
};

std::ostream& operator<<(std::ostream&, const ConstObj& obj);

class Obj : public ConstObj {
public:
Expand Down Expand Up @@ -315,7 +316,6 @@ class Obj : public ConstObj {
inline void set_spec(T&, ColKey);
};


inline Obj Obj::get_linked_object(ColKey link_col_key)
{
return ConstObj::get_linked_object(link_col_key);
Expand Down
17 changes: 17 additions & 0 deletions test/test_table.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4017,6 +4017,23 @@ TEST(Table_CreateObjectWithPrimaryKeyDidCreate)
CHECK_NOT(did_create);
}

TEST(Table_PrimaryKeyIndexBug)
{
Group g;
TableRef table = g.add_table("table");
TableRef origin = g.add_table("origin");
auto col_id = table->add_column(type_String, "id");
auto col_link = origin->add_column_link(type_Link, "link", *table);
table->add_search_index(col_id);
// Create an object where bit 62 is set in the ObkKey
auto obj = table->create_object(ObjKey(0x40083f0f9b0fb598)).set(col_id, "hallo");
origin->create_object().set(col_link, obj.get_key());

auto q = origin->link(col_link).column<String>(col_id) == "hallo";
auto cnt = q.count();
CHECK_EQUAL(cnt, 1);
}

TEST(Table_PrimaryKeyString)
{
#ifdef REALM_DEBUG
Expand Down

0 comments on commit a327790

Please sign in to comment.