use std::collections::HashMap;
use std::sync::Arc;
use std::{
fmt::{self, Display},
hash::{Hash, Hasher},
};
use crate::{Expr, LogicalPlan, Volatility};
use arrow::datatypes::DataType;
use datafusion_common::parsers::CompressionTypeVariant;
use datafusion_common::{
Constraints, DFSchemaRef, OwnedSchemaReference, OwnedTableReference,
};
use sqlparser::ast::Ident;
#[derive(Clone, PartialEq, Eq, Hash)]
pub enum DdlStatement {
CreateExternalTable(CreateExternalTable),
CreateMemoryTable(CreateMemoryTable),
CreateView(CreateView),
CreateCatalogSchema(CreateCatalogSchema),
CreateCatalog(CreateCatalog),
DropTable(DropTable),
DropView(DropView),
DropCatalogSchema(DropCatalogSchema),
CreateFunction(CreateFunction),
DropFunction(DropFunction),
}
impl DdlStatement {
pub fn schema(&self) -> &DFSchemaRef {
match self {
DdlStatement::CreateExternalTable(CreateExternalTable { schema, .. }) => {
schema
}
DdlStatement::CreateMemoryTable(CreateMemoryTable { input, .. })
| DdlStatement::CreateView(CreateView { input, .. }) => input.schema(),
DdlStatement::CreateCatalogSchema(CreateCatalogSchema { schema, .. }) => {
schema
}
DdlStatement::CreateCatalog(CreateCatalog { schema, .. }) => schema,
DdlStatement::DropTable(DropTable { schema, .. }) => schema,
DdlStatement::DropView(DropView { schema, .. }) => schema,
DdlStatement::DropCatalogSchema(DropCatalogSchema { schema, .. }) => schema,
DdlStatement::CreateFunction(CreateFunction { schema, .. }) => schema,
DdlStatement::DropFunction(DropFunction { schema, .. }) => schema,
}
}
pub fn name(&self) -> &str {
match self {
DdlStatement::CreateExternalTable(_) => "CreateExternalTable",
DdlStatement::CreateMemoryTable(_) => "CreateMemoryTable",
DdlStatement::CreateView(_) => "CreateView",
DdlStatement::CreateCatalogSchema(_) => "CreateCatalogSchema",
DdlStatement::CreateCatalog(_) => "CreateCatalog",
DdlStatement::DropTable(_) => "DropTable",
DdlStatement::DropView(_) => "DropView",
DdlStatement::DropCatalogSchema(_) => "DropCatalogSchema",
DdlStatement::CreateFunction(_) => "CreateFunction",
DdlStatement::DropFunction(_) => "DropFunction",
}
}
pub fn inputs(&self) -> Vec<&LogicalPlan> {
match self {
DdlStatement::CreateExternalTable(_) => vec![],
DdlStatement::CreateCatalogSchema(_) => vec![],
DdlStatement::CreateCatalog(_) => vec![],
DdlStatement::CreateMemoryTable(CreateMemoryTable { input, .. }) => {
vec![input]
}
DdlStatement::CreateView(CreateView { input, .. }) => vec![input],
DdlStatement::DropTable(_) => vec![],
DdlStatement::DropView(_) => vec![],
DdlStatement::DropCatalogSchema(_) => vec![],
DdlStatement::CreateFunction(_) => vec![],
DdlStatement::DropFunction(_) => vec![],
}
}
pub fn display(&self) -> impl fmt::Display + '_ {
struct Wrapper<'a>(&'a DdlStatement);
impl<'a> Display for Wrapper<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
DdlStatement::CreateExternalTable(CreateExternalTable {
ref name,
constraints,
..
}) => {
write!(f, "CreateExternalTable: {name:?}{constraints}")
}
DdlStatement::CreateMemoryTable(CreateMemoryTable {
name,
constraints,
..
}) => {
write!(f, "CreateMemoryTable: {name:?}{constraints}")
}
DdlStatement::CreateView(CreateView { name, .. }) => {
write!(f, "CreateView: {name:?}")
}
DdlStatement::CreateCatalogSchema(CreateCatalogSchema {
schema_name,
..
}) => {
write!(f, "CreateCatalogSchema: {schema_name:?}")
}
DdlStatement::CreateCatalog(CreateCatalog {
catalog_name, ..
}) => {
write!(f, "CreateCatalog: {catalog_name:?}")
}
DdlStatement::DropTable(DropTable {
name, if_exists, ..
}) => {
write!(f, "DropTable: {name:?} if not exist:={if_exists}")
}
DdlStatement::DropView(DropView {
name, if_exists, ..
}) => {
write!(f, "DropView: {name:?} if not exist:={if_exists}")
}
DdlStatement::DropCatalogSchema(DropCatalogSchema {
name,
if_exists,
cascade,
..
}) => {
write!(f, "DropCatalogSchema: {name:?} if not exist:={if_exists} cascade:={cascade}")
}
DdlStatement::CreateFunction(CreateFunction { name, .. }) => {
write!(f, "CreateFunction: name {name:?}")
}
DdlStatement::DropFunction(DropFunction { name, .. }) => {
write!(f, "CreateFunction: name {name:?}")
}
}
}
}
Wrapper(self)
}
}
#[derive(Clone, PartialEq, Eq)]
pub struct CreateExternalTable {
pub schema: DFSchemaRef,
pub name: OwnedTableReference,
pub location: String,
pub file_type: String,
pub has_header: bool,
pub delimiter: char,
pub table_partition_cols: Vec<String>,
pub if_not_exists: bool,
pub definition: Option<String>,
pub order_exprs: Vec<Vec<Expr>>,
pub file_compression_type: CompressionTypeVariant,
pub unbounded: bool,
pub options: HashMap<String, String>,
pub constraints: Constraints,
pub column_defaults: HashMap<String, Expr>,
}
impl Hash for CreateExternalTable {
fn hash<H: Hasher>(&self, state: &mut H) {
self.schema.hash(state);
self.name.hash(state);
self.location.hash(state);
self.file_type.hash(state);
self.has_header.hash(state);
self.delimiter.hash(state);
self.table_partition_cols.hash(state);
self.if_not_exists.hash(state);
self.definition.hash(state);
self.file_compression_type.hash(state);
self.order_exprs.hash(state);
self.unbounded.hash(state);
self.options.len().hash(state); }
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct CreateMemoryTable {
pub name: OwnedTableReference,
pub constraints: Constraints,
pub input: Arc<LogicalPlan>,
pub if_not_exists: bool,
pub or_replace: bool,
pub column_defaults: Vec<(String, Expr)>,
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct CreateView {
pub name: OwnedTableReference,
pub input: Arc<LogicalPlan>,
pub or_replace: bool,
pub definition: Option<String>,
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct CreateCatalog {
pub catalog_name: String,
pub if_not_exists: bool,
pub schema: DFSchemaRef,
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct CreateCatalogSchema {
pub schema_name: String,
pub if_not_exists: bool,
pub schema: DFSchemaRef,
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct DropTable {
pub name: OwnedTableReference,
pub if_exists: bool,
pub schema: DFSchemaRef,
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct DropView {
pub name: OwnedTableReference,
pub if_exists: bool,
pub schema: DFSchemaRef,
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct DropCatalogSchema {
pub name: OwnedSchemaReference,
pub if_exists: bool,
pub cascade: bool,
pub schema: DFSchemaRef,
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct CreateFunction {
pub or_replace: bool,
pub temporary: bool,
pub name: String,
pub args: Option<Vec<OperateFunctionArg>>,
pub return_type: Option<DataType>,
pub params: CreateFunctionBody,
pub schema: DFSchemaRef,
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct OperateFunctionArg {
pub name: Option<Ident>,
pub data_type: DataType,
pub default_expr: Option<Expr>,
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct CreateFunctionBody {
pub language: Option<Ident>,
pub behavior: Option<Volatility>,
pub as_: Option<DefinitionStatement>,
pub return_: Option<Expr>,
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub enum DefinitionStatement {
SingleQuotedDef(String),
DoubleDollarDef(String),
}
impl From<sqlparser::ast::FunctionDefinition> for DefinitionStatement {
fn from(value: sqlparser::ast::FunctionDefinition) -> Self {
match value {
sqlparser::ast::FunctionDefinition::SingleQuotedDef(s) => {
Self::SingleQuotedDef(s)
}
sqlparser::ast::FunctionDefinition::DoubleDollarDef(s) => {
Self::DoubleDollarDef(s)
}
}
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct DropFunction {
pub name: String,
pub if_exists: bool,
pub schema: DFSchemaRef,
}