@@ -28,6 +28,7 @@ use datafusion_physical_plan::execution_plan::{Boundedness, EmissionType};
2828use stabby:: vec:: Vec as SVec ;
2929
3030use crate :: arrow_wrappers:: WrappedSchema ;
31+ use crate :: physical_expr:: FFI_PhysicalExpr ;
3132use crate :: physical_expr:: partitioning:: FFI_Partitioning ;
3233use crate :: physical_expr:: sort:: FFI_PhysicalSortExpr ;
3334use crate :: util:: FFI_Option ;
@@ -63,6 +64,13 @@ pub struct FFI_PlanProperties {
6364 /// the foreign interface. See [`crate::get_library_marker_id`] and
6465 /// the crate's `README.md` for more information.
6566 pub library_marker_id : extern "C" fn ( ) -> usize ,
67+
68+ /// Return the components of the plan's group-contiguous composite key.
69+ ///
70+ /// See [`datafusion_physical_plan::ExecutionPlan::group_contiguous_exprs`]
71+ /// for the correctness contract.
72+ pub group_contiguous_exprs :
73+ unsafe extern "C" fn ( plan : & Self ) -> SVec < FFI_PhysicalExpr > ,
6674}
6775
6876struct PlanPropertiesPrivateData {
@@ -109,6 +117,18 @@ unsafe extern "C" fn output_ordering_fn_wrapper(
109117 ordering. into ( )
110118}
111119
120+ unsafe extern "C" fn group_contiguous_exprs_fn_wrapper (
121+ properties : & FFI_PlanProperties ,
122+ ) -> SVec < FFI_PhysicalExpr > {
123+ properties
124+ . inner ( )
125+ . group_contiguous_exprs ( )
126+ . iter ( )
127+ . cloned ( )
128+ . map ( FFI_PhysicalExpr :: from)
129+ . collect ( )
130+ }
131+
112132unsafe extern "C" fn schema_fn_wrapper ( properties : & FFI_PlanProperties ) -> WrappedSchema {
113133 let schema: SchemaRef = Arc :: clone ( properties. inner ( ) . eq_properties . schema ( ) ) ;
114134 schema. into ( )
@@ -145,6 +165,7 @@ impl From<&PlanProperties> for FFI_PlanProperties {
145165 release : release_fn_wrapper,
146166 private_data : Box :: into_raw ( private_data) as * mut c_void ,
147167 library_marker_id : crate :: get_library_marker_id,
168+ group_contiguous_exprs : group_contiguous_exprs_fn_wrapper,
148169 }
149170 }
150171}
@@ -186,12 +207,16 @@ impl TryFrom<FFI_PlanProperties> for PlanProperties {
186207 let boundedness: Boundedness =
187208 unsafe { ( ffi_props. boundedness ) ( & ffi_props) . into ( ) } ;
188209
189- Ok ( PlanProperties :: new (
190- eq_properties,
191- partitioning,
192- emission_type,
193- boundedness,
194- ) )
210+ let group_contiguous_exprs =
211+ unsafe { ( ffi_props. group_contiguous_exprs ) ( & ffi_props) }
212+ . iter ( )
213+ . map ( <Arc < dyn datafusion_physical_expr:: PhysicalExpr > >:: from)
214+ . collect ( ) ;
215+
216+ Ok (
217+ PlanProperties :: new ( eq_properties, partitioning, emission_type, boundedness)
218+ . with_group_contiguous_exprs ( group_contiguous_exprs) ,
219+ )
195220 }
196221}
197222
@@ -273,16 +298,16 @@ mod tests {
273298 let schema =
274299 Arc :: new ( Schema :: new ( vec ! [ Field :: new( "a" , DataType :: Float32 , false ) ] ) ) ;
275300
301+ let column = datafusion:: physical_plan:: expressions:: col ( "a" , & schema) ?;
276302 let mut eqp = EquivalenceProperties :: new ( Arc :: clone ( & schema) ) ;
277- let _ = eqp. reorder ( [ PhysicalSortExpr :: new_default (
278- datafusion:: physical_plan:: expressions:: col ( "a" , & schema) ?,
279- ) ] ) ;
303+ let _ = eqp. reorder ( [ PhysicalSortExpr :: new_default ( Arc :: clone ( & column) ) ] ) ;
280304 Ok ( PlanProperties :: new (
281305 eqp,
282306 Partitioning :: RoundRobinBatch ( 3 ) ,
283307 EmissionType :: Incremental ,
284308 Boundedness :: Bounded ,
285- ) )
309+ )
310+ . with_group_contiguous_exprs ( vec ! [ column] ) )
286311 }
287312
288313 fn create_range_test_props ( ) -> Result < PlanProperties > {
0 commit comments