@@ -63,30 +63,33 @@ def initialize(schema, query_string = nil, document: nil, context: nil, variable
63
63
end
64
64
65
65
@arguments_cache = Hash . new { |h , k | h [ k ] = { } }
66
+ @validation_errors = [ ]
67
+ @analysis_errors = [ ]
68
+ @internal_representation = { }
69
+ valid?
66
70
end
67
71
68
72
# Get the result for this query, executing it once
69
73
def result
70
74
@result ||= begin
71
- if @validate && ( validation_errors . any? || analysis_errors . any? )
72
- { "errors" => validation_errors + analysis_errors }
75
+ if !valid?
76
+ all_errors = validation_errors + analysis_errors
77
+ if all_errors . any?
78
+ { "errors" => all_errors }
79
+ else
80
+ nil
81
+ end
73
82
else
74
83
Executor . new ( self ) . result
75
84
end
76
85
end
77
-
78
86
end
79
87
80
88
81
89
# This is the operation to run for this query.
82
90
# If more than one operation is present, it must be named at runtime.
83
91
# @return [GraphQL::Language::Nodes::OperationDefinition, nil]
84
- def selected_operation
85
- @selected_operation ||= begin
86
- perform_validation
87
- @selected_operation
88
- end
89
- end
92
+ attr_reader :selected_operation
90
93
91
94
# Determine the values for variables of this query, using default values
92
95
# if a value isn't provided at runtime.
@@ -101,19 +104,16 @@ def variables
101
104
)
102
105
end
103
106
104
- def internal_representation
105
- @internal_representation ||= begin
106
- perform_validation
107
- @internal_representation
108
- end
109
- end
107
+ # @return [Hash<String, nil => GraphQL::InternalRepresentation::Node] Operation name -> Irep node pairs
108
+ attr_reader :internal_representation
110
109
111
- def validation_errors
112
- @validation_errors ||= begin
113
- perform_validation
114
- @validation_errors
115
- end
116
- end
110
+ # TODO this should probably contain error instances, not hashes
111
+ # @return [Array<Hash>] Static validation errors for the query string
112
+ attr_reader :validation_errors
113
+
114
+ # TODO this should probably contain error instances, not hashes
115
+ # @return [Array<Hash>] Errors for this particular query run (eg, exceeds max complexity)
116
+ attr_reader :analysis_errors
117
117
118
118
# Node-level cache for calculating arguments. Used during execution and query analysis.
119
119
# @return [GraphQL::Query::Arguments] Arguments for this node, merging default values, literal values and query variables
@@ -127,24 +127,55 @@ def arguments_for(irep_node, definition)
127
127
end
128
128
end
129
129
130
+ # @return [GraphQL::Language::Nodes::Document, nil]
131
+ def selected_operation
132
+ @selected_operation ||= find_operation ( @operations , @operation_name )
133
+ end
134
+
135
+ def valid?
136
+ @valid ||= if @validate
137
+ document_valid? && query_possible? && query_valid?
138
+ else
139
+ true
140
+ end
141
+ end
142
+
130
143
private
131
144
132
- def perform_validation
133
- @selected_operation = find_operation ( @operations , @operation_name )
145
+
146
+ # Assert that the passed-in query string is internally consistent
147
+ def document_valid?
134
148
validation_result = schema . static_validator . validate ( self )
135
149
@validation_errors = validation_result [ :errors ]
136
150
@internal_representation = validation_result [ :irep ]
137
- if @validation_errors . none?
138
- # Accessing variables will raise errors if there are any :S
139
- variables
140
- end
141
- nil
151
+ @validation_errors . none?
152
+ end
153
+
154
+ # Given that the document is valid, do we have what we need to
155
+ # execute the document this time?
156
+ # - Is there an operation to run?
157
+ # - Are all variables accounted for?
158
+ def query_possible?
159
+ !selected_operation . nil? && variables
160
+ true
142
161
rescue GraphQL ::Query ::OperationNameMissingError , GraphQL ::Query ::VariableValidationError => err
143
- @validation_errors = [ err . to_h ]
144
- @internal_representation = nil
145
- nil
162
+ @validation_errors << err . to_h
163
+ false
146
164
end
147
165
166
+ # Given that we _could_ execute this query, _should_ we?
167
+ # - Does it violate any query analyzers?
168
+ def query_valid?
169
+ @analysis_errors = begin
170
+ if @query_analyzers . any?
171
+ reduce_results = GraphQL ::Analysis . analyze_query ( self , @query_analyzers )
172
+ reduce_results . select { |r | r . is_a? ( GraphQL ::AnalysisError ) } . map ( &:to_h )
173
+ else
174
+ [ ]
175
+ end
176
+ end
177
+ @analysis_errors . none?
178
+ end
148
179
149
180
def find_operation ( operations , operation_name )
150
181
if operations . length == 1
@@ -157,19 +188,5 @@ def find_operation(operations, operation_name)
157
188
operations [ operation_name ]
158
189
end
159
190
end
160
-
161
- def analysis_errors
162
- @analysis_errors ||= begin
163
- if validation_errors . any?
164
- # Can't reduce an invalid query
165
- [ ]
166
- elsif @query_analyzers . any?
167
- reduce_results = GraphQL ::Analysis . analyze_query ( self , @query_analyzers )
168
- reduce_results . select { |r | r . is_a? ( GraphQL ::AnalysisError ) } . map ( &:to_h )
169
- else
170
- [ ]
171
- end
172
- end
173
- end
174
191
end
175
192
end
0 commit comments