@@ -286,6 +286,18 @@ fn execute_selection_set_to_map(
286
286
// Group fields with the same response key, so we can execute them together
287
287
let grouped_field_set = collect_fields ( ctx, object_type, selection_set, None ) ;
288
288
289
+ // Gather fields that appear more than once with the same response key.
290
+ let multiple_response_keys = {
291
+ let mut multiple_response_keys = HashSet :: new ( ) ;
292
+ let mut fields = HashSet :: new ( ) ;
293
+ for field in grouped_field_set. iter ( ) . map ( |( _, f) | f. iter ( ) ) . flatten ( ) {
294
+ if !fields. insert ( field. name . as_str ( ) ) {
295
+ multiple_response_keys. insert ( field. name . as_str ( ) ) ;
296
+ }
297
+ }
298
+ multiple_response_keys
299
+ } ;
300
+
289
301
// Process all field groups in order
290
302
for ( response_key, fields) in grouped_field_set {
291
303
match ctx. deadline {
@@ -298,15 +310,21 @@ fn execute_selection_set_to_map(
298
310
299
311
// If the field exists on the object, execute it and add its result to the result map
300
312
if let Some ( ref field) = sast:: get_field ( object_type, & fields[ 0 ] . name ) {
301
- // If we have the value already, because it's a scalar or a prefetched object, we want
302
- // to use it and avoid cloning, so we take it from the object value.
313
+ // Check if we have the value already.
303
314
let field_value = prefetched_object
304
315
. as_mut ( )
305
316
. map ( |o| {
306
- // Prefetched objects associated to `prefetch:response_key`,
307
- // while scalars are associated to the field name.
308
- o. remove ( & format ! ( "prefetch:{}" , response_key) )
309
- . or ( o. remove ( & fields[ 0 ] . name ) )
317
+ // Prefetched objects are associated to `prefetch:response_key`.
318
+ if let Some ( val) = o. remove ( & format ! ( "prefetch:{}" , response_key) ) {
319
+ return Some ( val) ;
320
+ }
321
+
322
+ // Scalars and scalar lists are associated to the field name.
323
+ // If the field has more than one response key, we have to clone.
324
+ match multiple_response_keys. contains ( fields[ 0 ] . name . as_str ( ) ) {
325
+ false => o. remove ( & fields[ 0 ] . name ) ,
326
+ true => o. get ( & fields[ 0 ] . name ) . cloned ( ) ,
327
+ }
310
328
} )
311
329
. flatten ( ) ;
312
330
match execute_field ( & ctx, object_type, field_value, & fields[ 0 ] , field, fields) {
0 commit comments