use std::fmt::Debug;
use std::sync::Arc;
use crate::expr::NullTreatment;
#[cfg(feature = "sql")]
use crate::logical_plan::LogicalPlan;
use crate::{
AggregateUDF, Expr, GetFieldAccess, ScalarUDF, SortExpr, TableSource, WindowFrame,
WindowFunctionDefinition, WindowUDF,
};
use arrow::datatypes::{DataType, Field, FieldRef, SchemaRef};
use datafusion_common::datatype::DataTypeExt;
use datafusion_common::{
DFSchema, Result, TableReference, config::ConfigOptions,
file_options::file_type::FileType, not_impl_err,
};
#[cfg(feature = "sql")]
use sqlparser::ast::{Expr as SQLExpr, Ident, ObjectName, TableAlias, TableFactor};
pub trait ContextProvider {
fn get_table_source(&self, name: TableReference) -> Result<Arc<dyn TableSource>>;
fn get_file_type(&self, _ext: &str) -> Result<Arc<dyn FileType>> {
not_impl_err!("Registered file types are not supported")
}
fn get_table_function_source(
&self,
_name: &str,
_args: Vec<Expr>,
) -> Result<Arc<dyn TableSource>> {
not_impl_err!("Table Functions are not supported")
}
fn create_cte_work_table(
&self,
_name: &str,
_schema: SchemaRef,
) -> Result<Arc<dyn TableSource>> {
not_impl_err!("Recursive CTE is not implemented")
}
fn get_expr_planners(&self) -> &[Arc<dyn ExprPlanner>] {
&[]
}
#[cfg(feature = "sql")]
fn get_relation_planners(&self) -> &[Arc<dyn RelationPlanner>] {
&[]
}
#[cfg(feature = "sql")]
fn get_type_planner(&self) -> Option<Arc<dyn TypePlanner>> {
None
}
fn get_function_meta(&self, name: &str) -> Option<Arc<ScalarUDF>>;
fn get_aggregate_meta(&self, name: &str) -> Option<Arc<AggregateUDF>>;
fn get_window_meta(&self, name: &str) -> Option<Arc<WindowUDF>>;
fn get_variable_type(&self, variable_names: &[String]) -> Option<DataType>;
fn get_variable_field(&self, variable_names: &[String]) -> Option<FieldRef> {
self.get_variable_type(variable_names)
.map(|data_type| data_type.into_nullable_field_ref())
}
fn options(&self) -> &ConfigOptions;
fn udf_names(&self) -> Vec<String>;
fn udaf_names(&self) -> Vec<String>;
fn udwf_names(&self) -> Vec<String>;
}
pub trait ExprPlanner: Debug + Send + Sync {
fn plan_binary_op(
&self,
expr: RawBinaryExpr,
_schema: &DFSchema,
) -> Result<PlannerResult<RawBinaryExpr>> {
Ok(PlannerResult::Original(expr))
}
fn plan_field_access(
&self,
expr: RawFieldAccessExpr,
_schema: &DFSchema,
) -> Result<PlannerResult<RawFieldAccessExpr>> {
Ok(PlannerResult::Original(expr))
}
fn plan_array_literal(
&self,
exprs: Vec<Expr>,
_schema: &DFSchema,
) -> Result<PlannerResult<Vec<Expr>>> {
Ok(PlannerResult::Original(exprs))
}
fn plan_position(&self, args: Vec<Expr>) -> Result<PlannerResult<Vec<Expr>>> {
Ok(PlannerResult::Original(args))
}
fn plan_dictionary_literal(
&self,
expr: RawDictionaryExpr,
_schema: &DFSchema,
) -> Result<PlannerResult<RawDictionaryExpr>> {
Ok(PlannerResult::Original(expr))
}
fn plan_extract(&self, args: Vec<Expr>) -> Result<PlannerResult<Vec<Expr>>> {
Ok(PlannerResult::Original(args))
}
fn plan_substring(&self, args: Vec<Expr>) -> Result<PlannerResult<Vec<Expr>>> {
Ok(PlannerResult::Original(args))
}
fn plan_struct_literal(
&self,
args: Vec<Expr>,
_is_named_struct: bool,
) -> Result<PlannerResult<Vec<Expr>>> {
Ok(PlannerResult::Original(args))
}
fn plan_overlay(&self, args: Vec<Expr>) -> Result<PlannerResult<Vec<Expr>>> {
Ok(PlannerResult::Original(args))
}
fn plan_make_map(&self, args: Vec<Expr>) -> Result<PlannerResult<Vec<Expr>>> {
Ok(PlannerResult::Original(args))
}
fn plan_compound_identifier(
&self,
_field: &Field,
_qualifier: Option<&TableReference>,
_nested_names: &[String],
) -> Result<PlannerResult<Vec<Expr>>> {
not_impl_err!(
"Default planner compound identifier hasn't been implemented for ExprPlanner"
)
}
fn plan_aggregate(
&self,
expr: RawAggregateExpr,
) -> Result<PlannerResult<RawAggregateExpr>> {
Ok(PlannerResult::Original(expr))
}
fn plan_window(&self, expr: RawWindowExpr) -> Result<PlannerResult<RawWindowExpr>> {
Ok(PlannerResult::Original(expr))
}
}
#[derive(Debug, Clone)]
pub struct RawBinaryExpr {
#[cfg(not(feature = "sql"))]
pub op: datafusion_expr_common::operator::Operator,
#[cfg(feature = "sql")]
pub op: sqlparser::ast::BinaryOperator,
pub left: Expr,
pub right: Expr,
}
#[derive(Debug, Clone)]
pub struct RawFieldAccessExpr {
pub field_access: GetFieldAccess,
pub expr: Expr,
}
#[derive(Debug, Clone)]
pub struct RawDictionaryExpr {
pub keys: Vec<Expr>,
pub values: Vec<Expr>,
}
#[derive(Debug, Clone)]
pub struct RawAggregateExpr {
pub func: Arc<AggregateUDF>,
pub args: Vec<Expr>,
pub distinct: bool,
pub filter: Option<Box<Expr>>,
pub order_by: Vec<SortExpr>,
pub null_treatment: Option<NullTreatment>,
}
#[derive(Debug, Clone)]
pub struct RawWindowExpr {
pub func_def: WindowFunctionDefinition,
pub args: Vec<Expr>,
pub partition_by: Vec<Expr>,
pub order_by: Vec<SortExpr>,
pub window_frame: WindowFrame,
pub filter: Option<Box<Expr>>,
pub null_treatment: Option<NullTreatment>,
pub distinct: bool,
}
#[derive(Debug, Clone)]
pub enum PlannerResult<T> {
Planned(Expr),
Original(T),
}
#[cfg(feature = "sql")]
#[derive(Debug, Clone)]
pub struct PlannedRelation {
pub plan: LogicalPlan,
pub alias: Option<TableAlias>,
}
#[cfg(feature = "sql")]
impl PlannedRelation {
pub fn new(plan: LogicalPlan, alias: Option<TableAlias>) -> Self {
Self { plan, alias }
}
}
#[cfg(feature = "sql")]
#[derive(Debug)]
pub enum RelationPlanning {
Planned(Box<PlannedRelation>),
Original(Box<TableFactor>),
}
#[cfg(feature = "sql")]
pub trait RelationPlanner: Debug + Send + Sync {
fn plan_relation(
&self,
relation: TableFactor,
context: &mut dyn RelationPlannerContext,
) -> Result<RelationPlanning>;
}
#[cfg(feature = "sql")]
pub trait RelationPlannerContext {
fn context_provider(&self) -> &dyn ContextProvider;
fn plan(&mut self, relation: TableFactor) -> Result<LogicalPlan>;
fn sql_to_expr(&mut self, expr: SQLExpr, schema: &DFSchema) -> Result<Expr>;
fn sql_expr_to_logical_expr(
&mut self,
expr: SQLExpr,
schema: &DFSchema,
) -> Result<Expr>;
fn normalize_ident(&self, ident: Ident) -> String;
fn object_name_to_table_reference(&self, name: ObjectName) -> Result<TableReference>;
}
#[cfg(feature = "sql")]
pub trait TypePlanner: Debug + Send + Sync {
fn plan_type(
&self,
_sql_type: &sqlparser::ast::DataType,
) -> Result<Option<DataType>> {
Ok(None)
}
}