@@ -48,6 +48,7 @@ use datafusion_execution::{
48
48
use datafusion_expr:: {
49
49
dml:: InsertOp , Expr , SortExpr , TableProviderFilterPushDown , TableType ,
50
50
} ;
51
+ use datafusion_physical_expr:: schema_rewriter:: PhysicalExprAdapterFactory ;
51
52
use datafusion_physical_expr_common:: sort_expr:: LexOrdering ;
52
53
use datafusion_physical_plan:: { empty:: EmptyExec , ExecutionPlan , Statistics } ;
53
54
use futures:: { future, stream, Stream , StreamExt , TryStreamExt } ;
@@ -99,6 +100,8 @@ pub struct ListingTableConfig {
99
100
schema_source : SchemaSource ,
100
101
/// Optional [`SchemaAdapterFactory`] for creating schema adapters
101
102
schema_adapter_factory : Option < Arc < dyn SchemaAdapterFactory > > ,
103
+ /// Optional [`PhysicalExprAdapterFactory`] for creating physical expression adapters
104
+ physical_expr_adapter_factory : Option < Arc < dyn PhysicalExprAdapterFactory > > ,
102
105
}
103
106
104
107
impl ListingTableConfig {
@@ -281,6 +284,7 @@ impl ListingTableConfig {
281
284
options : Some ( listing_options) ,
282
285
schema_source : self . schema_source ,
283
286
schema_adapter_factory : self . schema_adapter_factory ,
287
+ physical_expr_adapter_factory : self . physical_expr_adapter_factory ,
284
288
} )
285
289
}
286
290
@@ -300,6 +304,7 @@ impl ListingTableConfig {
300
304
options : _,
301
305
schema_source,
302
306
schema_adapter_factory,
307
+ physical_expr_adapter_factory,
303
308
} = self ;
304
309
305
310
let ( schema, new_schema_source) = match file_schema {
@@ -322,6 +327,7 @@ impl ListingTableConfig {
322
327
options : Some ( options) ,
323
328
schema_source : new_schema_source,
324
329
schema_adapter_factory,
330
+ physical_expr_adapter_factory,
325
331
} )
326
332
}
327
333
None => internal_err ! ( "No `ListingOptions` set for inferring schema" ) ,
@@ -364,6 +370,7 @@ impl ListingTableConfig {
364
370
options : Some ( options) ,
365
371
schema_source : self . schema_source ,
366
372
schema_adapter_factory : self . schema_adapter_factory ,
373
+ physical_expr_adapter_factory : self . physical_expr_adapter_factory ,
367
374
} )
368
375
}
369
376
None => config_err ! ( "No `ListingOptions` set for inferring schema" ) ,
@@ -415,6 +422,26 @@ impl ListingTableConfig {
415
422
pub fn schema_adapter_factory ( & self ) -> Option < & Arc < dyn SchemaAdapterFactory > > {
416
423
self . schema_adapter_factory . as_ref ( )
417
424
}
425
+
426
+ /// Set the [`PhysicalExprAdapterFactory`] for the [`ListingTable`]
427
+ ///
428
+ /// The expression adapter factory is used to create physical expression adapters that can
429
+ /// handle schema evolution and type conversions when evaluating expressions
430
+ /// with different schemas than the table schema.
431
+ ///
432
+ /// If not provided, a default physical expression adapter factory will be used unless a custom
433
+ /// `SchemaAdapterFactory` is set, in which case only the `SchemaAdapterFactory` will be used.
434
+ ///
435
+ /// See <https://github.com/apache/datafusion/issues/16800> for details on this transition.
436
+ pub fn with_physical_expr_adapter_factory (
437
+ self ,
438
+ physical_expr_adapter_factory : Arc < dyn PhysicalExprAdapterFactory > ,
439
+ ) -> Self {
440
+ Self {
441
+ physical_expr_adapter_factory : Some ( physical_expr_adapter_factory) ,
442
+ ..self
443
+ }
444
+ }
418
445
}
419
446
420
447
/// Options for creating a [`ListingTable`]
@@ -911,6 +938,8 @@ pub struct ListingTable {
911
938
column_defaults : HashMap < String , Expr > ,
912
939
/// Optional [`SchemaAdapterFactory`] for creating schema adapters
913
940
schema_adapter_factory : Option < Arc < dyn SchemaAdapterFactory > > ,
941
+ /// Optional [`PhysicalExprAdapterFactory`] for creating physical expression adapters
942
+ expr_adapter_factory : Option < Arc < dyn PhysicalExprAdapterFactory > > ,
914
943
}
915
944
916
945
impl ListingTable {
@@ -952,6 +981,7 @@ impl ListingTable {
952
981
constraints : Constraints :: default ( ) ,
953
982
column_defaults : HashMap :: new ( ) ,
954
983
schema_adapter_factory : config. schema_adapter_factory ,
984
+ expr_adapter_factory : config. physical_expr_adapter_factory ,
955
985
} ;
956
986
957
987
Ok ( table)
@@ -1196,6 +1226,7 @@ impl TableProvider for ListingTable {
1196
1226
. with_limit ( limit)
1197
1227
. with_output_ordering ( output_ordering)
1198
1228
. with_table_partition_cols ( table_partition_cols)
1229
+ . with_expr_adapter ( self . expr_adapter_factory . clone ( ) )
1199
1230
. build ( ) ,
1200
1231
)
1201
1232
. await
@@ -1995,7 +2026,6 @@ mod tests {
1995
2026
#[ tokio:: test]
1996
2027
async fn test_insert_into_append_new_parquet_files_session_overrides ( ) -> Result < ( ) > {
1997
2028
let mut config_map: HashMap < String , String > = HashMap :: new ( ) ;
1998
- config_map. insert ( "datafusion.execution.batch_size" . into ( ) , "10" . into ( ) ) ;
1999
2029
config_map. insert (
2000
2030
"datafusion.execution.soft_max_rows_per_output_file" . into ( ) ,
2001
2031
"10" . into ( ) ,
@@ -2060,7 +2090,7 @@ mod tests {
2060
2090
"datafusion.execution.parquet.write_batch_size" . into ( ) ,
2061
2091
"5" . into ( ) ,
2062
2092
) ;
2063
- config_map. insert ( "datafusion.execution.batch_size" . into ( ) , "1 " . into ( ) ) ;
2093
+ config_map. insert ( "datafusion.execution.batch_size" . into ( ) , "10 " . into ( ) ) ;
2064
2094
helper_test_append_new_files_to_table (
2065
2095
ParquetFormat :: default ( ) . get_ext ( ) ,
2066
2096
FileCompressionType :: UNCOMPRESSED ,
0 commit comments