use arrow::datatypes::FieldRef;
use datafusion_common::metadata::format_type_and_metadata;
use datafusion_common::{DFSchema, DFSchemaRef};
use itertools::Itertools as _;
use std::fmt::{self, Display};
use std::sync::{Arc, LazyLock};
use crate::{Expr, LogicalPlan, expr_vec_fmt};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
pub enum Statement {
TransactionStart(TransactionStart),
TransactionEnd(TransactionEnd),
SetVariable(SetVariable),
ResetVariable(ResetVariable),
Prepare(Prepare),
Execute(Execute),
Deallocate(Deallocate),
}
impl Statement {
pub fn schema(&self) -> &DFSchemaRef {
static STATEMENT_EMPTY_SCHEMA: LazyLock<DFSchemaRef> =
LazyLock::new(|| Arc::new(DFSchema::empty()));
&STATEMENT_EMPTY_SCHEMA
}
pub fn name(&self) -> &str {
match self {
Statement::TransactionStart(_) => "TransactionStart",
Statement::TransactionEnd(_) => "TransactionEnd",
Statement::SetVariable(_) => "SetVariable",
Statement::ResetVariable(_) => "ResetVariable",
Statement::Prepare(_) => "Prepare",
Statement::Execute(_) => "Execute",
Statement::Deallocate(_) => "Deallocate",
}
}
pub(super) fn inputs(&self) -> Vec<&LogicalPlan> {
match self {
Statement::Prepare(Prepare { input, .. }) => vec![input.as_ref()],
_ => vec![],
}
}
pub fn display(&self) -> impl Display + '_ {
struct Wrapper<'a>(&'a Statement);
impl Display for Wrapper<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
Statement::TransactionStart(TransactionStart {
access_mode,
isolation_level,
..
}) => {
write!(f, "TransactionStart: {access_mode:?} {isolation_level:?}")
}
Statement::TransactionEnd(TransactionEnd {
conclusion,
chain,
..
}) => {
write!(f, "TransactionEnd: {conclusion:?} chain:={chain}")
}
Statement::SetVariable(SetVariable {
variable, value, ..
}) => {
write!(f, "SetVariable: set {variable:?} to {value:?}")
}
Statement::ResetVariable(ResetVariable { variable }) => {
write!(f, "ResetVariable: reset {variable:?}")
}
Statement::Prepare(Prepare { name, fields, .. }) => {
write!(
f,
"Prepare: {name:?} [{}]",
fields
.iter()
.map(|f| format_type_and_metadata(
f.data_type(),
Some(f.metadata())
))
.join(", ")
)
}
Statement::Execute(Execute {
name, parameters, ..
}) => {
write!(
f,
"Execute: {} params=[{}]",
name,
expr_vec_fmt!(parameters)
)
}
Statement::Deallocate(Deallocate { name }) => {
write!(f, "Deallocate: {name}")
}
}
}
}
Wrapper(self)
}
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
pub enum TransactionConclusion {
Commit,
Rollback,
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
pub enum TransactionAccessMode {
ReadOnly,
ReadWrite,
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
pub enum TransactionIsolationLevel {
ReadUncommitted,
ReadCommitted,
RepeatableRead,
Serializable,
Snapshot,
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Hash)]
pub struct TransactionStart {
pub access_mode: TransactionAccessMode,
pub isolation_level: TransactionIsolationLevel,
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Hash)]
pub struct TransactionEnd {
pub conclusion: TransactionConclusion,
pub chain: bool,
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Hash)]
pub struct SetVariable {
pub variable: String,
pub value: String,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
pub struct ResetVariable {
pub variable: String,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
pub struct Prepare {
pub name: String,
pub fields: Vec<FieldRef>,
pub input: Arc<LogicalPlan>,
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Hash)]
pub struct Execute {
pub name: String,
pub parameters: Vec<Expr>,
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Hash)]
pub struct Deallocate {
pub name: String,
}