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

Fixes #725: OneOfThemWith{Component,} does not distinguish empty vs null #726

Merged
merged 5 commits into from Sep 26, 2019

Conversation

MMcM
Copy link
Contributor

@MMcM MMcM commented Sep 18, 2019

This introduces a new boolean parameter to oneOfThem and everything else in that path.

Note that no changes are made to the planner, which does not care about the difference, since it only turns query component into index operations in cases as part of a filter expression without anything like IS UNKNOWN or NOT.

@MMcM
Copy link
Contributor Author

MMcM commented Sep 18, 2019

A simpler change would be to just change the behavior to treat repeated fields uniformly always. In addition to being an incompatible change to a maintained class, I can imagine cases where the current behavior is desirable.

@@ -64,6 +64,17 @@ public OneOfThem oneOfThem() {
return new OneOfThem(fieldName);
}

/**
* If the associated field is a repeated one, this allows you to match against one of those values, the record will
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a comma splice (as is the first sentence of the docs on oneOfThem()). (More specifically, the comma between "values" and "the" is splicing; the comma between "one" and "this" is fine.)

}

@Nullable
@SuppressWarnings("unchecked")
protected List<Object> getValues(@Nonnull MessageOrBuilder message) {
final Descriptors.FieldDescriptor field = findFieldDescriptor(message);
if (message.getRepeatedFieldCount(field) == 0) {
if (emptyIsUnknown && message.getRepeatedFieldCount(field) == 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

It's possible I'm conflating some things, but I believe that there was some discussion that one could use the null/not null behavior of the field (as referenced in #677) to determine whether an unset repeated field should be the empty list (i.e., "not null") or null. It kind of seems like those are related, though maybe it's more difficult than we want to bring those two parts of the code base together. (Perhaps I was thinking of whether one should include null in fanout indexes, though I suppose one could also want that same control when trying to determine if one wants to put null or the empty list into a Concatenate index.)

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 can't figure out how to have a unified single expression of "null-handling" that works compatibly. Still, if the approach to #677 were to have some kind of "field options" that could be set at multiple levels, those options could include the new emptyIsUnknown, set on the Query.field instead of oneOfThem and inherited from the meta-data's field.

Concretely, instead of

Query.field("f1").oneOfThem(false).matches(...)

have

Query.field("f1").withOptions(FieldOptions.newBuilder().setEmptyIsUnknown(false).build()).oneOfThem().matches(...)

Would something along those lines still be worth it?

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't really see how the latter (in the example) would be better, no. I think the idea was more like if you had a field option set in the meta-data on the record that the repeated field were NOT_NULL (or equivalent), then it would fill in emptyIsUknown to false (or, in other words, it would evaluate the field as an empty list instead of a null list).

It's kind of hard to rendezvous those two things, though, so maybe emptyIsUnknown as a component option is better.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it does seem weird that saying at the meta-data level that a field does not do null values at all still does not affect this. Perhaps, instead of fully unifying the specification, just the default value for oneOfThem() could be influenced?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I think that's a sensible contract--that if you set emptyIsUnknown, then it does whatever the default from the null behavior would be. I guess for now DEFAULT is equivalent to EMPTY_IS_UNKNOWN, but maybe that changes to "whatever the field options say" after #677?

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, so I think the only question is whether this should be an enum here, with maybe the default option doing the same thing as the "empty is unknown" option (for now) but leaving room to make it use the field options if available.

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 made it an enum, with two values for now and a TODO comment about adding a third that means based on the null behavior of the field in the meta-data.

@alecgrieser
Copy link
Contributor

Do you know why 8596b15 is showing up here? Is that a GitHub artifact, or is something weird with the rebase?

@MMcM
Copy link
Contributor Author

MMcM commented Sep 23, 2019

Do you know why 8596b15 is showing up here? Is that a GitHub artifact, or is something weird with the rebase?

I think it has something to do with accepting suggested fixes.

@alecgrieser
Copy link
Contributor

I think it has something to do with accepting suggested fixes.

Ah, I see. It might make sense to squash this one, when it's merged then, to avoid weird things happening to history, though maybe it'd be fine either way.

@alecgrieser
Copy link
Contributor

Or maybe the point is moo, as the most recent push seems to have fixed it up.

MMcM and others added 5 commits September 26, 2019 11:33
…h empty vs null

This introduces a new boolean parameter to `oneOfThem` and everything else in that path.
…ord/query/expressions/Field.java

Co-Authored-By: Alec Grieser <alloc@apple.com>
…ord/query/expressions/Field.java

Co-Authored-By: Alec Grieser <alloc@apple.com>
@alecgrieser alecgrieser merged commit d06dd19 into FoundationDB:master Sep 26, 2019
@MMcM MMcM deleted the one-of-empty-null-option branch September 26, 2019 20:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants