use std::any::Any;
use std::fmt::Debug;
use std::sync::Arc;
use async_trait::async_trait;
use datafusion_common::{DFSchema, Result, not_impl_err};
use datafusion_expr::physical_planning_context::PhysicalPlanningContext;
use datafusion_expr::{Expr, LogicalPlan, TableScan, UserDefinedLogicalNode};
use datafusion_physical_plan::{ExecutionPlan, PhysicalExpr};
use crate::Session;
#[async_trait]
pub trait QueryPlanner: Any + Debug {
async fn create_physical_plan(
&self,
logical_plan: &LogicalPlan,
session: &dyn Session,
) -> Result<Arc<dyn ExecutionPlan>>;
}
#[derive(Debug, Default)]
pub struct UnsupportedQueryPlanner;
#[async_trait]
impl QueryPlanner for UnsupportedQueryPlanner {
async fn create_physical_plan(
&self,
_logical_plan: &LogicalPlan,
_session: &dyn Session,
) -> Result<Arc<dyn ExecutionPlan>> {
not_impl_err!("This session does not expose its query planner")
}
}
#[async_trait]
pub trait PhysicalPlanner: Send + Sync {
async fn create_physical_plan(
&self,
logical_plan: &LogicalPlan,
session: &dyn Session,
) -> Result<Arc<dyn ExecutionPlan>>;
fn create_physical_expr(
&self,
expr: &Expr,
input_dfschema: &DFSchema,
session: &dyn Session,
planning_ctx: &PhysicalPlanningContext,
) -> Result<Arc<dyn PhysicalExpr>>;
}
#[async_trait]
pub trait ExtensionPlanner {
async fn plan_extension(
&self,
planner: &dyn PhysicalPlanner,
node: &dyn UserDefinedLogicalNode,
logical_inputs: &[&LogicalPlan],
physical_inputs: &[Arc<dyn ExecutionPlan>],
session: &dyn Session,
planning_ctx: &PhysicalPlanningContext,
) -> Result<Option<Arc<dyn ExecutionPlan>>>;
async fn plan_table_scan(
&self,
_planner: &dyn PhysicalPlanner,
_scan: &TableScan,
_session: &dyn Session,
_planning_ctx: &PhysicalPlanningContext,
) -> Result<Option<Arc<dyn ExecutionPlan>>> {
Ok(None)
}
}