11use std:: {
22 ffi:: { c_void, CString } ,
3+ ptr:: null,
34 sync:: Arc ,
45} ;
56
6- use datafusion:: { physical_expr:: { EquivalenceProperties , LexOrdering } , physical_plan:: { DisplayAs , ExecutionMode , ExecutionPlan , Partitioning , PlanProperties } } ;
7+ use datafusion:: error:: Result ;
8+ use datafusion:: {
9+ error:: DataFusionError ,
10+ parquet:: file:: properties,
11+ physical_expr:: { EquivalenceProperties , LexOrdering } ,
12+ physical_plan:: { DisplayAs , ExecutionMode , ExecutionPlan , Partitioning , PlanProperties } ,
13+ } ;
714
815#[ repr( C ) ]
916#[ derive( Debug ) ]
1017#[ allow( missing_docs) ]
1118#[ allow( non_camel_case_types) ]
1219pub struct FFI_ExecutionPlan {
13- pub properties : Option < unsafe extern "C" fn ( provider : * const FFI_ExecutionPlan ) -> FFI_ArrowSchema > ,
20+ pub properties :
21+ Option < unsafe extern "C" fn ( plan : * const FFI_ExecutionPlan ) -> FFI_PlanProperties > ,
22+ pub children : Option <
23+ unsafe extern "C" fn (
24+ plan : * const FFI_ExecutionPlan ,
25+ num_children : & mut usize ,
26+ out : & mut * const FFI_ExecutionPlan ,
27+ ) -> i32 ,
28+ > ,
1429
1530 pub private_data : * mut c_void ,
1631}
1732
18- unsafe impl Send for FFI_ExecutionPlan { }
19- unsafe impl Sync for FFI_ExecutionPlan { }
20-
2133pub struct ExecutionPlanPrivateData {
2234 pub plan : Arc < dyn ExecutionPlan + Send > ,
2335 pub last_error : Option < CString > ,
2436}
2537
26- struct ExportedExecutionPlan ( * const FFI_ExecutionPlan ) ;
38+ unsafe extern "C" fn properties_fn_wrapper ( plan : * const FFI_ExecutionPlan ) -> FFI_PlanProperties {
39+ let private_data = ( * plan) . private_data as * const ExecutionPlanPrivateData ;
40+ let properties = ( * private_data) . plan . properties ( ) ;
41+ properties. into ( )
42+ }
2743
28- impl FFI_ExecutionPlan {
44+ unsafe extern "C" fn children_fn_wrapper (
45+ plan : * const FFI_ExecutionPlan ,
46+ num_children : & mut usize ,
47+ out : & mut * const FFI_ExecutionPlan ,
48+ ) -> i32 {
49+ let private_data = ( * plan) . private_data as * const ExecutionPlanPrivateData ;
50+
51+ let children = ( * private_data) . plan . children ( ) ;
52+ * num_children = children. len ( ) ;
53+ let children: Vec < FFI_ExecutionPlan > = children
54+ . into_iter ( )
55+ . map ( |child| FFI_ExecutionPlan :: new ( child. clone ( ) ) )
56+ . collect ( ) ;
57+ * out = children. as_ptr ( ) ;
58+
59+ 0
60+ }
2961
30- pub fn empty ( ) -> Self {
31- Self {
32- private_data : std:: ptr:: null_mut ( ) ,
33- }
62+ // Since the trait ExecutionPlan requires borrowed values, we wrap our FFI.
63+ // This struct exists on the consumer side (datafusion-python, for example) and not
64+ // in the provider's side.
65+ #[ derive( Debug ) ]
66+ pub struct ExportedExecutionPlan {
67+ plan : * const FFI_ExecutionPlan ,
68+ properties : PlanProperties ,
69+ children : Vec < Arc < dyn ExecutionPlan > > ,
70+ }
71+
72+ unsafe impl Send for ExportedExecutionPlan { }
73+ unsafe impl Sync for ExportedExecutionPlan { }
74+
75+ impl DisplayAs for ExportedExecutionPlan {
76+ fn fmt_as (
77+ & self ,
78+ t : datafusion:: physical_plan:: DisplayFormatType ,
79+ f : & mut std:: fmt:: Formatter ,
80+ ) -> std:: fmt:: Result {
81+ todo ! ( )
3482 }
3583}
3684
@@ -42,12 +90,63 @@ impl FFI_ExecutionPlan {
4290 } ) ;
4391
4492 Self {
45- private_data : Box :: into_raw ( private_data) as * mut c_void
93+ properties : Some ( properties_fn_wrapper) ,
94+ children : Some ( children_fn_wrapper) ,
95+ private_data : Box :: into_raw ( private_data) as * mut c_void ,
96+ }
97+ }
98+
99+ pub fn empty ( ) -> Self {
100+ Self {
101+ properties : None ,
102+ children : None ,
103+ private_data : std:: ptr:: null_mut ( ) ,
46104 }
47105 }
48106}
49107
50- impl ExecutionPlan for FFI_ExecutionPlan {
108+ impl ExportedExecutionPlan {
109+ pub fn new ( plan : * const FFI_ExecutionPlan ) -> Result < Self > {
110+ let properties = unsafe {
111+ let properties_fn = ( * plan) . properties . ok_or ( DataFusionError :: NotImplemented (
112+ "properties not implemented on FFI_ExecutionPlan" . to_string ( ) ,
113+ ) ) ?;
114+ properties_fn ( plan) . into ( )
115+ } ;
116+
117+ let children = unsafe {
118+ let children_fn = ( * plan) . children . ok_or ( DataFusionError :: NotImplemented (
119+ "children not implemented on FFI_ExecutionPlan" . to_string ( ) ,
120+ ) ) ?;
121+ let mut num_children = 0 ;
122+ let mut children_ptr: * const FFI_ExecutionPlan = null ( ) ;
123+
124+ if children_fn ( plan, & mut num_children, & mut children_ptr) != 0 {
125+ return Err ( DataFusionError :: Plan (
126+ "Error getting children for FFI_ExecutionPlan" . to_string ( ) ,
127+ ) ) ;
128+ }
129+
130+ let ffi_vec = Vec :: from_raw_parts ( & mut children_ptr, num_children, num_children) ;
131+ let maybe_children: Result < Vec < _ > > = ffi_vec
132+ . into_iter ( )
133+ . map ( |child| {
134+ ExportedExecutionPlan :: new ( child) . map ( |c| Arc :: new ( c) as Arc < dyn ExecutionPlan > )
135+ } )
136+ . collect ( ) ;
137+
138+ maybe_children?
139+ } ;
140+
141+ Ok ( Self {
142+ plan,
143+ properties,
144+ children,
145+ } )
146+ }
147+ }
148+
149+ impl ExecutionPlan for ExportedExecutionPlan {
51150 fn name ( & self ) -> & str {
52151 todo ! ( )
53152 }
@@ -57,11 +156,11 @@ impl ExecutionPlan for FFI_ExecutionPlan {
57156 }
58157
59158 fn properties ( & self ) -> & datafusion:: physical_plan:: PlanProperties {
60- self . properties
159+ & self . properties
61160 }
62161
63162 fn children ( & self ) -> Vec < & Arc < dyn ExecutionPlan > > {
64- todo ! ( )
163+ self . children . iter ( ) . collect ( )
65164 }
66165
67166 fn with_new_children (
@@ -81,16 +180,15 @@ impl ExecutionPlan for FFI_ExecutionPlan {
81180}
82181
83182impl DisplayAs for FFI_ExecutionPlan {
84- fn fmt_as ( & self , t : datafusion:: physical_plan:: DisplayFormatType , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
183+ fn fmt_as (
184+ & self ,
185+ t : datafusion:: physical_plan:: DisplayFormatType ,
186+ f : & mut std:: fmt:: Formatter ,
187+ ) -> std:: fmt:: Result {
85188 todo ! ( )
86189 }
87190}
88191
89-
90-
91-
92-
93-
94192#[ repr( C ) ]
95193#[ derive( Debug ) ]
96194#[ allow( missing_docs) ]
@@ -104,4 +202,16 @@ pub struct FFI_PlanProperties {
104202 pub execution_mode : ExecutionMode ,
105203 /// See [ExecutionPlanProperties::output_ordering]
106204 output_ordering : Option < LexOrdering > ,
107- }
205+ }
206+
207+ impl From < & PlanProperties > for FFI_PlanProperties {
208+ fn from ( value : & PlanProperties ) -> Self {
209+ todo ! ( )
210+ }
211+ }
212+
213+ impl From < FFI_PlanProperties > for PlanProperties {
214+ fn from ( value : FFI_PlanProperties ) -> Self {
215+ todo ! ( )
216+ }
217+ }
0 commit comments