@@ -21,19 +21,23 @@ use std::sync::Arc;
2121use arrow:: datatypes:: SchemaRef ;
2222use arrow:: pyarrow:: ToPyArrow ;
2323use async_trait:: async_trait;
24- use datafusion:: catalog:: Session ;
24+ use datafusion:: catalog:: { Session , TableProviderFactory } ;
2525use datafusion:: common:: Column ;
2626use datafusion:: datasource:: { TableProvider , TableType } ;
27- use datafusion:: logical_expr:: { Expr , LogicalPlanBuilder , TableProviderFilterPushDown } ;
27+ use datafusion:: logical_expr:: {
28+ CreateExternalTable , Expr , LogicalPlanBuilder , TableProviderFilterPushDown ,
29+ } ;
2830use datafusion:: physical_plan:: ExecutionPlan ;
2931use datafusion:: prelude:: DataFrame ;
32+ use datafusion_ffi:: proto:: logical_extension_codec:: FFI_LogicalExtensionCodec ;
3033use pyo3:: IntoPyObjectExt ;
3134use pyo3:: prelude:: * ;
3235
3336use crate :: context:: PySessionContext ;
3437use crate :: dataframe:: PyDataFrame ;
3538use crate :: dataset:: Dataset ;
36- use crate :: utils:: table_provider_from_pycapsule;
39+ use crate :: expr:: create_external_table:: PyCreateExternalTable ;
40+ use crate :: { errors, utils} ;
3741
3842/// This struct is used as a common method for all TableProviders,
3943/// whether they refer to an FFI provider, an internally known
@@ -91,7 +95,7 @@ impl PyTable {
9195 Some ( session) => session,
9296 None => PySessionContext :: global_ctx ( ) ?. into_bound_py_any ( obj. py ( ) ) ?,
9397 } ;
94- table_provider_from_pycapsule ( obj. clone ( ) , session) ?
98+ utils :: table_provider_from_pycapsule ( obj. clone ( ) , session) ?
9599 } {
96100 Ok ( PyTable :: from ( provider) )
97101 } else {
@@ -206,3 +210,51 @@ impl TableProvider for TempViewTable {
206210 Ok ( vec ! [ TableProviderFilterPushDown :: Exact ; filters. len( ) ] )
207211 }
208212}
213+
214+ #[ derive( Debug ) ]
215+ pub ( crate ) struct RustWrappedPyTableProviderFactory {
216+ pub ( crate ) table_provider_factory : Py < PyAny > ,
217+ pub ( crate ) codec : Arc < FFI_LogicalExtensionCodec > ,
218+ }
219+
220+ impl RustWrappedPyTableProviderFactory {
221+ pub fn new ( table_provider_factory : Py < PyAny > , codec : Arc < FFI_LogicalExtensionCodec > ) -> Self {
222+ Self {
223+ table_provider_factory,
224+ codec,
225+ }
226+ }
227+
228+ fn create_inner (
229+ & self ,
230+ cmd : CreateExternalTable ,
231+ codec : Bound < PyAny > ,
232+ ) -> PyResult < Arc < dyn TableProvider > > {
233+ Python :: attach ( |py| {
234+ let provider = self . table_provider_factory . bind ( py) ;
235+ let cmd = PyCreateExternalTable :: from ( cmd) ;
236+
237+ provider
238+ . call_method1 ( "create" , ( cmd, ) )
239+ . and_then ( |t| PyTable :: new ( t, Some ( codec) ) )
240+ . map ( |t| t. table ( ) )
241+ } )
242+ }
243+ }
244+
245+ #[ async_trait]
246+ impl TableProviderFactory for RustWrappedPyTableProviderFactory {
247+ async fn create (
248+ & self ,
249+ _: & dyn Session ,
250+ cmd : & CreateExternalTable ,
251+ ) -> datafusion:: common:: Result < Arc < dyn TableProvider > > {
252+ Python :: attach ( |py| {
253+ let codec = utils:: create_logical_extension_capsule ( py, self . codec . as_ref ( ) )
254+ . map_err ( errors:: to_datafusion_err) ?;
255+
256+ self . create_inner ( cmd. clone ( ) , codec. into_any ( ) )
257+ . map_err ( errors:: to_datafusion_err)
258+ } )
259+ }
260+ }
0 commit comments