1717
1818use crate :: dataset:: Dataset ;
1919use crate :: errors:: { py_datafusion_err, to_datafusion_err, PyDataFusionError , PyDataFusionResult } ;
20+ use crate :: table:: PyTableProvider ;
2021use crate :: utils:: { validate_pycapsule, wait_for_future} ;
2122use async_trait:: async_trait;
2223use datafusion:: catalog:: { MemoryCatalogProvider , MemorySchemaProvider } ;
@@ -51,7 +52,7 @@ pub struct PySchema {
5152#[ pyclass( name = "RawTable" , module = "datafusion.catalog" , subclass) ]
5253#[ derive( Clone ) ]
5354pub struct PyTable {
54- pub table : Arc < dyn TableProvider > ,
55+ pub table : Arc < dyn TableProvider + Send > ,
5556}
5657
5758impl From < Arc < dyn CatalogProvider > > for PyCatalog {
@@ -67,11 +68,11 @@ impl From<Arc<dyn SchemaProvider>> for PySchema {
6768}
6869
6970impl PyTable {
70- pub fn new ( table : Arc < dyn TableProvider > ) -> Self {
71+ pub fn new ( table : Arc < dyn TableProvider + Send > ) -> Self {
7172 Self { table }
7273 }
7374
74- pub fn table ( & self ) -> Arc < dyn TableProvider > {
75+ pub fn table ( & self ) -> Arc < dyn TableProvider + Send > {
7576 self . table . clone ( )
7677 }
7778}
@@ -205,15 +206,18 @@ impl PySchema {
205206
206207 let provider = unsafe { capsule. reference :: < FFI_TableProvider > ( ) } ;
207208 let provider: ForeignTableProvider = provider. into ( ) ;
208- Arc :: new ( provider) as Arc < dyn TableProvider >
209+ Arc :: new ( provider) as Arc < dyn TableProvider + Send >
209210 } else {
210211 match table_provider. extract :: < PyTable > ( ) {
211212 Ok ( py_table) => py_table. table ,
212- Err ( _) => {
213- let py = table_provider. py ( ) ;
214- let provider = Dataset :: new ( & table_provider, py) ?;
215- Arc :: new ( provider) as Arc < dyn TableProvider >
216- }
213+ Err ( _) => match table_provider. extract :: < PyTableProvider > ( ) {
214+ Ok ( py_provider) => py_provider. into_inner ( ) ,
215+ Err ( _) => {
216+ let py = table_provider. py ( ) ;
217+ let provider = Dataset :: new ( & table_provider, py) ?;
218+ Arc :: new ( provider) as Arc < dyn TableProvider + Send >
219+ }
220+ } ,
217221 }
218222 } ;
219223
@@ -294,7 +298,7 @@ impl RustWrappedPySchemaProvider {
294298 }
295299 }
296300
297- fn table_inner ( & self , name : & str ) -> PyResult < Option < Arc < dyn TableProvider > > > {
301+ fn table_inner ( & self , name : & str ) -> PyResult < Option < Arc < dyn TableProvider + Send > > > {
298302 Python :: with_gil ( |py| {
299303 let provider = self . schema_provider . bind ( py) ;
300304 let py_table_method = provider. getattr ( "table" ) ?;
@@ -305,26 +309,30 @@ impl RustWrappedPySchemaProvider {
305309 }
306310
307311 if py_table. hasattr ( "__datafusion_table_provider__" ) ? {
308- let capsule = provider . getattr ( "__datafusion_table_provider__" ) ?. call0 ( ) ?;
312+ let capsule = py_table . getattr ( "__datafusion_table_provider__" ) ?. call0 ( ) ?;
309313 let capsule = capsule. downcast :: < PyCapsule > ( ) . map_err ( py_datafusion_err) ?;
310314 validate_pycapsule ( capsule, "datafusion_table_provider" ) ?;
311315
312316 let provider = unsafe { capsule. reference :: < FFI_TableProvider > ( ) } ;
313317 let provider: ForeignTableProvider = provider. into ( ) ;
314318
315- Ok ( Some ( Arc :: new ( provider) as Arc < dyn TableProvider > ) )
319+ Ok ( Some ( Arc :: new ( provider) as Arc < dyn TableProvider + Send > ) )
316320 } else {
317321 if let Ok ( inner_table) = py_table. getattr ( "table" ) {
318322 if let Ok ( inner_table) = inner_table. extract :: < PyTable > ( ) {
319323 return Ok ( Some ( inner_table. table ) ) ;
320324 }
321325 }
322326
327+ if let Ok ( py_provider) = py_table. extract :: < PyTableProvider > ( ) {
328+ return Ok ( Some ( py_provider. into_inner ( ) ) ) ;
329+ }
330+
323331 match py_table. extract :: < PyTable > ( ) {
324332 Ok ( py_table) => Ok ( Some ( py_table. table ) ) ,
325333 Err ( _) => {
326334 let ds = Dataset :: new ( & py_table, py) . map_err ( py_datafusion_err) ?;
327- Ok ( Some ( Arc :: new ( ds) as Arc < dyn TableProvider > ) )
335+ Ok ( Some ( Arc :: new ( ds) as Arc < dyn TableProvider + Send > ) )
328336 }
329337 }
330338 }
@@ -360,15 +368,32 @@ impl SchemaProvider for RustWrappedPySchemaProvider {
360368 & self ,
361369 name : & str ,
362370 ) -> datafusion:: common:: Result < Option < Arc < dyn TableProvider > > , DataFusionError > {
363- self . table_inner ( name) . map_err ( to_datafusion_err)
371+ // Convert from our internal Send type to the trait expected type
372+ match self . table_inner ( name) . map_err ( to_datafusion_err) ? {
373+ Some ( table) => {
374+ // Safe conversion: we're widening the bounds (removing Send)
375+ let raw = Arc :: into_raw ( table) ;
376+ let wide: * const dyn TableProvider = raw as * const _ ;
377+ let arc = unsafe { Arc :: from_raw ( wide) } ;
378+ Ok ( Some ( arc) )
379+ }
380+ None => Ok ( None ) ,
381+ }
364382 }
365383
366384 fn register_table (
367385 & self ,
368386 name : String ,
369387 table : Arc < dyn TableProvider > ,
370388 ) -> datafusion:: common:: Result < Option < Arc < dyn TableProvider > > > {
371- let py_table = PyTable :: new ( table) ;
389+ // Convert from trait type to our internal Send type
390+ let send_table = {
391+ let raw = Arc :: into_raw ( table) ;
392+ let send: * const ( dyn TableProvider + Send ) = raw as * const _ ;
393+ unsafe { Arc :: from_raw ( send) }
394+ } ;
395+
396+ let py_table = PyTable :: new ( send_table) ;
372397 Python :: with_gil ( |py| {
373398 let provider = self . schema_provider . bind ( py) ;
374399 let _ = provider
@@ -397,7 +422,14 @@ impl SchemaProvider for RustWrappedPySchemaProvider {
397422 // If we can turn this table provider into a `Dataset`, return it.
398423 // Otherwise, return None.
399424 let dataset = match Dataset :: new ( & table, py) {
400- Ok ( dataset) => Some ( Arc :: new ( dataset) as Arc < dyn TableProvider > ) ,
425+ Ok ( dataset) => {
426+ // Convert from our internal Send type to trait expected type
427+ let send_table = Arc :: new ( dataset) as Arc < dyn TableProvider + Send > ;
428+ let raw = Arc :: into_raw ( send_table) ;
429+ let wide: * const dyn TableProvider = raw as * const _ ;
430+ let arc = unsafe { Arc :: from_raw ( wide) } ;
431+ Some ( arc)
432+ }
401433 Err ( _) => None ,
402434 } ;
403435
0 commit comments