0
# Query Validation
1
2
Validate GraphQL documents against schemas using specification-defined validation rules and custom validation logic. Ensures queries are well-formed, use valid fields and types, and follow GraphQL specification requirements before execution.
3
4
## Capabilities
5
6
### Document Validation
7
8
Validate complete GraphQL documents against a schema using all specification-defined rules.
9
10
```python { .api }
11
def validate(
12
schema: GraphQLSchema,
13
document_ast: DocumentNode,
14
rules: Optional[Collection[Type[ASTValidationRule]]] = None,
15
max_errors: Optional[int] = None,
16
type_info: Optional[TypeInfo] = None,
17
) -> List[GraphQLError]
18
```
19
20
**Parameters:**
21
- `schema`: GraphQL schema to validate against
22
- `document_ast`: Parsed GraphQL document AST to validate
23
- `rules`: Optional custom validation rules (defaults to `specified_rules`)
24
- `max_errors`: Maximum number of errors to collect before stopping
25
- `type_info`: Optional type information context
26
27
**Returns:** List of validation errors found in the document
28
29
#### Usage Example
30
31
```python
32
from graphql import validate, parse, build_schema
33
34
schema = build_schema('''
35
type Query {
36
user(id: ID!): User
37
users: [User]
38
}
39
40
type User {
41
id: ID!
42
name: String
43
email: String
44
}
45
''')
46
47
# Valid query
48
valid_query_ast = parse('{ user(id: "123") { name email } }')
49
errors = validate(schema, valid_query_ast)
50
print(len(errors)) # 0
51
52
# Invalid query - unknown field
53
invalid_query_ast = parse('{ user(id: "123") { name invalidField } }')
54
errors = validate(schema, invalid_query_ast)
55
print(len(errors)) # 1
56
print(errors[0].message) # Cannot query field "invalidField" on type "User"
57
```
58
59
### Validation Context
60
61
Access validation state and type information during rule execution.
62
63
```python { .api }
64
class ValidationContext:
65
def __init__(
66
self,
67
schema: GraphQLSchema,
68
document: DocumentNode,
69
type_info: TypeInfo,
70
on_error: Callable[[GraphQLError], None]
71
)
72
73
def report_error(self, error: GraphQLError) -> None
74
def get_errors(self) -> List[GraphQLError]
75
def get_schema(self) -> GraphQLSchema
76
def get_document(self) -> DocumentNode
77
def get_fragment(self, name: str) -> Optional[FragmentDefinitionNode]
78
def get_fragment_spreads(self, node: SelectionSetNode) -> List[FragmentSpreadNode]
79
def get_recursively_referenced_fragments(self, operation: OperationDefinitionNode) -> List[FragmentDefinitionNode]
80
81
class ASTValidationContext(ValidationContext):
82
"""Validation context for executable documents"""
83
pass
84
85
class SDLValidationContext(ValidationContext):
86
"""Validation context for schema definition language documents"""
87
pass
88
```
89
90
### Validation Rules
91
92
All validation rules implement the ValidationRule interface and can be used individually or in combination.
93
94
```python { .api }
95
class ValidationRule:
96
def __init__(self, context: ValidationContext)
97
98
def enter(self, node: Node, key: Optional[str], parent: Optional[Node], path: List[Union[int, str]], ancestors: List[Node]) -> Optional[VisitorAction]
99
def leave(self, node: Node, key: Optional[str], parent: Optional[Node], path: List[Union[int, str]], ancestors: List[Node]) -> Optional[VisitorAction]
100
101
class ASTValidationRule(ValidationRule):
102
"""Base class for executable document validation rules"""
103
pass
104
105
class SDLValidationRule(ValidationRule):
106
"""Base class for schema definition language validation rules"""
107
pass
108
109
# All specification-defined validation rules
110
specified_rules: List[Type[ValidationRule]]
111
```
112
113
### Individual Validation Rules
114
115
Specification-defined validation rules that can be used individually or customized.
116
117
```python { .api }
118
# Executable definition rules
119
class ExecutableDefinitionsRule(ASTValidationRule):
120
"""Ensures only executable definitions (operations and fragments) are present"""
121
122
class LoneAnonymousOperationRule(ASTValidationRule):
123
"""Ensures anonymous operations are alone in the document"""
124
125
class UniqueOperationNamesRule(ASTValidationRule):
126
"""Ensures operation names are unique within a document"""
127
128
# Field and fragment rules
129
class FieldsOnCorrectTypeRule(ASTValidationRule):
130
"""Ensures fields are queried on types that define them"""
131
132
class FragmentsOnCompositeTypesRule(ASTValidationRule):
133
"""Ensures fragments are on composite types"""
134
135
class KnownFragmentNamesRule(ASTValidationRule):
136
"""Ensures fragment spreads refer to defined fragments"""
137
138
class NoFragmentCyclesRule(ASTValidationRule):
139
"""Prevents circular fragment references"""
140
141
class UniqueFragmentNamesRule(ASTValidationRule):
142
"""Ensures fragment names are unique"""
143
144
class NoUnusedFragmentsRule(ASTValidationRule):
145
"""Ensures all fragments are used"""
146
147
class PossibleFragmentSpreadsRule(ASTValidationRule):
148
"""Ensures fragment spreads are possible"""
149
150
class OverlappingFieldsCanBeMergedRule(ASTValidationRule):
151
"""Complex rule ensuring field selection merging is valid"""
152
153
# Argument rules
154
class KnownArgumentNamesRule(ASTValidationRule):
155
"""Ensures arguments are defined on fields and directives"""
156
157
class UniqueArgumentNamesRule(ASTValidationRule):
158
"""Ensures argument names are unique per field/directive"""
159
160
class ProvidedRequiredArgumentsRule(ASTValidationRule):
161
"""Ensures required arguments are provided"""
162
163
# Variable rules
164
class UniqueVariableNamesRule(ASTValidationRule):
165
"""Ensures variable names are unique per operation"""
166
167
class NoUndefinedVariablesRule(ASTValidationRule):
168
"""Ensures all used variables are defined"""
169
170
class NoUnusedVariablesRule(ASTValidationRule):
171
"""Ensures all defined variables are used"""
172
173
class VariablesAreInputTypesRule(ASTValidationRule):
174
"""Ensures variables are input types"""
175
176
class VariablesInAllowedPositionRule(ASTValidationRule):
177
"""Ensures variable usage matches definitions"""
178
179
# Value and type rules
180
class ValuesOfCorrectTypeRule(ASTValidationRule):
181
"""Ensures values match their expected types"""
182
183
class ScalarLeafsRule(ASTValidationRule):
184
"""Ensures scalar fields don't have selections"""
185
186
# Directive rules
187
class KnownDirectivesRule(ASTValidationRule):
188
"""Ensures directives are defined and in valid locations"""
189
190
class UniqueDirectivesPerLocationRule(ASTValidationRule):
191
"""Ensures non-repeatable directives appear once per location"""
192
193
# Subscription rules
194
class SingleFieldSubscriptionsRule(ASTValidationRule):
195
"""Ensures subscriptions select only one root field"""
196
197
# Miscellaneous rules
198
class KnownTypeNamesRule(ASTValidationRule):
199
"""Ensures type names exist in the schema"""
200
201
class UniqueInputFieldNamesRule(ASTValidationRule):
202
"""Ensures input object field names are unique"""
203
```
204
205
### SDL Validation Rules
206
207
Rules specific to validating schema definition language documents.
208
209
```python { .api }
210
class LoneSchemaDefinitionRule(SDLValidationRule):
211
"""Ensures only one schema definition exists"""
212
213
class UniqueOperationTypesRule(SDLValidationRule):
214
"""Ensures operation types are unique in schema"""
215
216
class UniqueTypeNamesRule(SDLValidationRule):
217
"""Ensures type names are unique in schema"""
218
219
class UniqueEnumValueNamesRule(SDLValidationRule):
220
"""Ensures enum value names are unique per enum"""
221
222
class UniqueFieldDefinitionNamesRule(SDLValidationRule):
223
"""Ensures field names are unique per type"""
224
225
class UniqueArgumentDefinitionNamesRule(SDLValidationRule):
226
"""Ensures argument names are unique per field"""
227
228
class UniqueDirectiveNamesRule(SDLValidationRule):
229
"""Ensures directive names are unique in schema"""
230
231
class PossibleTypeExtensionsRule(SDLValidationRule):
232
"""Ensures type extensions are valid"""
233
```
234
235
### Custom Validation Rules
236
237
Optional rules not defined by the GraphQL specification but useful for specific use cases.
238
239
```python { .api }
240
class NoDeprecatedCustomRule(ASTValidationRule):
241
"""Prevents usage of deprecated fields and enum values"""
242
243
class NoSchemaIntrospectionCustomRule(ASTValidationRule):
244
"""Prevents introspection queries for security"""
245
```
246
247
#### Custom Rule Example
248
249
```python
250
from graphql import ValidationRule, GraphQLError
251
252
class NoIntrospectionRule(ValidationRule):
253
def enter_field(self, node, key, parent, path, ancestors):
254
if node.name.value.startswith('__'):
255
self.context.report_error(
256
GraphQLError(
257
'Introspection is disabled',
258
nodes=[node]
259
)
260
)
261
262
# Use custom rule
263
from graphql import validate, specified_rules
264
265
custom_rules = list(specified_rules) + [NoIntrospectionRule]
266
errors = validate(schema, document_ast, rules=custom_rules)
267
```
268
269
### Validation with Type Information
270
271
Use TypeInfo to provide enhanced validation with type context.
272
273
```python { .api }
274
from graphql.utilities import TypeInfo
275
276
# Create type info for enhanced validation
277
type_info = TypeInfo(schema)
278
errors = validate(schema, document_ast, type_info=type_info)
279
```
280
281
#### Advanced Validation Example
282
283
```python
284
from graphql import (
285
validate, parse, build_schema, specified_rules,
286
NoDeprecatedCustomRule, ValidationContext
287
)
288
289
schema = build_schema('''
290
type Query {
291
user(id: ID!): User
292
deprecated_field: String @deprecated(reason: "Use user instead")
293
}
294
295
type User {
296
id: ID!
297
name: String
298
old_name: String @deprecated
299
}
300
''')
301
302
query = parse('''
303
{
304
user(id: "123") {
305
name
306
old_name
307
}
308
deprecated_field
309
}
310
''')
311
312
# Validate with custom rules
313
all_rules = list(specified_rules) + [NoDeprecatedCustomRule]
314
errors = validate(schema, query_ast, rules=all_rules)
315
316
for error in errors:
317
print(f"Error: {error.message}")
318
if error.locations:
319
for location in error.locations:
320
print(f" at line {location.line}, column {location.column}")
321
```
322
323
## Types
324
325
```python { .api }
326
# Import required types
327
from typing import List, Optional, Sequence, Callable, Type, Union
328
from graphql.type import GraphQLSchema
329
from graphql.language import DocumentNode, Node, FragmentDefinitionNode, OperationDefinitionNode, SelectionSetNode, FragmentSpreadNode
330
from graphql.error import GraphQLError
331
from graphql.utilities import TypeInfo
332
from graphql.language.visitor import VisitorAction
333
334
# Core validation types
335
ValidationRule = Type[ValidationRule]
336
ASTValidationRule = Type[ASTValidationRule]
337
SDLValidationRule = Type[SDLValidationRule]
338
339
# Validation context types
340
ValidationContext = class ValidationContext
341
ASTValidationContext = class ASTValidationContext
342
SDLValidationContext = class SDLValidationContext
343
344
# Rule collections
345
specified_rules: List[Type[ValidationRule]]
346
```