15
15
// specific language governing permissions and limitations
16
16
// under the License.
17
17
18
+ use crate :: protobuf:: { LogicalExprNode , ProjectionColumns } ;
18
19
use crate :: {
19
20
from_proto:: { self , parse_expr} ,
20
21
protobuf:: {
@@ -24,6 +25,7 @@ use crate::{
24
25
to_proto,
25
26
} ;
26
27
use arrow:: datatypes:: Schema ;
28
+ use datafusion:: datasource:: custom:: CustomTable ;
27
29
use datafusion:: {
28
30
datasource:: {
29
31
file_format:: {
@@ -410,6 +412,48 @@ impl AsLogicalPlan for LogicalPlanNode {
410
412
) ?
411
413
. build ( )
412
414
}
415
+ LogicalPlanType :: CustomScan ( scan) => {
416
+ let schema: Schema = convert_required ! ( scan. schema) ?;
417
+ let mut projection = None ;
418
+ if let Some ( columns) = & scan. projection {
419
+ let column_indices = columns
420
+ . columns
421
+ . iter ( )
422
+ . map ( |name| schema. index_of ( name) )
423
+ . collect :: < Result < Vec < usize > , _ > > ( ) ?;
424
+ projection = Some ( column_indices) ;
425
+ }
426
+
427
+ let filters = scan
428
+ . filters
429
+ . iter ( )
430
+ . map ( |expr| parse_expr ( expr, ctx) )
431
+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
432
+ let state = ctx. state . read ( ) ;
433
+ let factory = state
434
+ . runtime_env
435
+ . table_factories
436
+ . get ( & scan. table_type )
437
+ . ok_or_else ( || {
438
+ DataFusionError :: Plan ( format ! (
439
+ "Planner unable to find factory for {}" ,
440
+ scan. table_type
441
+ ) )
442
+ } ) ?;
443
+ let provider = ( * factory) . with_schema (
444
+ Arc :: new ( schema) ,
445
+ scan. table_type . as_str ( ) ,
446
+ scan. path . as_str ( ) ,
447
+ ) ?;
448
+
449
+ LogicalPlanBuilder :: scan_with_filters (
450
+ & scan. table_name ,
451
+ provider_as_source ( provider) ,
452
+ projection,
453
+ filters,
454
+ ) ?
455
+ . build ( )
456
+ }
413
457
LogicalPlanType :: Sort ( sort) => {
414
458
let input: LogicalPlan =
415
459
into_logical_plan ! ( sort. input, ctx, extension_codec) ?;
@@ -760,55 +804,21 @@ impl AsLogicalPlan for LogicalPlanNode {
760
804
. collect :: < Result < Vec < _ > , _ > > ( ) ?;
761
805
762
806
if let Some ( listing_table) = source. downcast_ref :: < ListingTable > ( ) {
763
- let any = listing_table. options ( ) . format . as_any ( ) ;
764
- let file_format_type = if let Some ( parquet) =
765
- any. downcast_ref :: < ParquetFormat > ( )
766
- {
767
- FileFormatType :: Parquet ( protobuf:: ParquetFormat {
768
- enable_pruning : parquet. enable_pruning ( ) ,
769
- } )
770
- } else if let Some ( csv) = any. downcast_ref :: < CsvFormat > ( ) {
771
- FileFormatType :: Csv ( protobuf:: CsvFormat {
772
- delimiter : byte_to_string ( csv. delimiter ( ) ) ?,
773
- has_header : csv. has_header ( ) ,
774
- } )
775
- } else if any. is :: < AvroFormat > ( ) {
776
- FileFormatType :: Avro ( protobuf:: AvroFormat { } )
777
- } else {
778
- return Err ( proto_error ( format ! (
779
- "Error converting file format, {:?} is invalid as a datafusion foramt." ,
780
- listing_table. options( ) . format
781
- ) ) ) ;
782
- } ;
783
- Ok ( protobuf:: LogicalPlanNode {
784
- logical_plan_type : Some ( LogicalPlanType :: ListingScan (
785
- protobuf:: ListingTableScanNode {
786
- file_format_type : Some ( file_format_type) ,
787
- table_name : table_name. to_owned ( ) ,
788
- collect_stat : listing_table. options ( ) . collect_stat ,
789
- file_extension : listing_table
790
- . options ( )
791
- . file_extension
792
- . clone ( ) ,
793
- table_partition_cols : listing_table
794
- . options ( )
795
- . table_partition_cols
796
- . clone ( ) ,
797
- paths : listing_table
798
- . table_paths ( )
799
- . iter ( )
800
- . map ( |x| x. to_string ( ) )
801
- . collect ( ) ,
802
- schema : Some ( schema) ,
803
- projection,
804
- filters,
805
- target_partitions : listing_table
806
- . options ( )
807
- . target_partitions
808
- as u32 ,
809
- } ,
810
- ) ) ,
811
- } )
807
+ Self :: serialize_listing_table (
808
+ table_name,
809
+ projection,
810
+ schema,
811
+ filters,
812
+ listing_table,
813
+ )
814
+ } else if let Some ( custom_table) = source. downcast_ref :: < CustomTable > ( ) {
815
+ Self :: serialize_custom_table (
816
+ table_name,
817
+ projection,
818
+ schema,
819
+ filters,
820
+ custom_table,
821
+ )
812
822
} else if let Some ( view_table) = source. downcast_ref :: < ViewTable > ( ) {
813
823
Ok ( protobuf:: LogicalPlanNode {
814
824
logical_plan_type : Some ( LogicalPlanType :: ViewScan ( Box :: new (
@@ -831,8 +841,9 @@ impl AsLogicalPlan for LogicalPlanNode {
831
841
} )
832
842
} else {
833
843
Err ( DataFusionError :: Internal ( format ! (
834
- "logical plan to_proto unsupported table provider {:?}" ,
835
- source
844
+ "logical plan to_proto unsupported table provider {:?} {}" ,
845
+ source,
846
+ plan. display_indent( )
836
847
) ) )
837
848
}
838
849
}
@@ -1253,3 +1264,77 @@ impl AsLogicalPlan for LogicalPlanNode {
1253
1264
}
1254
1265
}
1255
1266
}
1267
+
1268
+ impl LogicalPlanNode {
1269
+ fn serialize_custom_table (
1270
+ table_name : & String ,
1271
+ projection : Option < ProjectionColumns > ,
1272
+ schema : protobuf:: Schema ,
1273
+ filters : Vec < LogicalExprNode > ,
1274
+ custom_table : & CustomTable ,
1275
+ ) -> Result < LogicalPlanNode , DataFusionError > {
1276
+ Ok ( protobuf:: LogicalPlanNode {
1277
+ logical_plan_type : Some ( LogicalPlanType :: CustomScan (
1278
+ protobuf:: CustomTableScanNode {
1279
+ table_name : table_name. to_owned ( ) ,
1280
+ table_type : custom_table. get_table_type ( ) ,
1281
+ path : custom_table. get_path ( ) ,
1282
+ schema : Some ( schema) ,
1283
+ projection,
1284
+ filters,
1285
+ } ,
1286
+ ) ) ,
1287
+ } )
1288
+ }
1289
+
1290
+ fn serialize_listing_table (
1291
+ table_name : & String ,
1292
+ projection : Option < ProjectionColumns > ,
1293
+ schema : protobuf:: Schema ,
1294
+ filters : Vec < LogicalExprNode > ,
1295
+ listing_table : & ListingTable ,
1296
+ ) -> Result < LogicalPlanNode , DataFusionError > {
1297
+ let any = listing_table. options ( ) . format . as_any ( ) ;
1298
+ let file_format_type = if let Some ( parquet) = any. downcast_ref :: < ParquetFormat > ( )
1299
+ {
1300
+ FileFormatType :: Parquet ( protobuf:: ParquetFormat {
1301
+ enable_pruning : parquet. enable_pruning ( ) ,
1302
+ } )
1303
+ } else if let Some ( csv) = any. downcast_ref :: < CsvFormat > ( ) {
1304
+ FileFormatType :: Csv ( protobuf:: CsvFormat {
1305
+ delimiter : byte_to_string ( csv. delimiter ( ) ) ?,
1306
+ has_header : csv. has_header ( ) ,
1307
+ } )
1308
+ } else if any. is :: < AvroFormat > ( ) {
1309
+ FileFormatType :: Avro ( protobuf:: AvroFormat { } )
1310
+ } else {
1311
+ return Err ( proto_error ( format ! (
1312
+ "Error converting file format, {:?} is invalid as a datafusion foramt." ,
1313
+ listing_table. options( ) . format
1314
+ ) ) ) ;
1315
+ } ;
1316
+ Ok ( protobuf:: LogicalPlanNode {
1317
+ logical_plan_type : Some ( LogicalPlanType :: ListingScan (
1318
+ protobuf:: ListingTableScanNode {
1319
+ file_format_type : Some ( file_format_type) ,
1320
+ table_name : table_name. to_owned ( ) ,
1321
+ collect_stat : listing_table. options ( ) . collect_stat ,
1322
+ file_extension : listing_table. options ( ) . file_extension . clone ( ) ,
1323
+ table_partition_cols : listing_table
1324
+ . options ( )
1325
+ . table_partition_cols
1326
+ . clone ( ) ,
1327
+ paths : listing_table
1328
+ . table_paths ( )
1329
+ . iter ( )
1330
+ . map ( |x| x. to_string ( ) )
1331
+ . collect ( ) ,
1332
+ schema : Some ( schema) ,
1333
+ projection,
1334
+ filters,
1335
+ target_partitions : listing_table. options ( ) . target_partitions as u32 ,
1336
+ } ,
1337
+ ) ) ,
1338
+ } )
1339
+ }
1340
+ }
0 commit comments