@@ -8,15 +8,17 @@ use crate::{
88 ir:: {
99 Argument , ContextField , EdgeParameters , Eid , FieldRef , FieldValue , FoldSpecificFieldKind ,
1010 IREdge , IRFold , IRQueryComponent , IRVertex , IndexedQuery , LocalField , Operation ,
11- OperationSubject , Recursive , Vid ,
11+ OperationSubject , Recursive , TransformBase , Vid ,
1212 } ,
1313 util:: BTreeMapTryInsertExt ,
1414} ;
1515
1616use super :: {
17- error:: QueryArgumentsError , filtering:: apply_filter, Adapter , AsVertex , ContextIterator ,
18- ContextOutcomeIterator , DataContext , InterpretedQuery , ResolveEdgeInfo , ResolveInfo ,
19- TaggedValue , ValueOrVec , VertexIterator ,
17+ error:: QueryArgumentsError ,
18+ filtering:: apply_filter,
19+ transformation:: { apply_transforms, push_transform_argument_tag_values_onto_stack} ,
20+ Adapter , AsVertex , ContextIterator , ContextOutcomeIterator , DataContext , InterpretedQuery ,
21+ ResolveEdgeInfo , ResolveInfo , TaggedValue , ValueOrVec , VertexIterator ,
2022} ;
2123
2224#[ derive( Debug , Clone ) ]
@@ -621,25 +623,15 @@ fn compute_fold<'query, AdapterT: Adapter<'query> + 'query>(
621623 let mut post_filtered_iterator: ContextIterator < ' query , AdapterT :: Vertex > =
622624 Box :: new ( folded_iterator) ;
623625 for post_fold_filter in fold. post_filters . iter ( ) {
624- let left = post_fold_filter. left ( ) ;
625- match left {
626- OperationSubject :: FoldSpecificField ( fold_specific_field) => {
627- let remapped_operation = post_fold_filter. map ( |_| fold_specific_field. kind , |x| x) ;
628- post_filtered_iterator = apply_fold_specific_filter (
629- adapter. as_ref ( ) ,
630- carrier,
631- parent_component,
632- fold. as_ref ( ) ,
633- expanding_from. vid ,
634- & remapped_operation,
635- post_filtered_iterator,
636- ) ;
637- }
638- OperationSubject :: TransformedField ( _) => todo ! ( ) ,
639- OperationSubject :: LocalField ( _) => {
640- unreachable ! ( "unexpectedly found a fold post-filtering step that references a LocalField: {fold:#?}" ) ;
641- }
642- }
626+ post_filtered_iterator = apply_fold_specific_filter (
627+ adapter. as_ref ( ) ,
628+ carrier,
629+ parent_component,
630+ fold. as_ref ( ) ,
631+ expanding_from. vid ,
632+ post_fold_filter,
633+ post_filtered_iterator,
634+ ) ;
643635 }
644636
645637 // Compute the outputs from this fold.
@@ -809,7 +801,63 @@ fn apply_filter_with_non_folded_field_subject<'query, AdapterT: Adapter<'query>>
809801 filter. map_left ( |_| field) ,
810802 iterator,
811803 ) ,
812- OperationSubject :: TransformedField ( _) => todo ! ( ) ,
804+ OperationSubject :: TransformedField ( transformed) => {
805+ let prepped_iterator = push_transform_argument_tag_values_onto_stack (
806+ adapter,
807+ carrier,
808+ component,
809+ current_vid,
810+ & transformed. value . transforms ,
811+ iterator,
812+ ) ;
813+
814+ let query_variables =
815+ Arc :: clone ( & carrier. query . as_ref ( ) . expect ( "query was not returned" ) . arguments ) ;
816+ let transform_data = Arc :: clone ( & transformed. value ) ;
817+
818+ match & transformed. value . base {
819+ TransformBase :: ContextField ( field) => {
820+ assert_eq ! ( current_vid, field. vertex_id, "filter left-hand side was a transformed field from a different vertex: {current_vid:?} {filter:?}" ) ;
821+ let local_field = LocalField {
822+ field_name : field. field_name . clone ( ) ,
823+ field_type : field. field_type . clone ( ) ,
824+ } ;
825+
826+ let filter_input_iterator = Box :: new (
827+ compute_local_field_with_separate_value (
828+ adapter,
829+ carrier,
830+ component,
831+ current_vid,
832+ & local_field,
833+ prepped_iterator,
834+ )
835+ . map ( move |( mut ctx, mut value) | {
836+ value = apply_transforms (
837+ & transform_data,
838+ & query_variables,
839+ & mut ctx. values ,
840+ value,
841+ ) ;
842+ ctx. values . push ( value) ;
843+ ctx
844+ } ) ,
845+ ) ;
846+
847+ apply_filter (
848+ adapter,
849+ carrier,
850+ component,
851+ current_vid,
852+ & filter. map ( |_| ( ) , |r| r) ,
853+ filter_input_iterator,
854+ )
855+ }
856+ TransformBase :: FoldSpecificField ( ..) => unreachable ! (
857+ "illegal filter over fold-specific field passed to this function: {filter:?}"
858+ ) ,
859+ }
860+ }
813861 OperationSubject :: FoldSpecificField ( ..) => unreachable ! (
814862 "illegal filter over fold-specific field passed to this function: {filter:?}"
815863 ) ,
@@ -844,27 +892,70 @@ fn apply_fold_specific_filter<'query, AdapterT: Adapter<'query>>(
844892 component : & IRQueryComponent ,
845893 fold : & IRFold ,
846894 current_vid : Vid ,
847- filter : & Operation < FoldSpecificFieldKind , & Argument > ,
895+ filter : & Operation < OperationSubject , Argument > ,
848896 iterator : ContextIterator < ' query , AdapterT :: Vertex > ,
849897) -> ContextIterator < ' query , AdapterT :: Vertex > {
850- let fold_specific_field = filter. left ( ) ;
851- let field_iterator = Box :: new ( compute_fold_specific_field_with_separate_value ( fold. eid , fold_specific_field, iterator) . map ( |( mut ctx, tagged_value) | {
852- let value = match tagged_value {
853- TaggedValue :: Some ( value) => value,
854- TaggedValue :: NonexistentOptional => {
855- unreachable ! ( "while applying fold-specific filter, the @fold turned out to not exist: {ctx:?}" )
898+ let left = filter. left ( ) ;
899+ let ( fold_specific_field, transform_data) = match left {
900+ OperationSubject :: FoldSpecificField ( field) => ( field, None ) ,
901+ OperationSubject :: TransformedField ( transformed) => match & transformed. value . base {
902+ TransformBase :: FoldSpecificField ( field) => ( field, Some ( & transformed. value ) ) ,
903+ TransformBase :: ContextField ( _) => {
904+ unreachable ! ( "post-fold filter does not refer to a fold-specific field: {left:?}" )
856905 }
857- } ;
858- ctx. values . push ( value) ;
859- ctx
860- } ) ) ;
906+ } ,
907+ OperationSubject :: LocalField ( _) => {
908+ unreachable ! ( "post-fold filter does not refer to a fold-specific field: {left:?}" )
909+ }
910+ } ;
911+
912+ let field_iterator: ContextIterator < ' query , AdapterT :: Vertex > = if let Some ( transform_data) =
913+ transform_data
914+ {
915+ let prepped_iterator = push_transform_argument_tag_values_onto_stack (
916+ adapter,
917+ carrier,
918+ component,
919+ current_vid,
920+ & transform_data. transforms ,
921+ iterator,
922+ ) ;
923+
924+ let query_variables =
925+ Arc :: clone ( & carrier. query . as_ref ( ) . expect ( "query was not returned" ) . arguments ) ;
926+ let transform_data = Arc :: clone ( transform_data) ;
927+ Box :: new ( compute_fold_specific_field_with_separate_value ( fold. eid , & fold_specific_field. kind , prepped_iterator) . map ( move |( mut ctx, tagged_value) | {
928+ let mut value = match tagged_value {
929+ TaggedValue :: Some ( value) => value,
930+ TaggedValue :: NonexistentOptional => {
931+ unreachable ! ( "while applying fold-specific filter, the @fold turned out to not exist: {ctx:?}" )
932+ }
933+ } ;
934+
935+ value = apply_transforms ( & transform_data, & query_variables, & mut ctx. values , value) ;
936+
937+ ctx. values . push ( value) ;
938+ ctx
939+ } ) )
940+ } else {
941+ Box :: new ( compute_fold_specific_field_with_separate_value ( fold. eid , & fold_specific_field. kind , iterator) . map ( |( mut ctx, tagged_value) | {
942+ let value = match tagged_value {
943+ TaggedValue :: Some ( value) => value,
944+ TaggedValue :: NonexistentOptional => {
945+ unreachable ! ( "while applying fold-specific filter, the @fold turned out to not exist: {ctx:?}" )
946+ }
947+ } ;
948+ ctx. values . push ( value) ;
949+ ctx
950+ } ) )
951+ } ;
861952
862953 apply_filter (
863954 adapter,
864955 carrier,
865956 component,
866957 current_vid,
867- & filter. map ( |_| ( ) , |r| * r) ,
958+ & filter. map ( |_| ( ) , |r| r) ,
868959 field_iterator,
869960 )
870961}
0 commit comments