Skip to content

Commit

Permalink
Allow keypath to be provided as argument (#7210)
Browse files Browse the repository at this point in the history
  • Loading branch information
jedelbo authored Dec 21, 2023
1 parent 4926641 commit 9593f49
Show file tree
Hide file tree
Showing 11 changed files with 1,171 additions and 1,042 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

### Enhancements
* <New feature description> (PR [#????](https://github.com/realm/realm-core/pull/????))
* None.
* Property keypath in RQL can be substituted with value given as argument. Use '$P<i>' in query string. (Issue [#7033](https://github.com/realm/realm-core/issues/7033))

### Fixed
* <How do the end-user experience this issue? what was the impact?> ([#????](https://github.com/realm/realm-core/issues/????), since v?.?.?)
Expand Down
34 changes: 34 additions & 0 deletions src/realm/parser/driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,7 @@ Query TrueOrFalseNode::visit(ParserDriver* drv)

std::unique_ptr<Subexpr> PropertyNode::visit(ParserDriver* drv, DataType)
{
path->resolve_arg(drv);
if (path->path_elems.back().is_key() && path->path_elems.back().get_key() == "@links") {
identifier = "@links";
// This is a backlink aggregate query
Expand Down Expand Up @@ -1610,6 +1611,23 @@ std::unique_ptr<Subexpr> ListNode::visit(ParserDriver* drv, DataType hint)
return ret;
}

void PathNode::resolve_arg(ParserDriver* drv)
{
if (arg.size()) {
if (path_elems.size()) {
throw InvalidQueryError("Key path argument cannot be mixed with other elements");
}
auto arg_str = drv->get_arg_for_key_path(arg);
const char* path = arg_str.data();
do {
auto p = find_chr(path, '.');
StringData elem(path, p - path);
add_element(elem);
path = p;
} while (*path++ == '.');
}
}

LinkChain PathNode::visit(ParserDriver* drv, util::Optional<ExpressionComparisonType> comp_type)
{
LinkChain link_chain(drv->m_base_table, comp_type);
Expand Down Expand Up @@ -1759,6 +1777,22 @@ PathElement ParserDriver::get_arg_for_index(const std::string& i)
}
}

std::string ParserDriver::get_arg_for_key_path(const std::string& i)
{
REALM_ASSERT(i[0] == '$');
REALM_ASSERT(i[1] == 'K');
size_t arg_no = size_t(strtol(i.substr(2).c_str(), nullptr, 10));
if (m_args.is_argument_null(arg_no) || m_args.is_argument_list(arg_no)) {
throw InvalidQueryArgError(util::format("Null or list cannot be used for parameter '%1'", i));
}
auto type = m_args.type_for_argument(arg_no);
if (type != type_String) {
throw InvalidQueryArgError(util::format("Invalid index type for '%1'. Expected a string, but found type '%2'",
i, get_data_type_name(type)));
}
return m_args.string_for_argument(arg_no);
}

double ParserDriver::get_arg_for_coordinate(const std::string& str)
{
REALM_ASSERT(str[0] == '$');
Expand Down
8 changes: 8 additions & 0 deletions src/realm/parser/driver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,13 +278,18 @@ class ListNode : public ValueNode {

class PathNode : public ParserNode {
public:
struct ArgTag {};
Path path_elems;
Path::iterator current_path_elem;

PathNode(const PathElement& first)
{
add_element(first);
}
PathNode(const std::string& arg_str, ArgTag)
: arg(arg_str)
{
}
bool at_end() const
{
return current_path_elem == path_elems.end();
Expand All @@ -298,6 +303,7 @@ class PathNode : public ParserNode {
return path_elems.back().get_key();
}

void resolve_arg(ParserDriver*);
LinkChain visit(ParserDriver*, util::Optional<ExpressionComparisonType> = util::none);
void add_element(const PathElement& elem)
{
Expand Down Expand Up @@ -332,6 +338,7 @@ class PathNode : public ParserNode {
}

private:
std::string arg;
std::string backlink_str;
int backlink = 0;
};
Expand Down Expand Up @@ -664,6 +671,7 @@ class ParserDriver {
}

PathElement get_arg_for_index(const std::string&);
std::string get_arg_for_key_path(const std::string& i);
double get_arg_for_coordinate(const std::string&);

template <class T>
Expand Down
Loading

0 comments on commit 9593f49

Please sign in to comment.