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 stage 1 #6715

Merged
merged 4 commits into from
Jun 19, 2023
Merged

Je/query index stage 1 #6715

merged 4 commits into from
Jun 19, 2023

Conversation

jedelbo
Copy link
Contributor

@jedelbo jedelbo commented Jun 15, 2023

What, How & Why?

☑️ ToDos

  • 📝 Changelog update
  • 🚦 Tests (or not relevant)
  • C-API, if public C++ API changed.

}
}
/*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove... commented code

@@ -4991,8 +4997,12 @@ TEST(Parser_Dictionary)
verify_query(test_context, foo, "ALL dict.@type == 'int'", 100); // all dictionaries have ints
verify_query(test_context, foo, "NONE dict.@type == 'int'", 0); // each object has Bar:i
verify_query(test_context, foo, "ANY dict.@type == 'string'", 0); // no strings present
// Dictionaries are not ordered
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the point of supporting FIRST and LAST for a dictionary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are actually testing that we throw in this case

val = list.get(idx);
}
if (path_size > 1) {
val = Collection::get_any(val, begin + 1, end, alloc);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be a problem (probably we are never going to hit it though), in case of nested collections that are too deep, we might run out of stack space.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any clue when that would be a problem?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is up to how long is the nested collection... List<List<List<List..... will result in N recursive call proportional to the amount of collections that are nested. Most probably we will never run into this problem in practise, and there are also others part in the code when this can manifest earlier than at this point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a check that nesting level will not exceed 100.

@@ -537,7 +537,7 @@ Query EqualityNode::visit(ParserDriver* drv)
else if (right->has_single_value() && (left_type == right_type || left_type == type_Mixed)) {
Mixed val = right->get_mixed();
const ObjPropertyBase* prop = dynamic_cast<const ObjPropertyBase*>(left.get());
if (prop && !prop->links_exist()) {
if (prop && !prop->links_exist() && !prop->has_path()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only managing simple values, right? No links?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No links and no path.

@@ -879,9 +891,29 @@ std::unique_ptr<Subexpr> PropertyNode::visit(ParserDriver* drv, DataType)
}
}
else {
throw InvalidQueryError("Index not supported");
// This must be an integer index
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we assert this somehow?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Certainly

@@ -2392,7 +2392,7 @@ TEST_TYPES(Parser_list_of_primitive_types, Prop<Int>, Nullable<Int>, Prop<Bool>,
auto col_link = t->add_column(*t, "link");

auto obj1 = t->create_object();
std::vector<type> values = gen.values_from_int<type>({0, 9, 4, 2, 7, 4, 1, 8, 11, 3, 4, 5, 22});
std::vector<type> values = gen.values_from_int<type>({2, 9, 4, 0, 7, 4, 1, 8, 11, 3, 4, 5, 22});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you swapping 2 and 0? Couldn't you do something like auto value_first = gen.convert_for_test<underlying_type>(0); ... or it is because zero represents null in a mixed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some types 0 could result in either 0 or NULL and thus give different results depending on the type. 2 does not have that problem.

friend class Table;
friend class LinkChain;
bool indexes(const Path& path)
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{
{
REALM_ASSERT(path.size());

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure


Obj paul = persons->create_object_with_primary_key("Paul");
paul.set(col_self, paul.get_key());
auto dict_paul = paul.get_dictionary(col);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this work, since this column is not a dictionary? Is this a new nested collection API shortcut that I've missed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was actually missing a set_collection call.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find it a bit strange that the core API allowed that to happen without throwing on a type check.

void evaluate(size_t index, ValueBase& destination) override
{
ColumnsCollection<Mixed>::evaluate<Mixed>(index, destination);
if (m_path.size() > 1) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it possible that the path is of length 1? What happens in that case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then the base class will use path[0] and no further processing is needed.

CHANGELOG.md Outdated
@@ -3,6 +3,8 @@
### Enhancements
* <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>).
* Quering a specific entry in a list-of-primitives (in particular 'first and 'last') is supported.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

keys.set_parent(&top, 0);
keys.init_from_parent();
size_t ndx = keys.find_first(StringData(begin->get_key()));
if (ndx != realm::not_found) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to see some tests where the key is found and there is more levels in the path, but the dictionary key contains a simple primitive value and not another nested level. In that case, we should return Null early and not recurse further (also for lists).

Copy link
Contributor Author

@jedelbo jedelbo Jun 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add some tests. We will always make a recursive call if the key is found, but that call will return quickly as non of the tests for type will succeed. Do you think this is a problem? Otherwise we would have to do the tests twice.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems fine to me 👍

@jedelbo jedelbo requested review from nicola-cab and ironage June 16, 2023 11:56
@nicola-cab
Copy link
Member

Copy link
Contributor

@ironage ironage left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM when CI is passing.

CHANGELOG.md Outdated
@@ -3,6 +3,8 @@
### Enhancements
* <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>).
* Quering 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))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Quering 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 list-of-primitives (in particular 'first and 'last') is supported. (PR [#4269](https://github.com/realm/realm-core/issues/4269))

@jedelbo jedelbo merged commit 26d37e2 into next-major Jun 19, 2023
@jedelbo jedelbo deleted the je/query-index-stage-1 branch June 19, 2023 10:40
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 21, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants