@@ -5,8 +5,8 @@ use lazy_static::lazy_static;
5
5
use stable_hash:: crypto:: SetHasher ;
6
6
use stable_hash:: prelude:: * ;
7
7
use stable_hash:: utils:: stable_hash;
8
- use std:: cmp;
9
8
use std:: collections:: { BTreeMap , HashMap , HashSet } ;
9
+ use std:: iter;
10
10
use std:: time:: Instant ;
11
11
12
12
use graph:: prelude:: * ;
@@ -159,7 +159,7 @@ where
159
159
let introspection_resolver = IntrospectionResolver :: new ( & self . logger , & self . query . schema ) ;
160
160
161
161
ExecutionContext {
162
- logger : self . logger . clone ( ) ,
162
+ logger : self . logger . cheap_clone ( ) ,
163
163
resolver : Arc :: new ( introspection_resolver) ,
164
164
query : self . query . as_introspection_query ( ) ,
165
165
deadline : self . deadline ,
@@ -210,7 +210,7 @@ pub fn execute_root_selection_set(
210
210
items : Vec :: new ( ) ,
211
211
} ;
212
212
213
- for ( _, fields) in collect_fields ( ctx, query_type, selection_set, None ) {
213
+ for ( _, fields) in collect_fields ( ctx, query_type, iter :: once ( selection_set) , None ) {
214
214
let name = fields[ 0 ] . name . clone ( ) ;
215
215
let selections = fields. into_iter ( ) . map ( |f| q:: Selection :: Field ( f. clone ( ) ) ) ;
216
216
// See if this is an introspection or data field. We don't worry about
@@ -228,7 +228,7 @@ pub fn execute_root_selection_set(
228
228
BTreeMap :: default ( )
229
229
} else {
230
230
let initial_data = ctx. resolver . prefetch ( & ctx, selection_set) ?;
231
- execute_selection_set_to_map ( & ctx, & data_set, query_type, initial_data) ?
231
+ execute_selection_set_to_map ( & ctx, iter :: once ( & data_set) , query_type, initial_data) ?
232
232
} ;
233
233
234
234
// Resolve introspection fields, if there are any
@@ -237,7 +237,7 @@ pub fn execute_root_selection_set(
237
237
238
238
values. extend ( execute_selection_set_to_map (
239
239
& ictx,
240
- & intro_set,
240
+ iter :: once ( & intro_set) ,
241
241
& * INTROSPECTION_QUERY_TYPE ,
242
242
None ,
243
243
) ?) ;
@@ -255,23 +255,23 @@ pub fn execute_root_selection_set(
255
255
/// Executes a selection set, requiring the result to be of the given object type.
256
256
///
257
257
/// Allows passing in a parent value during recursive processing of objects and their fields.
258
- pub fn execute_selection_set (
259
- ctx : & ExecutionContext < impl Resolver > ,
260
- selection_set : & q:: SelectionSet ,
258
+ pub fn execute_selection_set < ' a > (
259
+ ctx : & ' a ExecutionContext < impl Resolver > ,
260
+ selection_sets : impl Iterator < Item = & ' a q:: SelectionSet > ,
261
261
object_type : & s:: ObjectType ,
262
262
prefetched_value : Option < q:: Value > ,
263
263
) -> Result < q:: Value , Vec < QueryExecutionError > > {
264
264
Ok ( q:: Value :: Object ( execute_selection_set_to_map (
265
265
ctx,
266
- selection_set ,
266
+ selection_sets ,
267
267
object_type,
268
268
prefetched_value,
269
269
) ?) )
270
270
}
271
271
272
- fn execute_selection_set_to_map (
273
- ctx : & ExecutionContext < impl Resolver > ,
274
- selection_set : & q:: SelectionSet ,
272
+ fn execute_selection_set_to_map < ' a > (
273
+ ctx : & ' a ExecutionContext < impl Resolver > ,
274
+ selection_sets : impl Iterator < Item = & ' a q:: SelectionSet > ,
275
275
object_type : & s:: ObjectType ,
276
276
prefetched_value : Option < q:: Value > ,
277
277
) -> Result < BTreeMap < String , q:: Value > , Vec < QueryExecutionError > > {
@@ -284,7 +284,7 @@ fn execute_selection_set_to_map(
284
284
let mut result_map: BTreeMap < String , q:: Value > = BTreeMap :: new ( ) ;
285
285
286
286
// Group fields with the same response key, so we can execute them together
287
- let grouped_field_set = collect_fields ( ctx, object_type, selection_set , None ) ;
287
+ let grouped_field_set = collect_fields ( ctx, object_type, selection_sets , None ) ;
288
288
289
289
// Gather fields that appear more than once with the same response key.
290
290
let multiple_response_keys = {
@@ -356,101 +356,106 @@ fn execute_selection_set_to_map(
356
356
}
357
357
}
358
358
359
- /// Collects fields of a selection set .
359
+ /// Collects fields from selection sets .
360
360
pub fn collect_fields < ' a > (
361
361
ctx : & ' a ExecutionContext < impl Resolver > ,
362
362
object_type : & s:: ObjectType ,
363
- selection_set : & ' a q:: SelectionSet ,
363
+ selection_sets : impl Iterator < Item = & ' a q:: SelectionSet > ,
364
364
visited_fragments : Option < HashSet < & ' a q:: Name > > ,
365
365
) -> IndexMap < & ' a String , Vec < & ' a q:: Field > > {
366
366
let mut visited_fragments = visited_fragments. unwrap_or_default ( ) ;
367
367
let mut grouped_fields: IndexMap < _ , Vec < _ > > = IndexMap :: new ( ) ;
368
368
369
- // Only consider selections that are not skipped and should be included
370
- let selections: Vec < _ > = selection_set
371
- . items
372
- . iter ( )
373
- . filter ( |selection| !qast:: skip_selection ( selection, & ctx. query . variables ) )
374
- . filter ( |selection| qast:: include_selection ( selection, & ctx. query . variables ) )
375
- . collect ( ) ;
376
-
377
- for selection in selections {
378
- match selection {
379
- q:: Selection :: Field ( ref field) => {
380
- // Obtain the response key for the field
381
- let response_key = qast:: get_response_key ( field) ;
382
-
383
- // Create a field group for this response key on demand and
384
- // append the selection field to this group.
385
- grouped_fields. entry ( response_key) . or_default ( ) . push ( field) ;
386
- }
387
-
388
- q:: Selection :: FragmentSpread ( spread) => {
389
- // Only consider the fragment if it hasn't already been included,
390
- // as would be the case if the same fragment spread ...Foo appeared
391
- // twice in the same selection set
392
- if !visited_fragments. contains ( & spread. fragment_name ) {
393
- visited_fragments. insert ( & spread. fragment_name ) ;
394
-
395
- // Resolve the fragment using its name and, if it applies, collect
396
- // fields for the fragment and group them
397
- ctx. query
398
- . get_fragment ( & spread. fragment_name )
399
- . and_then ( |fragment| {
400
- // We have a fragment, only pass it on if it applies to the
401
- // current object type
402
- if does_fragment_type_apply ( ctx, object_type, & fragment. type_condition )
403
- {
404
- Some ( fragment)
405
- } else {
406
- None
407
- }
408
- } )
409
- . map ( |fragment| {
410
- // We have a fragment that applies to the current object type,
411
- // collect its fields into response key groups
412
- let fragment_grouped_field_set = collect_fields (
413
- ctx,
414
- object_type,
415
- & fragment. selection_set ,
416
- Some ( visited_fragments. clone ( ) ) ,
417
- ) ;
418
-
419
- // Add all items from each fragments group to the field group
420
- // with the corresponding response key
421
- for ( response_key, mut fragment_group) in fragment_grouped_field_set {
422
- grouped_fields
423
- . entry ( response_key)
424
- . or_default ( )
425
- . append ( & mut fragment_group) ;
426
- }
427
- } ) ;
369
+ for selection_set in selection_sets {
370
+ // Only consider selections that are not skipped and should be included
371
+ let selections = selection_set
372
+ . items
373
+ . iter ( )
374
+ . filter ( |selection| !qast:: skip_selection ( selection, & ctx. query . variables ) )
375
+ . filter ( |selection| qast:: include_selection ( selection, & ctx. query . variables ) ) ;
376
+
377
+ for selection in selections {
378
+ match selection {
379
+ q:: Selection :: Field ( ref field) => {
380
+ // Obtain the response key for the field
381
+ let response_key = qast:: get_response_key ( field) ;
382
+
383
+ // Create a field group for this response key on demand and
384
+ // append the selection field to this group.
385
+ grouped_fields. entry ( response_key) . or_default ( ) . push ( field) ;
428
386
}
429
- }
430
-
431
- q:: Selection :: InlineFragment ( fragment) => {
432
- let applies = match & fragment. type_condition {
433
- Some ( cond) => does_fragment_type_apply ( ctx, object_type, & cond) ,
434
- None => true ,
435
- } ;
436
387
437
- if applies {
438
- let fragment_grouped_field_set = collect_fields (
439
- ctx,
440
- object_type,
441
- & fragment. selection_set ,
442
- Some ( visited_fragments. clone ( ) ) ,
443
- ) ;
388
+ q:: Selection :: FragmentSpread ( spread) => {
389
+ // Only consider the fragment if it hasn't already been included,
390
+ // as would be the case if the same fragment spread ...Foo appeared
391
+ // twice in the same selection set
392
+ if !visited_fragments. contains ( & spread. fragment_name ) {
393
+ visited_fragments. insert ( & spread. fragment_name ) ;
394
+
395
+ // Resolve the fragment using its name and, if it applies, collect
396
+ // fields for the fragment and group them
397
+ ctx. query
398
+ . get_fragment ( & spread. fragment_name )
399
+ . and_then ( |fragment| {
400
+ // We have a fragment, only pass it on if it applies to the
401
+ // current object type
402
+ if does_fragment_type_apply (
403
+ ctx,
404
+ object_type,
405
+ & fragment. type_condition ,
406
+ ) {
407
+ Some ( fragment)
408
+ } else {
409
+ None
410
+ }
411
+ } )
412
+ . map ( |fragment| {
413
+ // We have a fragment that applies to the current object type,
414
+ // collect its fields into response key groups
415
+ let fragment_grouped_field_set = collect_fields (
416
+ ctx,
417
+ object_type,
418
+ iter:: once ( & fragment. selection_set ) ,
419
+ Some ( visited_fragments. clone ( ) ) ,
420
+ ) ;
421
+
422
+ // Add all items from each fragments group to the field group
423
+ // with the corresponding response key
424
+ for ( response_key, mut fragment_group) in fragment_grouped_field_set
425
+ {
426
+ grouped_fields
427
+ . entry ( response_key)
428
+ . or_default ( )
429
+ . append ( & mut fragment_group) ;
430
+ }
431
+ } ) ;
432
+ }
433
+ }
444
434
445
- for ( response_key, mut fragment_group) in fragment_grouped_field_set {
446
- grouped_fields
447
- . entry ( response_key)
448
- . or_default ( )
449
- . append ( & mut fragment_group) ;
435
+ q:: Selection :: InlineFragment ( fragment) => {
436
+ let applies = match & fragment. type_condition {
437
+ Some ( cond) => does_fragment_type_apply ( ctx, object_type, & cond) ,
438
+ None => true ,
439
+ } ;
440
+
441
+ if applies {
442
+ let fragment_grouped_field_set = collect_fields (
443
+ ctx,
444
+ object_type,
445
+ iter:: once ( & fragment. selection_set ) ,
446
+ Some ( visited_fragments. clone ( ) ) ,
447
+ ) ;
448
+
449
+ for ( response_key, mut fragment_group) in fragment_grouped_field_set {
450
+ grouped_fields
451
+ . entry ( response_key)
452
+ . or_default ( )
453
+ . append ( & mut fragment_group) ;
454
+ }
450
455
}
451
456
}
452
- }
453
- } ;
457
+ } ;
458
+ }
454
459
}
455
460
456
461
grouped_fields
@@ -776,7 +781,7 @@ fn complete_value(
776
781
// Complete object types recursively
777
782
s:: TypeDefinition :: Object ( object_type) => execute_selection_set (
778
783
ctx,
779
- & merge_selection_sets ( fields) ,
784
+ fields. iter ( ) . map ( |f| & f . selection_set ) ,
780
785
object_type,
781
786
Some ( resolved_value) ,
782
787
) ,
@@ -787,7 +792,7 @@ fn complete_value(
787
792
788
793
execute_selection_set (
789
794
ctx,
790
- & merge_selection_sets ( fields) ,
795
+ fields. iter ( ) . map ( |f| & f . selection_set ) ,
791
796
object_type,
792
797
Some ( resolved_value) ,
793
798
)
@@ -799,7 +804,7 @@ fn complete_value(
799
804
800
805
execute_selection_set (
801
806
ctx,
802
- & merge_selection_sets ( fields) ,
807
+ fields. iter ( ) . map ( |f| & f . selection_set ) ,
803
808
object_type,
804
809
Some ( resolved_value) ,
805
810
)
@@ -830,34 +835,6 @@ fn resolve_abstract_type<'a>(
830
835
} )
831
836
}
832
837
833
- /// Merges the selection sets of several fields into a single selection set.
834
- pub fn merge_selection_sets ( fields : & Vec < & q:: Field > ) -> q:: SelectionSet {
835
- let ( span, items) = fields
836
- . iter ( )
837
- . fold ( ( None , vec ! [ ] ) , |( span, mut items) , field| {
838
- (
839
- // The overal span is the min/max spans of all merged selection sets
840
- match span {
841
- None => Some ( field. selection_set . span ) ,
842
- Some ( ( start, end) ) => Some ( (
843
- cmp:: min ( start, field. selection_set . span . 0 ) ,
844
- cmp:: max ( end, field. selection_set . span . 1 ) ,
845
- ) ) ,
846
- } ,
847
- // The overall selection is the result of merging the selections of all fields
848
- {
849
- items. extend_from_slice ( field. selection_set . items . as_slice ( ) ) ;
850
- items
851
- } ,
852
- )
853
- } ) ;
854
-
855
- q:: SelectionSet {
856
- span : span. unwrap ( ) ,
857
- items,
858
- }
859
- }
860
-
861
838
/// Coerces argument values into GraphQL values.
862
839
pub fn coerce_argument_values < ' a > (
863
840
ctx : & ExecutionContext < impl Resolver > ,
0 commit comments