15
15
// specific language governing permissions and limitations
16
16
// under the License.
17
17
18
- use crate :: protobuf:: { LogicalExprNode , ProjectionColumns } ;
18
+ use crate :: protobuf:: { CustomTableScanNode , LogicalExprNode , ProjectionColumns } ;
19
19
use crate :: {
20
20
from_proto:: { self , parse_expr} ,
21
21
protobuf:: {
@@ -24,8 +24,7 @@ use crate::{
24
24
} ,
25
25
to_proto,
26
26
} ;
27
- use arrow:: datatypes:: Schema ;
28
- use datafusion:: datasource:: custom:: CustomTable ;
27
+ use arrow:: datatypes:: { Schema , SchemaRef } ;
29
28
use datafusion:: {
30
29
datasource:: {
31
30
file_format:: {
@@ -37,7 +36,7 @@ use datafusion::{
37
36
datasource:: { provider_as_source, source_as_provider} ,
38
37
prelude:: SessionContext ,
39
38
} ;
40
- use datafusion_common:: { Column , DataFusionError } ;
39
+ use datafusion_common:: { Column , context , DataFusionError } ;
41
40
use datafusion_expr:: {
42
41
logical_plan:: {
43
42
Aggregate , CreateCatalog , CreateCatalogSchema , CreateExternalTable , CreateView ,
@@ -50,6 +49,8 @@ use prost::bytes::BufMut;
50
49
use prost:: Message ;
51
50
use std:: fmt:: Debug ;
52
51
use std:: sync:: Arc ;
52
+ use datafusion:: datasource:: TableProvider ;
53
+ use crate :: protobuf:: logical_plan_node:: LogicalPlanType :: CustomScan ;
53
54
54
55
fn byte_to_string ( b : u8 ) -> Result < String , DataFusionError > {
55
56
let b = & [ b] ;
@@ -108,6 +109,19 @@ pub trait LogicalExtensionCodec: Debug + Send + Sync {
108
109
node : & Extension ,
109
110
buf : & mut Vec < u8 > ,
110
111
) -> Result < ( ) , DataFusionError > ;
112
+
113
+ fn try_decode_table_provider (
114
+ & self ,
115
+ buf : & [ u8 ] ,
116
+ schema : SchemaRef ,
117
+ ctx : & SessionContext ,
118
+ ) -> Result < Arc < dyn TableProvider > , DataFusionError > ;
119
+
120
+ fn try_encode_table_provider (
121
+ & self ,
122
+ node : Arc < dyn TableProvider > ,
123
+ buf : & mut Vec < u8 > ,
124
+ ) -> Result < ( ) , DataFusionError > ;
111
125
}
112
126
113
127
#[ derive( Debug , Clone ) ]
@@ -134,6 +148,18 @@ impl LogicalExtensionCodec for DefaultLogicalExtensionCodec {
134
148
"LogicalExtensionCodec is not provided" . to_string ( ) ,
135
149
) )
136
150
}
151
+
152
+ fn try_decode_table_provider ( & self , _buf : & [ u8 ] , _schema : SchemaRef , _ctx : & SessionContext ) -> Result < Arc < dyn TableProvider > , DataFusionError > {
153
+ Err ( DataFusionError :: NotImplemented (
154
+ "LogicalExtensionCodec is not provided" . to_string ( ) ,
155
+ ) )
156
+ }
157
+
158
+ fn try_encode_table_provider ( & self , _node : Arc < dyn TableProvider > , _buf : & mut Vec < u8 > ) -> Result < ( ) , DataFusionError > {
159
+ Err ( DataFusionError :: NotImplemented (
160
+ "LogicalExtensionCodec is not provided" . to_string ( ) ,
161
+ ) )
162
+ }
137
163
}
138
164
139
165
#[ macro_export]
@@ -414,6 +440,7 @@ impl AsLogicalPlan for LogicalPlanNode {
414
440
}
415
441
LogicalPlanType :: CustomScan ( scan) => {
416
442
let schema: Schema = convert_required ! ( scan. schema) ?;
443
+ let schema = Arc :: new ( schema) ;
417
444
let mut projection = None ;
418
445
if let Some ( columns) = & scan. projection {
419
446
let column_indices = columns
@@ -429,22 +456,7 @@ impl AsLogicalPlan for LogicalPlanNode {
429
456
. iter ( )
430
457
. map ( |expr| parse_expr ( expr, ctx) )
431
458
. 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
- ) ?;
459
+ let provider = extension_codec. try_decode_table_provider ( & scan. custom_table_data , schema, ctx) ?;
448
460
449
461
LogicalPlanBuilder :: scan_with_filters (
450
462
& scan. table_name ,
@@ -780,8 +792,8 @@ impl AsLogicalPlan for LogicalPlanNode {
780
792
projection,
781
793
..
782
794
} ) => {
783
- let source = source_as_provider ( source) ?;
784
- let schema = source . schema ( ) ;
795
+ let provider = source_as_provider ( source) ?;
796
+ let schema = provider . schema ( ) ;
785
797
let source = source. as_any ( ) ;
786
798
787
799
let projection = match projection {
@@ -811,14 +823,6 @@ impl AsLogicalPlan for LogicalPlanNode {
811
823
filters,
812
824
listing_table,
813
825
)
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
- )
822
826
} else if let Some ( view_table) = source. downcast_ref :: < ViewTable > ( ) {
823
827
Ok ( protobuf:: LogicalPlanNode {
824
828
logical_plan_type : Some ( LogicalPlanType :: ViewScan ( Box :: new (
@@ -840,11 +844,20 @@ impl AsLogicalPlan for LogicalPlanNode {
840
844
) ) ) ,
841
845
} )
842
846
} else {
843
- Err ( DataFusionError :: Internal ( format ! (
844
- "logical plan to_proto unsupported table provider {:?} {}" ,
845
- source,
846
- plan. display_indent( )
847
- ) ) )
847
+ let mut bytes = vec ! [ ] ;
848
+ extension_codec. try_encode_table_provider ( provider, & mut bytes)
849
+ . map_err ( |e| context ! ( "Error serializing custom table" , e) ) ?;
850
+ let scan = CustomScan ( CustomTableScanNode {
851
+ table_name : table_name. clone ( ) ,
852
+ projection,
853
+ schema : Some ( schema) ,
854
+ filters,
855
+ custom_table_data : bytes
856
+ } ) ;
857
+ let node = LogicalPlanNode {
858
+ logical_plan_type : Some ( scan)
859
+ } ;
860
+ Ok ( node)
848
861
}
849
862
}
850
863
LogicalPlan :: Projection ( Projection {
@@ -1266,27 +1279,6 @@ impl AsLogicalPlan for LogicalPlanNode {
1266
1279
}
1267
1280
1268
1281
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
1282
fn serialize_listing_table (
1291
1283
table_name : & String ,
1292
1284
projection : Option < ProjectionColumns > ,
0 commit comments