@@ -5,15 +5,13 @@ use graph::{
5
5
prelude:: { s, CheapClone } ,
6
6
util:: timed_rw_lock:: TimedMutex ,
7
7
} ;
8
- use indexmap:: IndexMap ;
9
8
use lazy_static:: lazy_static;
10
9
use stable_hash:: crypto:: SetHasher ;
11
10
use stable_hash:: prelude:: * ;
12
11
use stable_hash:: utils:: stable_hash;
13
- use std:: borrow:: ToOwned ;
14
- use std:: collections:: { HashMap , HashSet } ;
15
- use std:: iter;
12
+ use std:: collections:: HashMap ;
16
13
use std:: time:: Instant ;
14
+ use std:: { borrow:: ToOwned , collections:: HashSet } ;
17
15
18
16
use graph:: data:: graphql:: * ;
19
17
use graph:: data:: query:: CacheStatus ;
@@ -136,7 +134,6 @@ impl Default for WeightedResult {
136
134
137
135
struct HashableQuery < ' a > {
138
136
query_schema_id : & ' a DeploymentHash ,
139
- query_fragments : & ' a HashMap < String , a:: FragmentDefinition > ,
140
137
selection_set : & ' a a:: SelectionSet ,
141
138
block_ptr : & ' a BlockPtr ,
142
139
}
@@ -162,13 +159,6 @@ impl StableHash for HashableQuery<'_> {
162
159
self . query_schema_id
163
160
. stable_hash ( sequence_number. next_child ( ) , state) ;
164
161
165
- // Not stable! Uses to_string()
166
- self . query_fragments
167
- . iter ( )
168
- . map ( |( k, v) | ( k, format ! ( "{:?}" , v) ) )
169
- . collect :: < HashMap < _ , _ > > ( )
170
- . stable_hash ( sequence_number. next_child ( ) , state) ;
171
-
172
162
// Not stable! Uses to_string
173
163
format ! ( "{:?}" , self . selection_set) . stable_hash ( sequence_number. next_child ( ) , state) ;
174
164
@@ -187,7 +177,6 @@ fn cache_key(
187
177
// Otherwise, incorrect results may be returned.
188
178
let query = HashableQuery {
189
179
query_schema_id : ctx. query . schema . id ( ) ,
190
- query_fragments : & ctx. query . fragments ,
191
180
selection_set,
192
181
block_ptr,
193
182
} ;
@@ -275,7 +264,7 @@ where
275
264
}
276
265
}
277
266
278
- pub fn execute_root_selection_set_uncached (
267
+ pub ( crate ) fn execute_root_selection_set_uncached (
279
268
ctx : & ExecutionContext < impl Resolver > ,
280
269
selection_set : & a:: SelectionSet ,
281
270
root_type : & s:: ObjectType ,
@@ -286,18 +275,16 @@ pub fn execute_root_selection_set_uncached(
286
275
let mut intro_set = a:: SelectionSet :: empty_from ( selection_set) ;
287
276
let mut meta_items = Vec :: new ( ) ;
288
277
289
- for ( _, fields) in collect_fields ( ctx, root_type, iter:: once ( selection_set) ) {
290
- let name = fields[ 0 ] . name . clone ( ) ;
291
- let selections = fields. into_iter ( ) . map ( |f| a:: Selection :: Field ( f. clone ( ) ) ) ;
278
+ for field in selection_set. fields_for ( root_type) {
292
279
// See if this is an introspection or data field. We don't worry about
293
280
// non-existent fields; those will cause an error later when we execute
294
281
// the data_set SelectionSet
295
- if is_introspection_field ( & name) {
296
- intro_set. extend ( selections )
297
- } else if & name == META_FIELD_NAME {
298
- meta_items. extend ( selections )
282
+ if is_introspection_field ( & field . name ) {
283
+ intro_set. push ( field )
284
+ } else if & field . name == META_FIELD_NAME {
285
+ meta_items. push ( field )
299
286
} else {
300
- data_set. extend ( selections )
287
+ data_set. push ( field )
301
288
}
302
289
}
303
290
@@ -306,8 +293,8 @@ pub fn execute_root_selection_set_uncached(
306
293
Object :: default ( )
307
294
} else {
308
295
let initial_data = ctx. resolver . prefetch ( & ctx, & data_set) ?;
309
- data_set. extend ( meta_items) ;
310
- execute_selection_set_to_map ( & ctx, iter :: once ( & data_set) , root_type, initial_data) ?
296
+ data_set. push_fields ( meta_items) ;
297
+ execute_selection_set_to_map ( & ctx, & data_set, root_type, initial_data) ?
311
298
} ;
312
299
313
300
// Resolve introspection fields, if there are any
@@ -316,7 +303,7 @@ pub fn execute_root_selection_set_uncached(
316
303
317
304
values. extend ( execute_selection_set_to_map (
318
305
& ictx,
319
- iter :: once ( & intro_set ) ,
306
+ ctx . query . selection_set . as_ref ( ) ,
320
307
& * INTROSPECTION_QUERY_TYPE ,
321
308
None ,
322
309
) ?) ;
@@ -326,7 +313,7 @@ pub fn execute_root_selection_set_uncached(
326
313
}
327
314
328
315
/// Executes the root selection set of a query.
329
- pub async fn execute_root_selection_set < R : Resolver > (
316
+ pub ( crate ) async fn execute_root_selection_set < R : Resolver > (
330
317
ctx : Arc < ExecutionContext < R > > ,
331
318
selection_set : Arc < a:: SelectionSet > ,
332
319
root_type : Arc < s:: ObjectType > ,
@@ -472,21 +459,21 @@ pub async fn execute_root_selection_set<R: Resolver>(
472
459
/// Allows passing in a parent value during recursive processing of objects and their fields.
473
460
fn execute_selection_set < ' a > (
474
461
ctx : & ' a ExecutionContext < impl Resolver > ,
475
- selection_sets : impl Iterator < Item = & ' a a:: SelectionSet > ,
462
+ selection_set : & ' a a:: SelectionSet ,
476
463
object_type : & s:: ObjectType ,
477
464
prefetched_value : Option < r:: Value > ,
478
465
) -> Result < r:: Value , Vec < QueryExecutionError > > {
479
466
Ok ( r:: Value :: Object ( execute_selection_set_to_map (
480
467
ctx,
481
- selection_sets ,
468
+ selection_set ,
482
469
object_type,
483
470
prefetched_value,
484
471
) ?) )
485
472
}
486
473
487
474
fn execute_selection_set_to_map < ' a > (
488
475
ctx : & ' a ExecutionContext < impl Resolver > ,
489
- selection_sets : impl Iterator < Item = & ' a a:: SelectionSet > ,
476
+ selection_set : & ' a a:: SelectionSet ,
490
477
object_type : & s:: ObjectType ,
491
478
prefetched_value : Option < r:: Value > ,
492
479
) -> Result < Object , Vec < QueryExecutionError > > {
@@ -498,14 +485,11 @@ fn execute_selection_set_to_map<'a>(
498
485
let mut errors: Vec < QueryExecutionError > = Vec :: new ( ) ;
499
486
let mut result_map = Object :: new ( ) ;
500
487
501
- // Group fields with the same response key, so we can execute them together
502
- let grouped_field_set = collect_fields ( ctx, object_type, selection_sets) ;
503
-
504
488
// Gather fields that appear more than once with the same response key.
505
489
let multiple_response_keys = {
506
490
let mut multiple_response_keys = HashSet :: new ( ) ;
507
491
let mut fields = HashSet :: new ( ) ;
508
- for field in grouped_field_set . iter ( ) . map ( | ( _ , f ) | f . iter ( ) ) . flatten ( ) {
492
+ for field in selection_set . fields_for ( object_type ) {
509
493
if !fields. insert ( field. name . as_str ( ) ) {
510
494
multiple_response_keys. insert ( field. name . as_str ( ) ) ;
511
495
}
@@ -514,7 +498,7 @@ fn execute_selection_set_to_map<'a>(
514
498
} ;
515
499
516
500
// Process all field groups in order
517
- for ( response_key , fields ) in grouped_field_set {
501
+ for field in selection_set . fields_for ( object_type ) {
518
502
match ctx. deadline {
519
503
Some ( deadline) if deadline < Instant :: now ( ) => {
520
504
errors. push ( QueryExecutionError :: Timeout ) ;
@@ -523,8 +507,10 @@ fn execute_selection_set_to_map<'a>(
523
507
_ => ( ) ,
524
508
}
525
509
510
+ let response_key = field. response_key ( ) ;
511
+
526
512
// Unwrap: The query was validated to contain only valid fields.
527
- let field = sast:: get_field ( object_type, & fields [ 0 ] . name ) . unwrap ( ) ;
513
+ let field_type = sast:: get_field ( object_type, & field . name ) . unwrap ( ) ;
528
514
529
515
// Check if we have the value already.
530
516
let field_value = prefetched_object
@@ -537,13 +523,13 @@ fn execute_selection_set_to_map<'a>(
537
523
538
524
// Scalars and scalar lists are associated to the field name.
539
525
// If the field has more than one response key, we have to clone.
540
- match multiple_response_keys. contains ( fields [ 0 ] . name . as_str ( ) ) {
541
- false => o. remove ( & fields [ 0 ] . name ) ,
542
- true => o. get ( & fields [ 0 ] . name ) . cloned ( ) ,
526
+ match multiple_response_keys. contains ( field . name . as_str ( ) ) {
527
+ false => o. remove ( & field . name ) ,
528
+ true => o. get ( & field . name ) . cloned ( ) ,
543
529
}
544
530
} )
545
531
. flatten ( ) ;
546
- match execute_field ( & ctx, object_type, field_value, & fields [ 0 ] , field, fields ) {
532
+ match execute_field ( & ctx, object_type, field_value, field, field_type ) {
547
533
Ok ( v) => {
548
534
result_map. insert ( response_key. to_owned ( ) , v) ;
549
535
}
@@ -560,124 +546,13 @@ fn execute_selection_set_to_map<'a>(
560
546
}
561
547
}
562
548
563
- /// Collects fields from selection sets. Returns a map from response key to fields. There will
564
- /// typically be a single field for a response key. If there are multiple, the overall execution
565
- /// logic will effectively merged them into the output for the response key.
566
- pub fn collect_fields < ' a > (
567
- ctx : & ' a ExecutionContext < impl Resolver > ,
568
- object_type : & s:: ObjectType ,
569
- selection_sets : impl Iterator < Item = & ' a a:: SelectionSet > ,
570
- ) -> IndexMap < & ' a str , Vec < & ' a a:: Field > > {
571
- let mut grouped_fields = IndexMap :: new ( ) ;
572
- collect_fields_inner (
573
- ctx,
574
- object_type,
575
- selection_sets,
576
- & mut HashSet :: new ( ) ,
577
- & mut grouped_fields,
578
- ) ;
579
- grouped_fields
580
- }
581
-
582
- pub fn collect_fields_inner < ' a > (
583
- ctx : & ' a ExecutionContext < impl Resolver > ,
584
- object_type : & s:: ObjectType ,
585
- selection_sets : impl Iterator < Item = & ' a a:: SelectionSet > ,
586
- visited_fragments : & mut HashSet < & ' a str > ,
587
- output : & mut IndexMap < & ' a str , Vec < & ' a a:: Field > > ,
588
- ) {
589
- for selection_set in selection_sets {
590
- // Only consider selections that are not skipped and should be included
591
- for selection in selection_set. included ( ) {
592
- match selection {
593
- a:: Selection :: Field ( ref field) => {
594
- let response_key = field. response_key ( ) ;
595
- output. entry ( response_key) . or_default ( ) . push ( field) ;
596
- }
597
-
598
- a:: Selection :: FragmentSpread ( spread) => {
599
- // Only consider the fragment if it hasn't already been included,
600
- // as would be the case if the same fragment spread ...Foo appeared
601
- // twice in the same selection set.
602
- //
603
- // Note: This will skip both duplicate fragments and will break cycles,
604
- // so we support fragments even though the GraphQL spec prohibits them.
605
- if visited_fragments. insert ( & spread. fragment_name ) {
606
- let fragment = ctx. query . get_fragment ( & spread. fragment_name ) ;
607
- if does_fragment_type_apply ( ctx, object_type, & fragment. type_condition ) {
608
- // We have a fragment that applies to the current object type,
609
- // collect fields recursively
610
- collect_fields_inner (
611
- ctx,
612
- object_type,
613
- iter:: once ( & fragment. selection_set ) ,
614
- visited_fragments,
615
- output,
616
- ) ;
617
- }
618
- }
619
- }
620
-
621
- a:: Selection :: InlineFragment ( fragment) => {
622
- let applies = match & fragment. type_condition {
623
- Some ( cond) => does_fragment_type_apply ( ctx, object_type, & cond) ,
624
- None => true ,
625
- } ;
626
-
627
- if applies {
628
- collect_fields_inner (
629
- ctx,
630
- object_type,
631
- iter:: once ( & fragment. selection_set ) ,
632
- visited_fragments,
633
- output,
634
- )
635
- }
636
- }
637
- } ;
638
- }
639
- }
640
- }
641
-
642
- /// Determines whether a fragment is applicable to the given object type.
643
- fn does_fragment_type_apply (
644
- ctx : & ExecutionContext < impl Resolver > ,
645
- object_type : & s:: ObjectType ,
646
- fragment_type : & a:: TypeCondition ,
647
- ) -> bool {
648
- // This is safe to do, as TypeCondition only has a single `On` variant.
649
- let a:: TypeCondition :: On ( ref name) = fragment_type;
650
-
651
- // Resolve the type the fragment applies to based on its name
652
- let named_type = ctx. query . schema . document ( ) . get_named_type ( name) ;
653
-
654
- match named_type {
655
- // The fragment applies to the object type if its type is the same object type
656
- Some ( s:: TypeDefinition :: Object ( ot) ) => object_type == ot,
657
-
658
- // The fragment also applies to the object type if its type is an interface
659
- // that the object type implements
660
- Some ( s:: TypeDefinition :: Interface ( it) ) => {
661
- object_type. implements_interfaces . contains ( & it. name )
662
- }
663
-
664
- // The fragment also applies to an object type if its type is a union that
665
- // the object type is one of the possible types for
666
- Some ( s:: TypeDefinition :: Union ( ut) ) => ut. types . contains ( & object_type. name ) ,
667
-
668
- // In all other cases, the fragment does not apply
669
- _ => false ,
670
- }
671
- }
672
-
673
549
/// Executes a field.
674
550
fn execute_field (
675
551
ctx : & ExecutionContext < impl Resolver > ,
676
552
object_type : & s:: ObjectType ,
677
553
field_value : Option < r:: Value > ,
678
554
field : & a:: Field ,
679
555
field_definition : & s:: Field ,
680
- fields : Vec < & a:: Field > ,
681
556
) -> Result < r:: Value , Vec < QueryExecutionError > > {
682
557
coerce_argument_values ( & ctx. query , object_type, field)
683
558
. and_then ( |argument_values| {
@@ -691,7 +566,7 @@ fn execute_field(
691
566
& argument_values,
692
567
)
693
568
} )
694
- . and_then ( |value| complete_value ( ctx, field, & field_definition. field_type , & fields , value) )
569
+ . and_then ( |value| complete_value ( ctx, field, & field_definition. field_type , value) )
695
570
}
696
571
697
572
/// Resolves the value of a field.
@@ -878,13 +753,12 @@ fn complete_value(
878
753
ctx : & ExecutionContext < impl Resolver > ,
879
754
field : & a:: Field ,
880
755
field_type : & s:: Type ,
881
- fields : & Vec < & a:: Field > ,
882
756
resolved_value : r:: Value ,
883
757
) -> Result < r:: Value , Vec < QueryExecutionError > > {
884
758
match field_type {
885
759
// Fail if the field type is non-null but the value is null
886
760
s:: Type :: NonNullType ( inner_type) => {
887
- return match complete_value ( ctx, field, inner_type, fields , resolved_value) ? {
761
+ return match complete_value ( ctx, field, inner_type, resolved_value) ? {
888
762
r:: Value :: Null => Err ( vec ! [ QueryExecutionError :: NonNullError (
889
763
field. position,
890
764
field. name. to_string( ) ,
@@ -908,7 +782,7 @@ fn complete_value(
908
782
for value_place in & mut values {
909
783
// Put in a placeholder, complete the value, put the completed value back.
910
784
let value = std:: mem:: replace ( value_place, r:: Value :: Null ) ;
911
- match complete_value ( ctx, field, inner_type, fields , value) {
785
+ match complete_value ( ctx, field, inner_type, value) {
912
786
Ok ( value) => {
913
787
* value_place = value;
914
788
}
@@ -965,7 +839,7 @@ fn complete_value(
965
839
// Complete object types recursively
966
840
s:: TypeDefinition :: Object ( object_type) => execute_selection_set (
967
841
ctx,
968
- fields . iter ( ) . map ( |f| & f . selection_set ) ,
842
+ & field . selection_set ,
969
843
object_type,
970
844
Some ( resolved_value) ,
971
845
) ,
@@ -976,7 +850,7 @@ fn complete_value(
976
850
977
851
execute_selection_set (
978
852
ctx,
979
- fields . iter ( ) . map ( |f| & f . selection_set ) ,
853
+ & field . selection_set ,
980
854
object_type,
981
855
Some ( resolved_value) ,
982
856
)
@@ -988,7 +862,7 @@ fn complete_value(
988
862
989
863
execute_selection_set (
990
864
ctx,
991
- fields . iter ( ) . map ( |f| & f . selection_set ) ,
865
+ & field . selection_set ,
992
866
object_type,
993
867
Some ( resolved_value) ,
994
868
)
0 commit comments