@@ -99,12 +99,12 @@ pub trait VertexInfo {
9999
100100 // non-optional, non-recursed, non-folded edge
101101 // TODO: What happens if the same edge exists more than once in a given scope?
102- fn required_edge ( & self , edge_name : & str ) -> Option < EdgeInfo > ;
102+ fn first_required_edge ( & self , edge_name : & str ) -> Option < EdgeInfo > ;
103103
104104 // optional, recursed, or folded edge;
105105 // recursed because recursion always starts at depth 0
106106 // TODO: What happens if the same edge exists more than once in a given scope?
107- fn optional_edge ( & self , edge_name : & str ) -> Option < EdgeInfo > ;
107+ fn first_edge ( & self , edge_name : & str ) -> Option < EdgeInfo > ;
108108}
109109
110110#[ non_exhaustive]
@@ -238,7 +238,8 @@ impl VertexInfo for LocalQueryInfo {
238238 return Some ( DynamicallyResolvedValue {
239239 query : self . query . clone ( ) ,
240240 vid : vertex. vid ,
241- resolve_on_component : self . query . query . indexed_query . vids [ & vertex. vid ] . clone ( ) ,
241+ resolve_on_component : self . query . query . indexed_query . vids [ & vertex. vid ]
242+ . clone ( ) ,
242243 context_field : context_field. clone ( ) ,
243244 is_multiple : false ,
244245 } ) ;
@@ -247,7 +248,8 @@ impl VertexInfo for LocalQueryInfo {
247248 return Some ( DynamicallyResolvedValue {
248249 query : self . query . clone ( ) ,
249250 vid : vertex. vid ,
250- resolve_on_component : self . query . query . indexed_query . vids [ & vertex. vid ] . clone ( ) ,
251+ resolve_on_component : self . query . query . indexed_query . vids [ & vertex. vid ]
252+ . clone ( ) ,
251253 context_field : context_field. clone ( ) ,
252254 is_multiple : true ,
253255 } ) ;
@@ -264,7 +266,7 @@ impl VertexInfo for LocalQueryInfo {
264266 // }
265267
266268 // non-optional, non-recursed, non-folded edge
267- fn required_edge ( & self , edge_name : & str ) -> Option < EdgeInfo > {
269+ fn first_required_edge ( & self , edge_name : & str ) -> Option < EdgeInfo > {
268270 // TODO: What happens if the same edge exists more than once in a given scope?
269271 let component = self . current_component ( ) ;
270272 let current_vertex = self . current_vertex ( ) ;
@@ -277,7 +279,7 @@ impl VertexInfo for LocalQueryInfo {
277279 first_matching_edge. map ( |edge| self . make_non_folded_edge_info ( edge. as_ref ( ) ) )
278280 }
279281
280- fn optional_edge ( & self , edge_name : & str ) -> Option < EdgeInfo > {
282+ fn first_edge ( & self , edge_name : & str ) -> Option < EdgeInfo > {
281283 // TODO: What happens if the same edge exists more than once in a given scope?
282284 let component = self . current_component ( ) ;
283285 let current_vertex = self . current_vertex ( ) ;
@@ -410,7 +412,9 @@ impl VertexInfo for NeighboringQueryInfo {
410412 query : self . query . clone ( ) ,
411413 vid : vertex. vid ,
412414 context_field : context_field. clone ( ) ,
413- resolve_on_component : self . query . query . indexed_query . vids [ & self . starting_vertex ] . clone ( ) ,
415+ resolve_on_component : self . query . query . indexed_query . vids
416+ [ & self . starting_vertex ]
417+ . clone ( ) ,
414418 is_multiple : false ,
415419 } ) ;
416420 }
@@ -421,7 +425,9 @@ impl VertexInfo for NeighboringQueryInfo {
421425 query : self . query . clone ( ) ,
422426 vid : vertex. vid ,
423427 context_field : context_field. clone ( ) ,
424- resolve_on_component : self . query . query . indexed_query . vids [ & self . starting_vertex ] . clone ( ) ,
428+ resolve_on_component : self . query . query . indexed_query . vids
429+ [ & self . starting_vertex ]
430+ . clone ( ) ,
425431 is_multiple : true ,
426432 } ) ;
427433 }
@@ -437,7 +443,7 @@ impl VertexInfo for NeighboringQueryInfo {
437443 // todo!()
438444 // }
439445
440- fn required_edge ( & self , edge_name : & str ) -> Option < EdgeInfo > {
446+ fn first_required_edge ( & self , edge_name : & str ) -> Option < EdgeInfo > {
441447 // TODO: What happens if the same edge exists more than once in a given scope?
442448 let component = self . current_component ( ) ;
443449 let current_vertex = self . current_vertex ( ) ;
@@ -450,7 +456,7 @@ impl VertexInfo for NeighboringQueryInfo {
450456 first_matching_edge. map ( |edge| self . make_non_folded_edge_info ( edge. as_ref ( ) ) )
451457 }
452458
453- fn optional_edge ( & self , edge_name : & str ) -> Option < EdgeInfo > {
459+ fn first_edge ( & self , edge_name : & str ) -> Option < EdgeInfo > {
454460 // TODO: What happens if the same edge exists more than once in a given scope?
455461 let component = self . current_component ( ) ;
456462 let current_vertex = self . current_vertex ( ) ;
@@ -498,11 +504,30 @@ impl DynamicallyResolvedValue {
498504 & self . context_field ,
499505 contexts,
500506 ) ;
507+ let context_field_vid = self . context_field . vertex_id ;
508+ let nullable_context_field = self . context_field . field_type . nullable ;
501509 if self . is_multiple {
502510 Box :: new ( iterator. map ( move |( ctx, value) | {
503511 match value {
504512 FieldValue :: List ( v) => ( ctx, CandidateValue :: Multiple ( v) ) ,
505- FieldValue :: Null => ( ctx, CandidateValue :: Impossible ) , // nullable field tagged
513+ FieldValue :: Null => {
514+ // Either a nullable field was tagged, or
515+ // the @tag is inside an @optional scope that doesn't exist.
516+ let candidate = if ctx. tokens [ & context_field_vid] . is_none ( ) {
517+ // @optional scope that didn't exist. Our query rules say that
518+ // any filters using this tag *must* pass.
519+ CandidateValue :: All
520+ } else {
521+ // The field must have been nullable.
522+ debug_assert ! (
523+ nullable_context_field,
524+ "tagged field {:?} was not nullable but received a null value for it" ,
525+ self . context_field,
526+ ) ;
527+ CandidateValue :: Impossible
528+ } ;
529+ ( ctx, candidate)
530+ }
506531 bad_value => {
507532 panic ! (
508533 "\
@@ -513,7 +538,27 @@ tagged field named {} of type {:?} produced an invalid value: {bad_value:?}",
513538 }
514539 } ) )
515540 } else {
516- Box :: new ( iterator. map ( |( ctx, value) | ( ctx, CandidateValue :: Single ( value) ) ) )
541+ Box :: new ( iterator. map ( move |( ctx, value) | match value {
542+ null_value @ FieldValue :: Null => {
543+ // Either a nullable field was tagged, or
544+ // the @tag is inside an @optional scope that doesn't exist.
545+ let candidate = if ctx. tokens [ & context_field_vid] . is_none ( ) {
546+ // @optional scope that didn't exist. Our query rules say that
547+ // any filters using this tag *must* pass.
548+ CandidateValue :: All
549+ } else {
550+ // The field must have been nullable.
551+ debug_assert ! (
552+ nullable_context_field,
553+ "tagged field {:?} was not nullable but received a null value for it" ,
554+ self . context_field,
555+ ) ;
556+ CandidateValue :: Single ( null_value)
557+ } ;
558+ ( ctx, candidate)
559+ }
560+ other_value => ( ctx, CandidateValue :: Single ( other_value) ) ,
561+ } ) )
517562 }
518563 }
519564}
0 commit comments