From 220e8d4c7574dd65121b8db623e63a3b0d975590 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Sat, 23 May 2026 15:00:00 -0700 Subject: [PATCH 1/3] Allow empty selection sets --- spec/Appendix C -- Grammar Summary.md | 2 +- spec/Section 2 -- Language.md | 2 +- spec/Section 3 -- Type System.md | 7 +++---- spec/Section 5 -- Validation.md | 4 ++-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/spec/Appendix C -- Grammar Summary.md b/spec/Appendix C -- Grammar Summary.md index cc464a4a6..6635a3a23 100644 --- a/spec/Appendix C -- Grammar Summary.md +++ b/spec/Appendix C -- Grammar Summary.md @@ -156,7 +156,7 @@ OperationDefinition : OperationType : one of `query` `mutation` `subscription` -SelectionSet : { Selection+ } +SelectionSet : { Selection\* } Selection : diff --git a/spec/Section 2 -- Language.md b/spec/Section 2 -- Language.md index e00683019..f46372671 100644 --- a/spec/Section 2 -- Language.md +++ b/spec/Section 2 -- Language.md @@ -383,7 +383,7 @@ Note: many examples below will use the query shorthand syntax. ## Selection Sets -SelectionSet : { Selection+ } +SelectionSet : { Selection\* } Selection : diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index 1be92a0ea..9b3b36796 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -716,7 +716,7 @@ Where `name` is a field that will yield a {String} value, and `age` is a field that will yield an {Int} value, and `picture` is a field that will yield a `Url` value. -A query of an object value must select at least one field. This selection of +A query of an object value must be made via a selection set. This selection of fields will yield an ordered map containing exactly the subset of the object queried, which should be represented in the order in which they were queried. Only fields that are declared on the object type may validly be queried on that @@ -1933,9 +1933,8 @@ to denote a field that uses a Non-Null type like this: `name: String!`. **Nullable vs. Optional** Fields are _always_ optional within the context of a _selection set_, a field -may be omitted and the selection set is still valid (so long as the selection -set does not become empty). However fields that return Non-Null types will never -return the value {null} if queried. +may be omitted and the selection set is still valid. However fields that return +Non-Null types will never return the value {null} if queried. Inputs (such as field arguments), are always optional by default. However a non-null input type is required. In addition to not accepting the value {null}, diff --git a/spec/Section 5 -- Validation.md b/spec/Section 5 -- Validation.md index 88a8b8e2c..a71c379f5 100644 --- a/spec/Section 5 -- Validation.md +++ b/spec/Section 5 -- Validation.md @@ -720,9 +720,9 @@ fragment conflictingDifferingResponses on Pet { - For each {selection} in the document: - Let {selectionType} be the unwrapped result type of {selection}. - If {selectionType} is a scalar or enum: - - The subselection set of that selection must be empty. + - The subselection set of that selection must not be present. - If {selectionType} is an interface, union, or object: - - The subselection set of that selection must not be empty. + - The subselection set of that selection must be present. **Explanatory Text** From 27145940ed63e2fbb5de331c15de96949eb78225 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Fri, 4 Sep 2026 11:22:55 +0100 Subject: [PATCH 2/3] Add examples to make empty selections more obvious --- spec/Section 5 -- Validation.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/spec/Section 5 -- Validation.md b/spec/Section 5 -- Validation.md index a71c379f5..a55d7d149 100644 --- a/spec/Section 5 -- Validation.md +++ b/spec/Section 5 -- Validation.md @@ -747,6 +747,14 @@ fragment scalarSelectionsNotAllowedOnInt on Dog { } ``` +An empty selection is still a selection, so the following is also invalid. + +```graphql counter-example +fragment scalarEmptySelectionsNotAllowedOnInt on Dog { + barkVolume {} +} +``` + Conversely, non-leaf fields must have a field subselection. A non-leaf field is any field with an object, interface, or union unwrapped type. @@ -788,6 +796,14 @@ query directQueryOnObjectWithSubFields { } ``` +The subselection is permitted to be empty, so the following is also valid. + +```graphql example +query directQueryOnObjectWithEmptySelection { + human {} +} +``` + ## Arguments Arguments are provided to both fields and directives. The following validation From e10dca193db77346596cb327065d904cb74f3a65 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Fri, 4 Sep 2026 11:25:12 +0100 Subject: [PATCH 3/3] Minus a word --- spec/Section 5 -- Validation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/Section 5 -- Validation.md b/spec/Section 5 -- Validation.md index a55d7d149..6206d92e0 100644 --- a/spec/Section 5 -- Validation.md +++ b/spec/Section 5 -- Validation.md @@ -747,7 +747,7 @@ fragment scalarSelectionsNotAllowedOnInt on Dog { } ``` -An empty selection is still a selection, so the following is also invalid. +An empty selection is a selection, so the following is also invalid. ```graphql counter-example fragment scalarEmptySelectionsNotAllowedOnInt on Dog {