pub trait ExtensionPlanner {
// Required method
fn plan_extension<'life0, 'life1, 'life2, 'life3, 'life4, 'life5, 'life6, 'async_trait>(
&'life0 self,
planner: &'life1 dyn PhysicalPlanner,
node: &'life2 dyn UserDefinedLogicalNode,
logical_inputs: &'life3 [&'life4 LogicalPlan],
physical_inputs: &'life5 [Arc<dyn ExecutionPlan>],
session_state: &'life6 SessionState,
) -> Pin<Box<dyn Future<Output = Result<Option<Arc<dyn ExecutionPlan>>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
'life5: 'async_trait,
'life6: 'async_trait;
// Provided method
fn plan_table_scan<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
_planner: &'life1 dyn PhysicalPlanner,
_scan: &'life2 TableScan,
_session_state: &'life3 SessionState,
) -> Pin<Box<dyn Future<Output = Result<Option<Arc<dyn ExecutionPlan>>>> + Send + 'async_trait>>
where Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait { ... }
}Expand description
This trait exposes the ability to plan an ExecutionPlan out of a LogicalPlan.
Required Methods§
Sourcefn plan_extension<'life0, 'life1, 'life2, 'life3, 'life4, 'life5, 'life6, 'async_trait>(
&'life0 self,
planner: &'life1 dyn PhysicalPlanner,
node: &'life2 dyn UserDefinedLogicalNode,
logical_inputs: &'life3 [&'life4 LogicalPlan],
physical_inputs: &'life5 [Arc<dyn ExecutionPlan>],
session_state: &'life6 SessionState,
) -> Pin<Box<dyn Future<Output = Result<Option<Arc<dyn ExecutionPlan>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
'life5: 'async_trait,
'life6: 'async_trait,
fn plan_extension<'life0, 'life1, 'life2, 'life3, 'life4, 'life5, 'life6, 'async_trait>(
&'life0 self,
planner: &'life1 dyn PhysicalPlanner,
node: &'life2 dyn UserDefinedLogicalNode,
logical_inputs: &'life3 [&'life4 LogicalPlan],
physical_inputs: &'life5 [Arc<dyn ExecutionPlan>],
session_state: &'life6 SessionState,
) -> Pin<Box<dyn Future<Output = Result<Option<Arc<dyn ExecutionPlan>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
'life5: 'async_trait,
'life6: 'async_trait,
Create a physical plan for a UserDefinedLogicalNode.
input_dfschema: the logical plan schema for the inputs to this node
Returns an error when the planner knows how to plan the concrete
implementation of node but errors while doing so.
Returns None when the planner does not know how to plan the
node and wants to delegate the planning to another
ExtensionPlanner.
Provided Methods§
Sourcefn plan_table_scan<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
_planner: &'life1 dyn PhysicalPlanner,
_scan: &'life2 TableScan,
_session_state: &'life3 SessionState,
) -> Pin<Box<dyn Future<Output = Result<Option<Arc<dyn ExecutionPlan>>>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn plan_table_scan<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
_planner: &'life1 dyn PhysicalPlanner,
_scan: &'life2 TableScan,
_session_state: &'life3 SessionState,
) -> Pin<Box<dyn Future<Output = Result<Option<Arc<dyn ExecutionPlan>>>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Create a physical plan for a LogicalPlan::TableScan.
This is useful for planning valid TableSources that are not TableProviders.
Returns:
Ok(Some(plan))if the planner knows how to plan thescanOk(None)if the planner does not know how to plan thescanand wants to delegate the planning to anotherExtensionPlannerErrif the planner knows how to plan thescanbut errors while doing so
§Example
ⓘ
use std::sync::Arc;
use datafusion::physical_plan::ExecutionPlan;
use datafusion::logical_expr::TableScan;
use datafusion::execution::context::SessionState;
use datafusion::error::Result;
use datafusion_physical_planner::{ExtensionPlanner, PhysicalPlanner};
use async_trait::async_trait;
// Your custom table source type
struct MyCustomTableSource { /* ... */ }
// Your custom execution plan
struct MyCustomExec { /* ... */ }
struct MyExtensionPlanner;
#[async_trait]
impl ExtensionPlanner for MyExtensionPlanner {
async fn plan_extension(
&self,
_planner: &dyn PhysicalPlanner,
_node: &dyn UserDefinedLogicalNode,
_logical_inputs: &[&LogicalPlan],
_physical_inputs: &[Arc<dyn ExecutionPlan>],
_session_state: &SessionState,
) -> Result<Option<Arc<dyn ExecutionPlan>>> {
Ok(None)
}
async fn plan_table_scan(
&self,
_planner: &dyn PhysicalPlanner,
scan: &TableScan,
_session_state: &SessionState,
) -> Result<Option<Arc<dyn ExecutionPlan>>> {
// Check if this is your custom table source
if scan.source.as_any().is::<MyCustomTableSource>() {
// Create a custom execution plan for your table source
let exec = MyCustomExec::new(
scan.table_name.clone(),
Arc::clone(scan.projected_schema.inner()),
);
Ok(Some(Arc::new(exec)))
} else {
// Return None to let other extension planners handle it
Ok(None)
}
}
}