@@ -52,7 +52,7 @@ pub struct PySchema {
5252#[ pyclass( name = "RawTable" , module = "datafusion.catalog" , subclass) ]
5353#[ derive( Clone ) ]
5454pub struct PyTable {
55- pub table : Arc < dyn TableProvider > ,
55+ pub table : Arc < dyn TableProvider + Send > ,
5656}
5757
5858impl From < Arc < dyn CatalogProvider > > for PyCatalog {
@@ -68,11 +68,11 @@ impl From<Arc<dyn SchemaProvider>> for PySchema {
6868}
6969
7070impl PyTable {
71- pub fn new ( table : Arc < dyn TableProvider > ) -> Self {
71+ pub fn new ( table : Arc < dyn TableProvider + Send > ) -> Self {
7272 Self { table }
7373 }
7474
75- pub fn table ( & self ) -> Arc < dyn TableProvider > {
75+ pub fn table ( & self ) -> Arc < dyn TableProvider + Send > {
7676 self . table . clone ( )
7777 }
7878}
@@ -206,7 +206,7 @@ impl PySchema {
206206
207207 let provider = unsafe { capsule. reference :: < FFI_TableProvider > ( ) } ;
208208 let provider: ForeignTableProvider = provider. into ( ) ;
209- Arc :: new ( provider) as Arc < dyn TableProvider >
209+ Arc :: new ( provider) as Arc < dyn TableProvider + Send >
210210 } else {
211211 match table_provider. extract :: < PyTable > ( ) {
212212 Ok ( py_table) => py_table. table ,
@@ -215,7 +215,7 @@ impl PySchema {
215215 Err ( _) => {
216216 let py = table_provider. py ( ) ;
217217 let provider = Dataset :: new ( & table_provider, py) ?;
218- Arc :: new ( provider) as Arc < dyn TableProvider >
218+ Arc :: new ( provider) as Arc < dyn TableProvider + Send >
219219 }
220220 } ,
221221 }
@@ -298,7 +298,7 @@ impl RustWrappedPySchemaProvider {
298298 }
299299 }
300300
301- fn table_inner ( & self , name : & str ) -> PyResult < Option < Arc < dyn TableProvider > > > {
301+ fn table_inner ( & self , name : & str ) -> PyResult < Option < Arc < dyn TableProvider + Send > > > {
302302 Python :: with_gil ( |py| {
303303 let provider = self . schema_provider . bind ( py) ;
304304 let py_table_method = provider. getattr ( "table" ) ?;
@@ -316,7 +316,7 @@ impl RustWrappedPySchemaProvider {
316316 let provider = unsafe { capsule. reference :: < FFI_TableProvider > ( ) } ;
317317 let provider: ForeignTableProvider = provider. into ( ) ;
318318
319- Ok ( Some ( Arc :: new ( provider) as Arc < dyn TableProvider > ) )
319+ Ok ( Some ( Arc :: new ( provider) as Arc < dyn TableProvider + Send > ) )
320320 } else {
321321 if let Ok ( inner_table) = py_table. getattr ( "table" ) {
322322 if let Ok ( inner_table) = inner_table. extract :: < PyTable > ( ) {
@@ -332,7 +332,7 @@ impl RustWrappedPySchemaProvider {
332332 Ok ( py_table) => Ok ( Some ( py_table. table ) ) ,
333333 Err ( _) => {
334334 let ds = Dataset :: new ( & py_table, py) . map_err ( py_datafusion_err) ?;
335- Ok ( Some ( Arc :: new ( ds) as Arc < dyn TableProvider > ) )
335+ Ok ( Some ( Arc :: new ( ds) as Arc < dyn TableProvider + Send > ) )
336336 }
337337 }
338338 }
@@ -368,15 +368,32 @@ impl SchemaProvider for RustWrappedPySchemaProvider {
368368 & self ,
369369 name : & str ,
370370 ) -> datafusion:: common:: Result < Option < Arc < dyn TableProvider > > , DataFusionError > {
371- 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+ }
372382 }
373383
374384 fn register_table (
375385 & self ,
376386 name : String ,
377387 table : Arc < dyn TableProvider > ,
378388 ) -> datafusion:: common:: Result < Option < Arc < dyn TableProvider > > > {
379- 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) ;
380397 Python :: with_gil ( |py| {
381398 let provider = self . schema_provider . bind ( py) ;
382399 let _ = provider
@@ -405,7 +422,14 @@ impl SchemaProvider for RustWrappedPySchemaProvider {
405422 // If we can turn this table provider into a `Dataset`, return it.
406423 // Otherwise, return None.
407424 let dataset = match Dataset :: new ( & table, py) {
408- 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+ }
409433 Err ( _) => None ,
410434 } ;
411435
0 commit comments