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

Migrate to text based query parser. #7318

Merged
merged 81 commits into from
Mar 26, 2021

Conversation

clementetb
Copy link
Collaborator

@clementetb clementetb commented Feb 22, 2021

Refactors the current type-safe query system in Ream Java to use the new string-based query parser. It introduced some behavioral changes:

  • Querying for equalto/notequalto null on non-nullable fields no longer throws.
  • or() with not right part does not throw.
  • distinct() does not fail on invalid types/unknown fields.
  • isEmpty/isNotEmpty now works with all Realm list types (before it only worked on Realm Objects Lists).
  • There is no actual query validation until it gets executed.

String operations contains, like, beginsWith, endsWith enforce non-null value arguments. These operations arguments were marked as non-null but no check was in place.

Known issues

@clementetb clementetb self-assigned this Feb 22, 2021
@clementetb clementetb requested review from cmelchior and edualonso and removed request for cmelchior February 26, 2021 16:03
Copy link
Contributor

@cmelchior cmelchior left a comment

Choose a reason for hiding this comment

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

Really nice... are a bunch of tests that needs to be revisited though. And I had some comments to implementation in places.

One question though: If FieldDescriptors are no longer needed, couldn't we also remove a lot of code from the ProxyClassGenerator?

CHANGELOG.md Outdated
@@ -1,12 +1,18 @@
## 10.4.0 (YYYY-MM-DD)
### Breaking Changes
* Queries no longer check do nullability checks on non-nullable fields.
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
* Queries no longer check do nullability checks on non-nullable fields.
* Queries no longer do nullability checks on non-nullable fields, so using `null` as an argument will not throw an `IllegalArgumentException`

CHANGELOG.md Outdated

### Known Bugs
* Java field names not supported on Sort or Distinct operations. (Issue [#4550] (https://github.com/realm/realm-core/issues/4550))
* Queries on fields named with non-latin characters are not currently supported. (Issue [#4467] (https://github.com/realm/realm-core/issues/4467))
Copy link
Contributor

Choose a reason for hiding this comment

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

It is fine to have this entry when merging this PR, but I would consider this a blocker for releasing.

@@ -725,6 +725,7 @@ public void run() throws Exception {
}

@Test
@Ignore("FIXME: See https://github.com/realm/realm-core/issues/4469")
Copy link
Contributor

Choose a reason for hiding this comment

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

The issue has been closed, so this test should probably be updated.

fail();
} catch (IllegalArgumentException ignored) {
}
RealmResults<Owner> owners7 = testRealm.where(Owner.class).between("cat.age", 1, 20).findAll();
Copy link
Contributor

Choose a reason for hiding this comment

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

It also closes this issue: #2204 🥳 , so should definitely be in the CHANGELOG

* <p>
* Class and property names used in the raw predicate can be either the names defined in the
* Realm Model classes or the internal names defined using the {@link io.realm.annotations.RealmClass}
* or {@link io.realm.annotations.RealmField} annotations.
* <p>
Copy link
Contributor

Choose a reason for hiding this comment

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

Any reason to remove this?
We should probably also add something about neededing to escape field names with spaces?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Shouldn't have removed. Added a comment on escaping field and class names.

this.context = sharedRealm.context;
this.sharedRealm = sharedRealm;
this.nativeTableRefPtr = nativeTableRefPointer;
this.osKeyPathMapping = osKeyPathMapping;
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure it is safe to store it like this? The keypath mapping can be updated by a callback from Core, making storing it here dangerous. Unless the usage is very shortlived. But maybe I am missing something?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Great catch, it is not safe as it can be recreated by a callback from core.

private boolean queryValidated = true;

// TODO: Can we protect this?
public TableQuery(NativeContext context, Table table, long nativeQueryPtr) {
private static String escapeFieldName(String fieldName) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure it is a bug as such, just something we need to document for using the string-based queries.

queryValidated = false;
return this;
}
sortSeparator = ", ";
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems to lead to trailing , . That is okay with the Query Parser?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It is fine! We use the separator between fields.

if (value == null) { throw new IllegalArgumentException(DATE_NULL_ERROR_MESSAGE); }
nativeGreaterTimestamp(nativePtr, columnKey, tablePtrs, value.getTime());
public TableQuery isEmpty(String fieldName) {
rawPredicateWithPointers(escapeFieldName(fieldName) + ".@count = 0");
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this also work with Strings? If I remember correctly the old isEmpty() also accepted Strings?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, it does!

@@ -3097,30 +3095,28 @@ private void distinctAllFields(Realm realm, String prefix) {
types.remove(type);
}

// Verify that we have tested all field types except LinkingObjects which is not part of
// the schema lookup
// Validate that backlinks are not supported by sort/distinct
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Distinct and sort don't support backlinks: realm/realm-core#4524

@clementetb clementetb merged commit 2f0eb94 into ct/mixed-datatype-story Mar 26, 2021
@clementetb clementetb deleted the ct/migrate-to-raw-queries branch March 26, 2021 13:59
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 15, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants