Support non-archetypal QueryData
#21581
Open
+390
−193
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Objective
For #17647, we want to create a
QueryData
that can follow a relation and query data from an entity's parent. If the parent does not have the queried data, the child entity should be skipped in the query. However, there is no way to tell from the child's archetype whether the parent will match! So, we need to support non-archetypalQueryData
, just as we support non-archetypalQueryFilter
s forAdded
andChanged
.That is, if
Query<Parent<&T>>
yields&T
, and we do:then
query
must yield a row forchild1
but not forchild2
, even though they have the same archetype.Solution
Change
QueryData::fetch
to returnOption
so that entities can be filtered during fetching by returningNone
.To support
ExactSizeIterator
, introduce anArchetypeQueryData
trait and anQueryData::IS_ARCHETYPAL
associated constant, similar toArchetypeFilter
andQueryFilter::IS_ARCHETYPAL
. Implement this trait on existingQueryData
types. ModifyExactSizeIterator
implementations to requireD: ArchetypeQueryData
, and thesize_hint()
methods to return a minimum size of0
if!D::IS_ARCHETYPAL
.Alternatives
We could do nothing here, and have
Query<Parent<&T>>
yieldOption<&T>
. That makes the API less convenient, though. Note that if one wants to query forOption
, they can use eitherQuery<Option<Parent<&T>>
orQuery<Parent<Option<&T>>
, depending on whether they want to include entities with no parent.Another option is to re-use the
ArchetypeFilter
trait instead of introducing a new one. There are no places where we want to abstract over both, however, and it would require writing bounds likeD: QueryData + ArchetypeFilter, F: QueryFilter + ArchetypeFilter
instead of simplyD: ArchetypeQueryData, F: ArchetypeFilter
.