@@ -186,6 +186,26 @@ impl FetchGraph {
186186
187187 Ok ( ( ) )
188188 }
189+
190+ /// Checks whether the given step is an ancestor of a step that has the given condition
191+ pub fn is_ancestor_of_condition ( & self , step_index : NodeIndex , condition : & Condition ) -> bool {
192+ let mut bfs = Bfs :: new ( & self . graph , step_index) ;
193+
194+ while let Some ( current_index) = bfs. next ( & self . graph ) {
195+ let current_step = match self . get_step_data ( current_index) {
196+ Ok ( s) => s,
197+ Err ( _) => continue ,
198+ } ;
199+
200+ if let Some ( step_condition) = & current_step. condition {
201+ if step_condition == condition {
202+ return true ;
203+ }
204+ }
205+ }
206+
207+ false
208+ }
189209}
190210
191211impl Display for FetchGraph {
@@ -1004,6 +1024,92 @@ fn process_subgraph_entrypoint_edge(
10041024 )
10051025}
10061026
1027+ // TODO: simplfy args
1028+ #[ allow( clippy:: too_many_arguments) ]
1029+ #[ instrument( level = "trace" , skip_all, fields(
1030+ parent_fetch_step_index = parent_fetch_step_index. index( ) ,
1031+ requiring_fetch_step_index = requiring_fetch_step_index. map( |f| f. index( ) ) ,
1032+ type_name = target_type_name,
1033+ response_path = response_path. to_string( ) ,
1034+ fetch_path = fetch_path. to_string( )
1035+ ) ) ]
1036+ fn process_selfie_edge (
1037+ graph : & Graph ,
1038+ fetch_graph : & mut FetchGraph ,
1039+ override_context : & PlannerOverrideContext ,
1040+ query_node : & QueryTreeNode ,
1041+ parent_fetch_step_index : NodeIndex ,
1042+ requiring_fetch_step_index : Option < NodeIndex > ,
1043+ response_path : & MergePath ,
1044+ fetch_path : & MergePath ,
1045+ target_type_name : & String ,
1046+ condition : Option < & Condition > ,
1047+ ) -> Result < Vec < NodeIndex > , FetchGraphError > {
1048+ let is_ancestor_of_condition = match condition {
1049+ Some ( c) => fetch_graph. is_ancestor_of_condition ( parent_fetch_step_index, c) ,
1050+ None => false ,
1051+ } ;
1052+
1053+ let parent_fetch_step = fetch_graph. get_step_data_mut ( parent_fetch_step_index) ?;
1054+ trace ! (
1055+ "starting an inline fragment for type '{}' to fetch step [{}]" ,
1056+ parent_fetch_step_index. index( ) ,
1057+ target_type_name,
1058+ ) ;
1059+ parent_fetch_step. output . add_at_path (
1060+ & TypeAwareSelection {
1061+ selection_set : SelectionSet {
1062+ items : vec ! [ SelectionItem :: InlineFragment ( InlineFragmentSelection {
1063+ type_condition: target_type_name. clone( ) ,
1064+ selections: SelectionSet :: default ( ) ,
1065+ skip_if: condition. and_then( |c| {
1066+ if is_ancestor_of_condition {
1067+ None
1068+ } else {
1069+ c. to_skip_if( )
1070+ }
1071+ } ) ,
1072+ include_if: condition. and_then( |c| {
1073+ if is_ancestor_of_condition {
1074+ None
1075+ } else {
1076+ c. to_include_if( )
1077+ }
1078+ } ) ,
1079+ } ) ] ,
1080+ } ,
1081+ type_name : target_type_name. clone ( ) ,
1082+ } ,
1083+ fetch_path. clone ( ) ,
1084+ false ,
1085+ ) ?;
1086+
1087+ let segment_condition = if is_ancestor_of_condition {
1088+ None
1089+ } else {
1090+ condition. cloned ( )
1091+ } ;
1092+ let child_response_path = response_path. push ( Segment :: Cast (
1093+ target_type_name. clone ( ) ,
1094+ segment_condition. clone ( ) ,
1095+ ) ) ;
1096+ let child_fetch_path =
1097+ fetch_path. push ( Segment :: Cast ( target_type_name. clone ( ) , segment_condition) ) ;
1098+
1099+ process_children_for_fetch_steps (
1100+ graph,
1101+ fetch_graph,
1102+ override_context,
1103+ query_node,
1104+ parent_fetch_step_index,
1105+ & child_response_path,
1106+ & child_fetch_path,
1107+ requiring_fetch_step_index,
1108+ condition,
1109+ false ,
1110+ )
1111+ }
1112+
10071113// TODO: simplfy args
10081114#[ allow( clippy:: too_many_arguments) ]
10091115#[ instrument( level = "trace" , skip_all, fields(
@@ -1111,6 +1217,25 @@ fn process_plain_field_edge(
11111217 fetch_graph. connect ( parent_fetch_step_index, requiring_fetch_step_index) ;
11121218 }
11131219
1220+ // If we are inserting into "... | [Product] @include(if: $bool)", we don't need the condition on the field.
1221+ let condition_in_path = if let Some ( condition) = condition {
1222+ fetch_path. inner . iter ( ) . any ( |segment| {
1223+ matches ! (
1224+ segment,
1225+ Segment :: Cast ( _, Some ( c) ) | Segment :: Field ( _, _, Some ( c) ) if c == condition
1226+ )
1227+ } )
1228+ } else {
1229+ false
1230+ } ;
1231+
1232+ let ancestor_of_condition = match condition {
1233+ Some ( c) => fetch_graph. is_ancestor_of_condition ( parent_fetch_step_index, c) ,
1234+ None => false ,
1235+ } ;
1236+
1237+ let should_strip_condition = condition_in_path || ancestor_of_condition;
1238+
11141239 let parent_fetch_step = fetch_graph. get_step_data_mut ( parent_fetch_step_index) ?;
11151240 trace ! (
11161241 "adding output field '{}' to fetch step [{}]" ,
@@ -1126,8 +1251,20 @@ fn process_plain_field_edge(
11261251 alias: query_node. selection_alias( ) . map( |a| a. to_string( ) ) ,
11271252 selections: SelectionSet :: default ( ) ,
11281253 arguments: query_node. selection_arguments( ) . cloned( ) ,
1129- skip_if: None ,
1130- include_if: None ,
1254+ skip_if: condition. and_then( |c| {
1255+ if should_strip_condition {
1256+ None
1257+ } else {
1258+ c. to_skip_if( )
1259+ }
1260+ } ) ,
1261+ include_if: condition. and_then( |c| {
1262+ if should_strip_condition {
1263+ None
1264+ } else {
1265+ c. to_include_if( )
1266+ }
1267+ } ) ,
11311268 } ) ] ,
11321269 } ,
11331270 type_name : field_move. type_name . to_string ( ) ,
@@ -1137,19 +1274,24 @@ fn process_plain_field_edge(
11371274 ) ?;
11381275
11391276 let child_segment = query_node. selection_alias ( ) . unwrap_or ( & field_move. name ) ;
1277+ let segment_condition = if ancestor_of_condition {
1278+ None
1279+ } else {
1280+ condition. cloned ( )
1281+ } ;
11401282 let segment_args_hash = query_node
11411283 . selection_arguments ( )
11421284 . map ( |a| a. hash_u64 ( ) )
11431285 . unwrap_or ( 0 ) ;
11441286 let mut child_response_path = response_path. push ( Segment :: Field (
11451287 child_segment. to_string ( ) ,
11461288 segment_args_hash,
1147- None ,
1289+ segment_condition . clone ( ) ,
11481290 ) ) ;
11491291 let mut child_fetch_path = fetch_path. push ( Segment :: Field (
11501292 child_segment. to_string ( ) ,
11511293 segment_args_hash,
1152- None ,
1294+ segment_condition ,
11531295 ) ) ;
11541296
11551297 if field_move. is_list {
@@ -1595,6 +1737,18 @@ fn process_query_node(
15951737 created_from_requires,
15961738 ) ,
15971739 } ,
1740+ Edge :: Selfie ( type_name) => process_selfie_edge (
1741+ graph,
1742+ fetch_graph,
1743+ override_context,
1744+ query_node,
1745+ parent_fetch_step_index,
1746+ requiring_fetch_step_index,
1747+ response_path,
1748+ fetch_path,
1749+ type_name,
1750+ condition,
1751+ ) ,
15981752 Edge :: AbstractMove ( type_name) => process_abstract_edge (
15991753 graph,
16001754 fetch_graph,
0 commit comments