1- use std:: sync:: { Arc , OnceLock } ;
1+ use std:: hash:: Hash ;
2+ use std:: sync:: { Arc , OnceLock , RwLock } ;
23
3- use vortex_array:: aliases:: hash_map:: HashMap ;
4+ use vortex_array:: aliases:: hash_map:: { Entry , HashMap } ;
45use vortex_array:: ContextRef ;
56use vortex_dtype:: { DType , FieldName , StructDType } ;
67use vortex_error:: { vortex_err, vortex_panic, VortexExpect , VortexResult } ;
8+ use vortex_expr:: transform:: partition:: { partition, PartitionedExpr } ;
9+ use vortex_expr:: ExprRef ;
710
811use crate :: layouts:: struct_:: StructLayout ;
912use crate :: segments:: AsyncSegmentReader ;
@@ -18,6 +21,8 @@ pub struct StructReader {
1821
1922 field_readers : Arc < [ OnceLock < Arc < dyn LayoutReader > > ] > ,
2023 field_lookup : HashMap < FieldName , usize > ,
24+
25+ expr_cache : Arc < RwLock < HashMap < ExactExpr , Arc < PartitionedExpr > > > > ,
2126}
2227
2328impl StructReader {
@@ -52,6 +57,7 @@ impl StructReader {
5257 segments,
5358 field_readers,
5459 field_lookup,
60+ expr_cache : Arc :: new ( Default :: default ( ) ) ,
5561 } )
5662 }
5763
@@ -77,10 +83,46 @@ impl StructReader {
7783 child_layout. reader ( self . segments . clone ( ) , self . ctx . clone ( ) )
7884 } )
7985 }
86+
87+ /// Utility for partitioning an expression over the fields of a struct.
88+ pub ( crate ) fn partition_expr ( & self , expr : ExprRef ) -> VortexResult < Arc < PartitionedExpr > > {
89+ Ok (
90+ match self
91+ . expr_cache
92+ . write ( )
93+ . map_err ( |_| vortex_err ! ( "poisoned lock" ) ) ?
94+ . entry ( ExactExpr ( expr. clone ( ) ) )
95+ {
96+ Entry :: Occupied ( entry) => entry. get ( ) . clone ( ) ,
97+ Entry :: Vacant ( entry) => entry
98+ . insert ( Arc :: new ( partition ( expr, self . struct_dtype ( ) ) ?) )
99+ . clone ( ) ,
100+ } ,
101+ )
102+ }
80103}
81104
82105impl LayoutReader for StructReader {
83106 fn layout ( & self ) -> & LayoutData {
84107 & self . layout
85108 }
86109}
110+
111+ /// An expression wrapper that performs pointer equality.
112+ /// NOTE(ngates): we should consider if this shoud live in vortex-expr crate?
113+ #[ derive( Clone ) ]
114+ struct ExactExpr ( ExprRef ) ;
115+
116+ impl PartialEq for ExactExpr {
117+ fn eq ( & self , other : & Self ) -> bool {
118+ Arc :: ptr_eq ( & self . 0 , & other. 0 )
119+ }
120+ }
121+
122+ impl Eq for ExactExpr { }
123+
124+ impl Hash for ExactExpr {
125+ fn hash < H : std:: hash:: Hasher > ( & self , state : & mut H ) {
126+ Arc :: as_ptr ( & self . 0 ) . hash ( state)
127+ }
128+ }
0 commit comments