Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Je/query index all #6854

Merged
merged 3 commits into from
Aug 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* <New feature description> (PR [#????](https://github.com/realm/realm-core/pull/????))
* Storage of Decimal128 properties has been optimised so that the individual values will take up 0 bits (if all nulls), 32 bits, 64 bits or 128 bits depending on what is needed. (PR [#6111]https://github.com/realm/realm-core/pull/6111))
* You can have a collection embedded in any Mixed property (except Set<Mixed>).
* Querying a specific entry in a list-of-primitives (in particular 'first and 'last') is supported. (PR [#4269](https://github.com/realm/realm-core/issues/4269))
* Querying a specific entry in a collection (in particular 'first and 'last') is supported. (PR [#4269](https://github.com/realm/realm-core/issues/4269))

### Fixed
* <How do the end-user experience this issue? what was the impact?> ([#????](https://github.com/realm/realm-core/issues/????), since v?.?.?)
Expand Down
150 changes: 1 addition & 149 deletions src/realm/collection_parent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

#include <realm/alloc.hpp>
#include <realm/table_ref.hpp>
#include <realm/keys.hpp>
#include <realm/path.hpp>
#include <realm/mixed.hpp>

#include <external/mpark/variant.hpp>
Expand Down Expand Up @@ -72,154 +72,6 @@ enum class UpdateStatus {
NoChange,
};

// Given an object as starting point, a collection can be identified by
// a sequence of PathElements. The first element should always be a
// column key. The next elements are either an index into a list or a key
// to an entry in a dictionary
struct PathElement {
union {
std::string string_val;
int64_t int_val;
};
enum Type { column, key, index, all } m_type;
struct AllTag {};

PathElement()
: int_val(-1)
, m_type(Type::column)
{
}
PathElement(ColKey col_key)
: int_val(col_key.value)
, m_type(Type::column)
{
}
PathElement(int ndx)
: int_val(ndx)
, m_type(Type::index)
{
REALM_ASSERT(ndx >= 0);
}
PathElement(size_t ndx)
: int_val(int64_t(ndx))
, m_type(Type::index)
{
}
PathElement(StringData str)
: string_val(str)
, m_type(Type::key)
{
}
PathElement(const char* str)
: string_val(str)
, m_type(Type::key)
{
}
PathElement(AllTag)
: int_val(0)
, m_type(Type::all)
{
}
PathElement(const std::string& str)
: string_val(str)
, m_type(Type::key)
{
}
PathElement(const PathElement& other)
: m_type(other.m_type)
{
if (other.m_type == Type::key) {
new (&string_val) std::string(other.string_val);
}
else {
int_val = other.int_val;
}
}

PathElement(PathElement&& other) noexcept
: m_type(other.m_type)
{
if (other.m_type == Type::key) {
new (&string_val) std::string(std::move(other.string_val));
}
else {
int_val = other.int_val;
}
}
~PathElement()
{
if (m_type == Type::key) {
string_val.std::string::~string();
}
}

bool is_col_key() const noexcept
{
return m_type == Type::column;
}
bool is_ndx() const noexcept
{
return m_type == Type::index;
}
bool is_key() const noexcept
{
return m_type == Type::key;
}
bool is_all() const noexcept
{
return m_type == Type::all;
}

ColKey get_col_key() const noexcept
{
REALM_ASSERT(is_col_key());
return ColKey(int_val);
}
size_t get_ndx() const noexcept
{
REALM_ASSERT(is_ndx());
return size_t(int_val);
}
const std::string& get_key() const noexcept
{
REALM_ASSERT(is_key());
return string_val;
}

PathElement& operator=(const PathElement& other) = delete;

bool operator==(const PathElement& other) const
{
if (m_type == other.m_type) {
return (m_type == Type::key) ? string_val == other.string_val : int_val == other.int_val;
}
return false;
}
bool operator==(const char* str) const
{
return (m_type == Type::key) ? string_val == str : false;
}
bool operator==(size_t i) const
{
return (m_type == Type::index) ? size_t(int_val) == i : false;
}
bool operator==(ColKey ck) const
{
return (m_type == Type::column) ? int_val == ck.value : false;
}
};

using Path = std::vector<PathElement>;

std::ostream& operator<<(std::ostream& ostr, const PathElement& elem);
std::ostream& operator<<(std::ostream& ostr, const Path& path);

// Path from the group level.
struct FullPath {
TableKey top_table;
ObjKey top_objkey;
Path path_from_top;
};

using StableIndex = mpark::variant<ColKey, int64_t, std::string>;
using StablePath = std::vector<StableIndex>;
Expand Down
7 changes: 7 additions & 0 deletions src/realm/list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,13 @@ class LnkLst final : public ObjCollectionBase<LstBase> {
// FIXME: Should this add to the end of the unresolved list?
insert(size(), value);
}
void add(const Obj& obj)
{
if (get_target_table()->get_key() != obj.get_table_key()) {
throw InvalidArgument("LnkLst::add: Wrong object type");
}
add(obj.get_key());
}

// Overriding members of CollectionBase:
using CollectionBase::get_owner_key;
Expand Down
15 changes: 11 additions & 4 deletions src/realm/parser/driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,9 @@ std::unique_ptr<Subexpr> PropertyNode::visit(ParserDriver* drv, DataType)
}
m_link_chain = path->visit(drv, comp_type);
if (!path->at_end()) {
if (!path->current_path_elem->is_key()) {
throw InvalidQueryError(util::format("[%1] not expected", *path->current_path_elem));
}
identifier = path->current_path_elem->get_key();
}
std::unique_ptr<Subexpr> subexpr{drv->column(m_link_chain, path)};
Expand Down Expand Up @@ -1537,13 +1540,17 @@ LinkChain PathNode::visit(ParserDriver* drv, util::Optional<ExpressionComparison
continue; // this element has been removed, this happens in subqueries
}

if (!link_chain.link(path_elem)) {
// Check if it is a link
if (link_chain.link(path_elem)) {
continue;
}
// The next identifier being a property on the linked to object takes precedence
if (link_chain.get_current_table()->get_column_key(path_elem)) {
break;
}
}
else {
throw InvalidQueryError("Index not supported here");
}
if (!link_chain.index(*current_path_elem))
break;
}
return link_chain;
}
Expand Down
Loading