-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Spec edits to reduce "query ambiguity" #777
Conversation
Thank you for tackling this! 🙏
|
Also I accidentally included an earlier decision which was to use "operation document" which I've since rethought and gone with simply "document"; so have edited that into the description too. |
Why do you include schema and initial value in graphql request? This is purely server side implementation concept. |
@sungam3r good question. The answer’s straight-forward: because that’s how the GraphQL spec defines it; this isn’t definitions for accessing a GraphQL schema over HTTP (for example), a request in schema spec terms relates to the items listed: |
GraphQL spec defines implementation part of executing request with some additional server-side context - schema and initialValue. In this paragraph, I do not see that the specification describes the content of the request. It says
Executor can have any number of things to execute the request, not related to the request itself.
It always seemed to me that the request should be defined as a (document, operationName, variables) for an arbitrary transport. To be honest, I find it strange if its definition would include something else. |
I'm not sure; all requests indicate a schema - sometimes by explicitly having a schema instance, sometimes by referencing the schema via URL endpoint. You can't validate a GraphQL request without knowing to which GraphQL schema it applies. (Not true for the initial value, sure.) But anyway; we're currently discussing something that's not actually part of the changes proposed by this PR - you're currently commenting on my notes on the terms that I added so that we as GraphQL Working Group members would know what's being referenced. An actual RFC to add a glossary would be a separate PR which can and should have this kind of discussion on this and many other topics. |
Ok |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the clarifications very much! 👍
I saw that you introduced the term “query operation” for an operation of type “query”, but didn’t use it consistently in the examples. To be consistent, the examples should then also be “query operations” to distinguish them from mutation / subscription operations. Of course the alternative would be to change “query operation” to “operation” in the other places instead.
As another thought, maybe for the glossary, now that “query” has been de-overloaded. What does the naked term “query” actually mean and when is it appropriate to use it?
@@ -431,7 +432,7 @@ Many arguments can exist for a given field: | |||
Arguments may be provided in any syntactic order and maintain identical | |||
semantic meaning. | |||
|
|||
These two queries are semantically identical: | |||
These two operations are semantically identical: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
“Query operations”, to be consistent.
@@ -593,7 +594,7 @@ fragment standardProfilePic on User { | |||
} | |||
``` | |||
|
|||
The queries `noFragments`, `withFragments`, and `withNestedFragments` all | |||
The operations `noFragments`, `withFragments`, and `withNestedFragments` all |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
“Query operations”, to be consistent.
spec/Section 2 -- Language.md
Outdated
If a document contains only one query operation, and that query defines no | ||
variables and contains no directives, that operation may be represented in a | ||
short-hand form which omits the query keyword and query name. | ||
If a document contains only one operation and the operation is query operation, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
“a query operation”
@@ -1045,7 +1046,7 @@ literal representation of input objects as "object literals." | |||
Input object fields may be provided in any syntactic order and maintain | |||
identical semantic meaning. | |||
|
|||
These two queries are semantically identical: | |||
These two operations are semantically identical: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
“Query operations”, to be consistent.
spec/Section 4 -- Introspection.md
Outdated
@@ -16,7 +16,7 @@ type User { | |||
} | |||
``` | |||
|
|||
The query | |||
The operation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
“Query operation”, to be consistent.
@@ -1587,7 +1587,7 @@ extend type Query { | |||
} | |||
``` | |||
|
|||
The following queries are valid: | |||
The following operations are valid: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
“Query operations”, to be consistent.
@@ -1607,7 +1607,7 @@ query TakesListOfBooleanBang($booleans: [Boolean!]) { | |||
} | |||
``` | |||
|
|||
The following queries are invalid: | |||
The following operations are invalid: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
“Query operations”, to be consistent.
@@ -687,7 +687,7 @@ When more than one field of the same name is executed in parallel, their | |||
selection sets are merged together when completing the value in order to | |||
continue execution of the sub-selection sets. | |||
|
|||
An example query illustrating parallel fields with the same name with | |||
An example operation illustrating parallel fields with the same name with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
“Query operation”, to be consistent.
|
||
For example, if fetching one of the friends' names fails in the following | ||
query: | ||
operation: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
“Query operation”, to be consistent.
@vwkd Thanks for your review. There's a reason that I used |
@benjie I intendedly left out the places where an operation was defined or mentioned in general, and commented only where there was a concrete example showing a query operation. I don't think explicitly mentioning the type of the operation in the example is implying that whatever was defined before it couldn't be used for operations of other types. On the contrary, I think being explicit about the type of operation used in the example helps clear confusion, just as mentioning if some shorthand is used in an example would too, but that's probably better saved for another time. |
Is it only me, or does |
Would it make sense to formalize the glossary you've created in the description, even in just for "internal" use? It would seem useful for those creating documentation as part of formal working group activities. I think members of the community would also benefit from something like this as it would help to further align usage of these terms. |
Absolutely; it’s one of my action items to push that forward (it’s just currently queued up behind a few higher priority items). |
@@ -68,7 +68,7 @@ schema { | |||
} | |||
|
|||
""" | |||
Root type for all your queries | |||
Root type for all your query operations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a valid use of the term query operation
? According to the spec and the glossary I believe a query operation is an OperationDefinition
with the type query
.
If this is not a valid use of the term, what term should be used to describe these fields on the Query type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I recently had a conversation with a colleague here at Indeed and used (misused?) the term query operation
in a similar context.
I said something like "when a response includes data for multiple query operations...". He pointed me to the spec and pointed out that only one query operation
can be executed.
What I was trying to communicate was that it's possible to select multiple fields on the top level Query type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Query
is the root type for all query operations; you issue a selection set against the Query root type, this selection set may select more than one field like most selection sets (the exception being the selection set at the root of the subscription
operation).
Here's a (single) query operation issuing a selection set against a root Query type:
query {
__typename
myField
myOtherField { id }
}
So yes, I believe the usage here is correct.
According to the spec and the glossary I believe a query operation is an OperationDefinition with the type query.
Correct.
He pointed me to the spec and pointed out that only one query operation can be executed.
He's correct 👍
What term should be used to describe these fields on the Query type?
You could call them "Query fields" I guess; just like fields on the User type would by "User fields." I'm not sure we have an established name for them, the root level fields on the mutation
operation would generally be called "mutation fields" and for subscription
"subscription fields" so I think "query fields" would make sense, but is potentially ambiguous.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW the historical official name for these were "root fields" - when we generalized roots to be no different from other types, we dropped an official name. I've also heard "top level fields" which makes sense to me, but "Query fields" or "Fields on the Query type" both would be perfectly clear
5912463
to
e114dae
Compare
I'll review this in the next few hours 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally good improvements to the text; I've called out a few things that I don't fully agree with and some minor issues which I will fix shortly.
I've added 4 more tiny commits which are justified in the resolved comments above (including references to the commit). There's a couple other changes that I think may warrant exploration (these are still open above); but I'm happy with this being merged as is. |
324a6bf
to
07aec6e
Compare
Factored out of #777 - this rephrases input object introspection to be more accurate.
Clarify use of root types and improve formatting. Factored out of #777
Clarify the rules for using query shorthand. Factored out of #777
Factored out of #777. Clarifies when type definition & extension can and cannot be included in executable documents To do this more clearly, this introduces a number of new grammar rules. This does not change the actual behavior of a parser (all existing docs are parsed equivalently, no new docs are legal). However instead of using language that manipulates existing rules this can just reference those already restricted. Hopefully this actually is useful for implementations which seek to offer clear subsets for each use case.
c3a9e01
to
8278927
Compare
Factored out of #777. This clarifies the relationship between field aliases and response keys.
Factored out of #777. This clarifies the relationship between field aliases and response keys.
Factored out of #777. This clarifies the relationship between field aliases and response keys.
8278927
to
7bd26f7
Compare
Derived from #777 Renames "field" to "meta-field" consistently. Adds "with the single exception of the subscription root operation type". Clarifies some language.
The glossary entries in this PR description have been extracted to #846 (and they've also been improved). |
Factored out of #777. Clarifies when type definition & extension can and cannot be included in executable documents To do this more clearly, this introduces a number of new grammar rules. This does not change the actual behavior of a parser (all existing docs are parsed equivalently, no new docs are legal). However instead of using language that manipulates existing rules this can just reference those already restricted. Hopefully this actually is useful for implementations which seek to offer clear subsets for each use case.
623f655
to
faf8683
Compare
* Editorial: Clarify meta-fields in introspection Derived from #777 Renames "field" to "meta-field" consistently. Adds "with the single exception of the subscription root operation type". Clarifies some language. * Update spec/Section 4 -- Introspection.md Co-authored-by: Benjie Gillam <benjie@jemjie.com> * Update spec/Section 4 -- Introspection.md Co-authored-by: Benjie Gillam <benjie@jemjie.com> * Update spec/Section 4 -- Introspection.md Co-authored-by: Benjie Gillam <benjie@jemjie.com> * wrap Co-authored-by: Benjie Gillam <benjie@jemjie.com>
I went through this editorial in two passes. One where I tuned the usage of "operation", "request", and "selection set". I hopefully made these spots slightly clearer, but I'm open to feedback. Second pass was more freeform prose edits in cases where I thought the intended ideas could have been clearer and avoid the query ambiguity in the first place.
faf8683
to
e36b4b1
Compare
Following revisions in the spec graphql/graphql-spec#777, this commit applies similar changes to type and method names where feasible. The chief exception for now is the use of "query" for request input since that is what it is called in the JSON for GraphQL over HTTP.
This PR addresses the "query ambiguity" issue raised in #715 and discussed in the May 2020 GraphQL Working Group.
I went through every usage of the word
query
,queries
andqueried
in the spec and attempted to discern the different terminology we have going on. I've come up with the following definitions which are broadly in line with the terminology the spec already uses in places.What follows are notes I took whilst doing this work, which also constitutes the beginnings of a glossary. This glossary is probably sufficient for WG members who already understand these concepts, but I'll need to tidy them up and define them more concretely if we want to add them as a glossary to the spec itself. (Also need to populate it with non-
query
terms.) I think if we do decide to add a glossary we should do that as a separate PR.Glossary
When usage of these terms may cause ambiguity* the normally optional
parenthesized "(GraphQL)" should be included for clarity.
* example of an ambiguous phrase: "sending a request to a server" may refer to
an HTTP request, network request, or a GraphQL request.
(GraphQL) operation
Definition: an action you wish GraphQL to perform, for example retrieving
data, mutating data or state, or subscribing to events.
Examples:
Used in the GraphQL spec:
(GraphQL) operation type
Definition: a type of operation supported by GraphQL - "query", "mutation", or
"subscription".
Examples:
Not to be confused with (GraphQL) root operation type.
Used in the GraphQL spec:
(GraphQL) query operation
A GraphQL operation of type
query
.Used in the GraphQL spec:
(GraphQL) mutation operation
A GraphQL operation of type
mutation
.Used in the GraphQL spec:
(GraphQL) subscription operation
A GraphQL operation of type
subscription
.Used in the GraphQL spec:
(GraphQL) root operation type
The GraphQL object type associated with a given GraphQL operation type within
the schema.
Used in the GraphQL spec:
(GraphQL) document
Definition: the textual representation (using GraphQL query language) of an
operation (or operations) you wish to perform, including selection sets and
fragments as appropriate.
Examples:
Inspired by.
Alternatives considered:
(GraphQL) operation variables
Definition: variables declared within an operation.
Previously "query variables".
Example:
$devicePicSize
is an operation variable in the following operation:Why not "request variables"? The variables are declared in the operation and
there doesn't seem to be a need to push the definition up to request level.
(GraphQL) request
Definition: the full description of what you wish GraphQL to execute,
including the GraphQL schema, document, variables, operation name and initial
value.
Used in the GraphQL spec:
(GraphQL) request error
Definition: an error which occurs during validating a GraphQL request
(including coercing the variables) resulting in the entire GraphQL request
being aborted.
Previously: consistently "query error" throughout the spec.
Why not "query error"? It also occurs for mutations, subscriptions, and invalid
documents.
Why not "operation error"? It can occur when operationName is not specified,
and thus the operation is indeterminate. Further it may result from invalid
variables which are a GraphQL request concern, not a GraphQL operation concern.
Unmodified terms
The verb "to query" is left in may places, as is the term "query language". A few of these are noted below:
Questionable terms
query reuse
"query reuse" w.r.t fragments. "query" seems like the wrong term here (because
of how overloaded/vague it is) but I can't come up with a succinct alternative.
Best I've come up with is "data requirement reuse," but I'm not super happy
with it.
queried
querying
Can be replaced with 'selecting' / 'selecting fields from', using 'select' as
in 'selection set'.
query of
request
In many cases 'request' can be replaced with 'fetch' to avoid ambiguity with
'GraphQL request'.
query root object type
Also mutation/subscription root object type and simply "query root type". These
have the same meaning as query "root operation type", but "root object type" is
more explicit that the root operation type is an object type. We should pick
between them and stick to that throughout.
query execution
Replaced with "request execution" due to the function being called
ExecuteRequest
Interesting terms
Fetch
Response key
Ethos
Rather than being conservative with edits and leaving ambiguity I was quite heavy
Status
This is not ready for merging, it's only a first edit and there's likely inconsistencies where the final rules I applied weren't reapplied to earlier edits. Mostly this is a discovery exercise.
Next steps
I'll add this to the next GraphQL WG. I have broadly the following questions: