#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, string::ToString, vec::Vec};
use core::fmt;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use super::FormatEncodeOptions;
use crate::ast::{
display_comma_separated, display_separated, DataType, Expr, Ident, ObjectName, SetVariableValue,
};
use crate::tokenizer::Token;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AlterDatabaseOperation {
ChangeOwner { new_owner_name: Ident },
RenameDatabase { database_name: ObjectName },
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AlterSchemaOperation {
ChangeOwner { new_owner_name: Ident },
RenameSchema { schema_name: ObjectName },
SwapRenameSchema { target_schema: ObjectName },
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AlterTableOperation {
AddConstraint(TableConstraint),
AddColumn {
column_def: ColumnDef,
},
DropConstraint {
name: Ident,
},
DropColumn {
column_name: Ident,
if_exists: bool,
cascade: bool,
},
RenameColumn {
old_column_name: Ident,
new_column_name: Ident,
},
RenameTable {
table_name: ObjectName,
},
ChangeColumn {
old_name: Ident,
new_name: Ident,
data_type: DataType,
options: Vec<ColumnOption>,
},
RenameConstraint {
old_name: Ident,
new_name: Ident,
},
AlterColumn {
column_name: Ident,
op: AlterColumnOperation,
},
ChangeOwner {
new_owner_name: Ident,
},
SetSchema {
new_schema_name: ObjectName,
},
SetParallelism {
parallelism: SetVariableValue,
deferred: bool,
},
RefreshSchema,
SetSourceRateLimit {
rate_limit: i32,
},
SetBackfillRateLimit {
rate_limit: i32,
},
SwapRenameTable {
target_table: ObjectName,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AlterIndexOperation {
RenameIndex {
index_name: ObjectName,
},
SetParallelism {
parallelism: SetVariableValue,
deferred: bool,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AlterViewOperation {
RenameView {
view_name: ObjectName,
},
ChangeOwner {
new_owner_name: Ident,
},
SetSchema {
new_schema_name: ObjectName,
},
SetParallelism {
parallelism: SetVariableValue,
deferred: bool,
},
SetBackfillRateLimit {
rate_limit: i32,
},
SwapRenameView {
target_view: ObjectName,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AlterSinkOperation {
RenameSink {
sink_name: ObjectName,
},
ChangeOwner {
new_owner_name: Ident,
},
SetSchema {
new_schema_name: ObjectName,
},
SetParallelism {
parallelism: SetVariableValue,
deferred: bool,
},
SwapRenameSink {
target_sink: ObjectName,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AlterSubscriptionOperation {
RenameSubscription { subscription_name: ObjectName },
ChangeOwner { new_owner_name: Ident },
SetSchema { new_schema_name: ObjectName },
SwapRenameSubscription { target_subscription: ObjectName },
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AlterSourceOperation {
RenameSource { source_name: ObjectName },
AddColumn { column_def: ColumnDef },
ChangeOwner { new_owner_name: Ident },
SetSchema { new_schema_name: ObjectName },
FormatEncode { format_encode: FormatEncodeOptions },
RefreshSchema,
SetSourceRateLimit { rate_limit: i32 },
SwapRenameSource { target_source: ObjectName },
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AlterFunctionOperation {
SetSchema { new_schema_name: ObjectName },
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AlterConnectionOperation {
SetSchema { new_schema_name: ObjectName },
}
impl fmt::Display for AlterDatabaseOperation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AlterDatabaseOperation::ChangeOwner { new_owner_name } => {
write!(f, "OWNER TO {}", new_owner_name)
}
AlterDatabaseOperation::RenameDatabase { database_name } => {
write!(f, "RENAME TO {}", database_name)
}
}
}
}
impl fmt::Display for AlterSchemaOperation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AlterSchemaOperation::ChangeOwner { new_owner_name } => {
write!(f, "OWNER TO {}", new_owner_name)
}
AlterSchemaOperation::RenameSchema { schema_name } => {
write!(f, "RENAME TO {}", schema_name)
}
AlterSchemaOperation::SwapRenameSchema { target_schema } => {
write!(f, "SWAP WITH {}", target_schema)
}
}
}
}
impl fmt::Display for AlterTableOperation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AlterTableOperation::AddConstraint(c) => write!(f, "ADD {}", c),
AlterTableOperation::AddColumn { column_def } => {
write!(f, "ADD COLUMN {}", column_def)
}
AlterTableOperation::AlterColumn { column_name, op } => {
write!(f, "ALTER COLUMN {} {}", column_name, op)
}
AlterTableOperation::DropConstraint { name } => write!(f, "DROP CONSTRAINT {}", name),
AlterTableOperation::DropColumn {
column_name,
if_exists,
cascade,
} => write!(
f,
"DROP COLUMN {}{}{}",
if *if_exists { "IF EXISTS " } else { "" },
column_name,
if *cascade { " CASCADE" } else { "" }
),
AlterTableOperation::RenameColumn {
old_column_name,
new_column_name,
} => write!(
f,
"RENAME COLUMN {} TO {}",
old_column_name, new_column_name
),
AlterTableOperation::RenameTable { table_name } => {
write!(f, "RENAME TO {}", table_name)
}
AlterTableOperation::ChangeColumn {
old_name,
new_name,
data_type,
options,
} => {
write!(f, "CHANGE COLUMN {} {} {}", old_name, new_name, data_type)?;
if options.is_empty() {
Ok(())
} else {
write!(f, " {}", display_separated(options, " "))
}
}
AlterTableOperation::RenameConstraint { old_name, new_name } => {
write!(f, "RENAME CONSTRAINT {} TO {}", old_name, new_name)
}
AlterTableOperation::ChangeOwner { new_owner_name } => {
write!(f, "OWNER TO {}", new_owner_name)
}
AlterTableOperation::SetSchema { new_schema_name } => {
write!(f, "SET SCHEMA {}", new_schema_name)
}
AlterTableOperation::SetParallelism {
parallelism,
deferred,
} => {
write!(
f,
"SET PARALLELISM TO {} {}",
parallelism,
if *deferred { " DEFERRED" } else { "" }
)
}
AlterTableOperation::RefreshSchema => {
write!(f, "REFRESH SCHEMA")
}
AlterTableOperation::SetSourceRateLimit { rate_limit } => {
write!(f, "SET SOURCE_RATE_LIMIT TO {}", rate_limit)
}
AlterTableOperation::SetBackfillRateLimit { rate_limit } => {
write!(f, "SET BACKFILL_RATE_LIMIT TO {}", rate_limit)
}
AlterTableOperation::SwapRenameTable { target_table } => {
write!(f, "SWAP WITH {}", target_table)
}
}
}
}
impl fmt::Display for AlterIndexOperation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AlterIndexOperation::RenameIndex { index_name } => {
write!(f, "RENAME TO {index_name}")
}
AlterIndexOperation::SetParallelism {
parallelism,
deferred,
} => {
write!(
f,
"SET PARALLELISM TO {} {}",
parallelism,
if *deferred { " DEFERRED" } else { "" }
)
}
}
}
}
impl fmt::Display for AlterViewOperation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AlterViewOperation::RenameView { view_name } => {
write!(f, "RENAME TO {view_name}")
}
AlterViewOperation::ChangeOwner { new_owner_name } => {
write!(f, "OWNER TO {}", new_owner_name)
}
AlterViewOperation::SetSchema { new_schema_name } => {
write!(f, "SET SCHEMA {}", new_schema_name)
}
AlterViewOperation::SetParallelism {
parallelism,
deferred,
} => {
write!(
f,
"SET PARALLELISM TO {} {}",
parallelism,
if *deferred { " DEFERRED" } else { "" }
)
}
AlterViewOperation::SetBackfillRateLimit { rate_limit } => {
write!(f, "SET BACKFILL_RATE_LIMIT TO {}", rate_limit)
}
AlterViewOperation::SwapRenameView { target_view } => {
write!(f, "SWAP WITH {}", target_view)
}
}
}
}
impl fmt::Display for AlterSinkOperation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AlterSinkOperation::RenameSink { sink_name } => {
write!(f, "RENAME TO {sink_name}")
}
AlterSinkOperation::ChangeOwner { new_owner_name } => {
write!(f, "OWNER TO {}", new_owner_name)
}
AlterSinkOperation::SetSchema { new_schema_name } => {
write!(f, "SET SCHEMA {}", new_schema_name)
}
AlterSinkOperation::SetParallelism {
parallelism,
deferred,
} => {
write!(
f,
"SET PARALLELISM TO {} {}",
parallelism,
if *deferred { " DEFERRED" } else { "" }
)
}
AlterSinkOperation::SwapRenameSink { target_sink } => {
write!(f, "SWAP WITH {}", target_sink)
}
}
}
}
impl fmt::Display for AlterSubscriptionOperation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AlterSubscriptionOperation::RenameSubscription { subscription_name } => {
write!(f, "RENAME TO {subscription_name}")
}
AlterSubscriptionOperation::ChangeOwner { new_owner_name } => {
write!(f, "OWNER TO {}", new_owner_name)
}
AlterSubscriptionOperation::SetSchema { new_schema_name } => {
write!(f, "SET SCHEMA {}", new_schema_name)
}
AlterSubscriptionOperation::SwapRenameSubscription {
target_subscription,
} => {
write!(f, "SWAP WITH {}", target_subscription)
}
}
}
}
impl fmt::Display for AlterSourceOperation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AlterSourceOperation::RenameSource { source_name } => {
write!(f, "RENAME TO {source_name}")
}
AlterSourceOperation::AddColumn { column_def } => {
write!(f, "ADD COLUMN {column_def}")
}
AlterSourceOperation::ChangeOwner { new_owner_name } => {
write!(f, "OWNER TO {}", new_owner_name)
}
AlterSourceOperation::SetSchema { new_schema_name } => {
write!(f, "SET SCHEMA {}", new_schema_name)
}
AlterSourceOperation::FormatEncode { format_encode } => {
write!(f, "{format_encode}")
}
AlterSourceOperation::RefreshSchema => {
write!(f, "REFRESH SCHEMA")
}
AlterSourceOperation::SetSourceRateLimit { rate_limit } => {
write!(f, "SET SOURCE_RATE_LIMIT TO {}", rate_limit)
}
AlterSourceOperation::SwapRenameSource { target_source } => {
write!(f, "SWAP WITH {}", target_source)
}
}
}
}
impl fmt::Display for AlterFunctionOperation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AlterFunctionOperation::SetSchema { new_schema_name } => {
write!(f, "SET SCHEMA {new_schema_name}")
}
}
}
}
impl fmt::Display for AlterConnectionOperation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AlterConnectionOperation::SetSchema { new_schema_name } => {
write!(f, "SET SCHEMA {new_schema_name}")
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AlterColumnOperation {
SetNotNull,
DropNotNull,
SetDefault { value: Expr },
DropDefault,
SetDataType {
data_type: DataType,
using: Option<Expr>,
},
}
impl fmt::Display for AlterColumnOperation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AlterColumnOperation::SetNotNull => write!(f, "SET NOT NULL",),
AlterColumnOperation::DropNotNull => write!(f, "DROP NOT NULL",),
AlterColumnOperation::SetDefault { value } => {
write!(f, "SET DEFAULT {}", value)
}
AlterColumnOperation::DropDefault {} => {
write!(f, "DROP DEFAULT")
}
AlterColumnOperation::SetDataType { data_type, using } => {
if let Some(expr) = using {
write!(f, "SET DATA TYPE {} USING {}", data_type, expr)
} else {
write!(f, "SET DATA TYPE {}", data_type)
}
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SourceWatermark {
pub column: Ident,
pub expr: Expr,
}
impl fmt::Display for SourceWatermark {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "WATERMARK FOR {} AS {}", self.column, self.expr,)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum TableConstraint {
Unique {
name: Option<Ident>,
columns: Vec<Ident>,
is_primary: bool,
},
ForeignKey {
name: Option<Ident>,
columns: Vec<Ident>,
foreign_table: ObjectName,
referred_columns: Vec<Ident>,
on_delete: Option<ReferentialAction>,
on_update: Option<ReferentialAction>,
},
Check {
name: Option<Ident>,
expr: Box<Expr>,
},
}
impl fmt::Display for TableConstraint {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TableConstraint::Unique {
name,
columns,
is_primary,
} => write!(
f,
"{}{} ({})",
display_constraint_name(name),
if *is_primary { "PRIMARY KEY" } else { "UNIQUE" },
display_comma_separated(columns)
),
TableConstraint::ForeignKey {
name,
columns,
foreign_table,
referred_columns,
on_delete,
on_update,
} => {
write!(
f,
"{}FOREIGN KEY ({}) REFERENCES {}({})",
display_constraint_name(name),
display_comma_separated(columns),
foreign_table,
display_comma_separated(referred_columns),
)?;
if let Some(action) = on_delete {
write!(f, " ON DELETE {}", action)?;
}
if let Some(action) = on_update {
write!(f, " ON UPDATE {}", action)?;
}
Ok(())
}
TableConstraint::Check { name, expr } => {
write!(f, "{}CHECK ({})", display_constraint_name(name), expr)
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ColumnDef {
pub name: Ident,
pub data_type: Option<DataType>,
pub collation: Option<ObjectName>,
pub options: Vec<ColumnOptionDef>,
}
impl ColumnDef {
pub fn new(
name: Ident,
data_type: DataType,
collation: Option<ObjectName>,
options: Vec<ColumnOptionDef>,
) -> Self {
ColumnDef {
name,
data_type: Some(data_type),
collation,
options,
}
}
pub fn is_generated(&self) -> bool {
self.options
.iter()
.any(|option| matches!(option.option, ColumnOption::GeneratedColumns(_)))
}
}
impl fmt::Display for ColumnDef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{} {}",
self.name,
if let Some(data_type) = &self.data_type {
data_type.to_string()
} else {
"None".to_string()
}
)?;
for option in &self.options {
write!(f, " {}", option)?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ColumnOptionDef {
pub name: Option<Ident>,
pub option: ColumnOption,
}
impl fmt::Display for ColumnOptionDef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}{}", display_constraint_name(&self.name), self.option)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum ColumnOption {
Null,
NotNull,
DefaultColumns(Expr),
Unique { is_primary: bool },
ForeignKey {
foreign_table: ObjectName,
referred_columns: Vec<Ident>,
on_delete: Option<ReferentialAction>,
on_update: Option<ReferentialAction>,
},
Check(Expr),
DialectSpecific(Vec<Token>),
GeneratedColumns(Expr),
}
impl fmt::Display for ColumnOption {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use ColumnOption::*;
match self {
Null => write!(f, "NULL"),
NotNull => write!(f, "NOT NULL"),
DefaultColumns(expr) => write!(f, "DEFAULT {}", expr),
Unique { is_primary } => {
write!(f, "{}", if *is_primary { "PRIMARY KEY" } else { "UNIQUE" })
}
ForeignKey {
foreign_table,
referred_columns,
on_delete,
on_update,
} => {
write!(f, "REFERENCES {}", foreign_table)?;
if !referred_columns.is_empty() {
write!(f, " ({})", display_comma_separated(referred_columns))?;
}
if let Some(action) = on_delete {
write!(f, " ON DELETE {}", action)?;
}
if let Some(action) = on_update {
write!(f, " ON UPDATE {}", action)?;
}
Ok(())
}
Check(expr) => write!(f, "CHECK ({})", expr),
DialectSpecific(val) => write!(f, "{}", display_separated(val, " ")),
GeneratedColumns(expr) => write!(f, "AS {}", expr),
}
}
}
fn display_constraint_name(name: &'_ Option<Ident>) -> impl fmt::Display + '_ {
struct ConstraintName<'a>(&'a Option<Ident>);
impl fmt::Display for ConstraintName<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(name) = self.0 {
write!(f, "CONSTRAINT {} ", name)?;
}
Ok(())
}
}
ConstraintName(name)
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum ReferentialAction {
Restrict,
Cascade,
SetNull,
NoAction,
SetDefault,
}
impl fmt::Display for ReferentialAction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
ReferentialAction::Restrict => "RESTRICT",
ReferentialAction::Cascade => "CASCADE",
ReferentialAction::SetNull => "SET NULL",
ReferentialAction::NoAction => "NO ACTION",
ReferentialAction::SetDefault => "SET DEFAULT",
})
}
}