use std::sync::Arc;
use datafusion::arrow::datatypes::SchemaRef;
use datafusion::execution::context::SessionContext;
use datafusion::optimizer::OptimizerRule;
use datafusion::physical_optimizer::PhysicalOptimizerRule;
use datafusion::physical_plan::ExecutionPlan;
use crate::errors::FnError;
#[non_exhaustive]
pub struct PlannerArgs<'a> {
pub session_ctx: &'a SessionContext,
pub input_plans: &'a [Arc<dyn ExecutionPlan>],
pub config_json: &'a str,
pub schema_hint: Option<SchemaRef>,
}
impl std::fmt::Debug for PlannerArgs<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PlannerArgs")
.field("session_ctx", &"<SessionContext>")
.field("input_plans.len", &self.input_plans.len())
.field("config_json", &self.config_json)
.field("schema_hint", &self.schema_hint)
.finish()
}
}
pub trait OperatorProvider: Send + Sync {
fn logical_name(&self) -> &str;
fn plan(&self, args: PlannerArgs<'_>) -> Result<Arc<dyn ExecutionPlan>, FnError>;
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum OptimizerPhase {
Logical,
Physical,
Both,
}
pub trait OptimizerRuleProvider: Send + Sync {
fn rule(&self) -> Arc<dyn OptimizerRule + Send + Sync> {
Arc::new(NoopOptimizerRule)
}
fn physical_rule(&self) -> Option<Arc<dyn PhysicalOptimizerRule + Send + Sync>> {
None
}
fn phase(&self) -> OptimizerPhase;
fn precedence(&self) -> i32 {
0
}
}
#[derive(Debug, Default)]
pub struct NoopOptimizerRule;
impl OptimizerRule for NoopOptimizerRule {
fn name(&self) -> &str {
"uni_noop_optimizer_rule"
}
fn apply_order(&self) -> Option<datafusion::optimizer::ApplyOrder> {
Some(datafusion::optimizer::ApplyOrder::BottomUp)
}
fn rewrite(
&self,
plan: datafusion::logical_expr::LogicalPlan,
_config: &dyn datafusion::optimizer::OptimizerConfig,
) -> Result<
datafusion::common::tree_node::Transformed<datafusion::logical_expr::LogicalPlan>,
datafusion::error::DataFusionError,
> {
Ok(datafusion::common::tree_node::Transformed::no(plan))
}
}