Skip to content

Replace ExecuteSelectionSet with ExecuteCollectedFields #1039

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

Merged
merged 25 commits into from
Jul 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b76671b
Extract common logic from ExecuteQuery, ExecuteMutation and ExecuteSu…
benjie Apr 28, 2023
c9837a4
Change ExecuteSelectionSet to ExecuteGroupedFieldSet
benjie Apr 28, 2023
a52310e
Correct reference to MergeSelectionSets
benjie Aug 21, 2023
60a9c35
move Field Collection section earlier (#1111)
yaacovCR Oct 17, 2024
a1de2dd
Merge branch 'main' into benjie/incremental-common
benjie Jan 9, 2025
e8f80c8
Merge branch 'main' into benjie/incremental-common
benjie Mar 6, 2025
213fd2a
Define 'grouped field set'
benjie Mar 6, 2025
383cf8e
that -> which
benjie Mar 6, 2025
48a789b
More similar to prior wording
benjie Mar 6, 2025
0b9eed7
Remove reason from definition
benjie Mar 6, 2025
0728c4a
subGroupedFieldSet -> fieldGroupedFieldSet
benjie Mar 6, 2025
140c3da
Add note for clarity
benjie Mar 6, 2025
65df539
Merge branch 'main' into benjie/incremental-common
benjie Apr 17, 2025
d68df95
move field collections into one section, section reworking, minor wor…
leebyron Apr 17, 2025
180a51c
Apply suggestions from code review
benjie Apr 24, 2025
3c6dfb3
Rename 'ExecuteGroupedFieldSet' to 'ExecuteCollectedFields'
benjie Apr 25, 2025
5459f16
Merge branch 'main' into benjie/incremental-common
benjie May 1, 2025
70de903
Merge branch 'main' into benjie/incremental-common
benjie May 22, 2025
d0fb75c
Lee editorial + manual merge #1161
leebyron Jun 30, 2025
9c4a529
also rename grouped field set -> collected fields map
leebyron Jul 1, 2025
22c5888
Merge branch 'main' into benjie/incremental-common
leebyron Jul 1, 2025
97d43ba
include changes after merging master
leebyron Jul 1, 2025
301a81b
Merge branch 'main' into benjie/incremental-common
leebyron Jul 1, 2025
de56b68
fixup map iterations
leebyron Jul 1, 2025
cc17846
editorial
leebyron Jul 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions spec/Section 3 -- Type System.md
Original file line number Diff line number Diff line change
Expand Up @@ -779,8 +779,8 @@ type Person {
}
```

Valid operations must supply a nested field set for any field that returns an
object, so this operation is not valid:
Valid operations must supply a _selection set_ for every field of an object
type, so this operation is not valid:

```graphql counter-example
{
Expand Down
47 changes: 24 additions & 23 deletions spec/Section 5 -- Validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,24 +303,25 @@ query getName {
- Let {subscriptionType} be the root Subscription type in {schema}.
- For each subscription operation definition {subscription} in the document:
- Let {selectionSet} be the top level selection set on {subscription}.
- Let {groupedFieldSet} be the result of
- Let {collectedFieldsMap} be the result of
{CollectSubscriptionFields(subscriptionType, selectionSet)}.
- {groupedFieldSet} must have exactly one entry, which must not be an
- {collectedFieldsMap} must have exactly one entry, which must not be an
introspection field.

CollectSubscriptionFields(objectType, selectionSet, visitedFragments):

- If {visitedFragments} is not provided, initialize it to the empty set.
- Initialize {groupedFields} to an empty ordered map of lists.
- Initialize {collectedFieldsMap} to an empty ordered map of ordered sets.
- For each {selection} in {selectionSet}:
- {selection} must not provide the `@skip` directive.
- {selection} must not provide the `@include` directive.
- If {selection} is a {Field}:
- Let {responseKey} be the response key of {selection} (the alias if
- Let {responseName} be the _response name_ of {selection} (the alias if
defined, otherwise the field name).
- Let {groupForResponseKey} be the list in {groupedFields} for
{responseKey}; if no such list exists, create it as an empty list.
- Append {selection} to the {groupForResponseKey}.
- Let {fieldsForResponseKey} be the _field set_ value in
{collectedFieldsMap} for the key {responseName}; otherwise create the
entry with an empty ordered set.
- Add {selection} to the {fieldsForResponseKey}.
- If {selection} is a {FragmentSpread}:
- Let {fragmentSpreadName} be the name of {selection}.
- If {fragmentSpreadName} is in {visitedFragments}, continue with the next
Expand All @@ -334,31 +335,31 @@ CollectSubscriptionFields(objectType, selectionSet, visitedFragments):
- If {DoesFragmentTypeApply(objectType, fragmentType)} is {false}, continue
with the next {selection} in {selectionSet}.
- Let {fragmentSelectionSet} be the top-level selection set of {fragment}.
- Let {fragmentGroupedFieldSet} be the result of calling
- Let {fragmentCollectedFieldMap} be the result of calling
{CollectSubscriptionFields(objectType, fragmentSelectionSet,
visitedFragments)}.
- For each {fragmentGroup} in {fragmentGroupedFieldSet}:
- Let {responseKey} be the response key shared by all fields in
{fragmentGroup}.
- Let {groupForResponseKey} be the list in {groupedFields} for
{responseKey}; if no such list exists, create it as an empty list.
- Append all items in {fragmentGroup} to {groupForResponseKey}.
- For each {responseName} and {fragmentFields} in
{fragmentCollectedFieldMap}:
- Let {fieldsForResponseKey} be the _field set_ value in
{collectedFieldsMap} for the key {responseName}; otherwise create the
entry with an empty ordered set.
- Add each item from {fragmentFields} to {fieldsForResponseKey}.
- If {selection} is an {InlineFragment}:
- Let {fragmentType} be the type condition on {selection}.
- If {fragmentType} is not {null} and {DoesFragmentTypeApply(objectType,
fragmentType)} is {false}, continue with the next {selection} in
{selectionSet}.
- Let {fragmentSelectionSet} be the top-level selection set of {selection}.
- Let {fragmentGroupedFieldSet} be the result of calling
- Let {fragmentCollectedFieldMap} be the result of calling
{CollectSubscriptionFields(objectType, fragmentSelectionSet,
visitedFragments)}.
- For each {fragmentGroup} in {fragmentGroupedFieldSet}:
- Let {responseKey} be the response key shared by all fields in
{fragmentGroup}.
- Let {groupForResponseKey} be the list in {groupedFields} for
{responseKey}; if no such list exists, create it as an empty list.
- Append all items in {fragmentGroup} to {groupForResponseKey}.
- Return {groupedFields}.
- For each {responseName} and {fragmentFields} in
{fragmentCollectedFieldMap}:
- Let {fieldsForResponseKey} be the _field set_ value in
{collectedFieldsMap} for the key {responseName}; otherwise create the
entry with an empty ordered set.
- Add each item from {fragmentFields} to {fieldsForResponseKey}.
- Return {collectedFieldsMap}.

Note: This algorithm is very similar to {CollectFields()}, it differs in that it
does not have access to runtime variables and thus the `@skip` and `@include`
Expand Down Expand Up @@ -584,7 +585,7 @@ should be unambiguous. Therefore any two field selections which might both be
encountered for the same object are only valid if they are equivalent.

During execution, the simultaneous execution of fields with the same response
name is accomplished by {MergeSelectionSets()} and {CollectFields()}.
name is accomplished by {CollectSubfields()} before execution.

For simple hand-written GraphQL, this rule is obviously a clear developer error,
however nested fragments can make this difficult to detect manually.
Expand Down
Loading