use derive_more::From;
use std::fmt;
use std::fmt::{Display, Formatter};
use crate::sql::expression::identifier::SimpleIdentifier;
use crate::sql::expression::literal::ColumnReference;
use crate::sql::expression::SQLExpression;
use crate::sql::query::TableReference;
use crate::types::struct_type::Struct;
use crate::write_utils::{maybe_newline, maybe_pad, newline_or_space, Indent};
use super::SQLQuery;
#[derive(Debug, Clone, From, PartialEq, Eq)]
pub enum DML {
Insert(Insert),
Merge(Merge),
}
impl DML {
pub fn fmt_indented(&self, f: &mut Formatter<'_>, indentation: Indent) -> fmt::Result {
match self {
DML::Insert(insert) => insert.fmt_indented(f, indentation),
DML::Merge(merge) => merge.fmt_indented(f, indentation),
}
}
}
impl Display for DML {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.fmt_indented(f, Indent::default())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Insert {
pub table: TableReference,
pub schema: Struct,
pub query: SQLQuery,
}
impl Insert {
pub fn fmt_indented(&self, f: &mut Formatter<'_>, indentation: Indent) -> fmt::Result {
write!(f, "INSERT INTO ")?;
write!(f, "{} (", self.table)?;
for (i, si) in self.schema.keys().enumerate() {
let sql_si: SimpleIdentifier = si.clone().into();
sql_si.fmt_indented(f, Indent::default())?;
if i != self.schema.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, ")")?;
newline_or_space(f, indentation)?;
self.query.fmt_indented(f, indentation)
}
}
impl Display for Insert {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.fmt_indented(f, Indent::default())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Merge {
pub table_alias: SimpleIdentifier,
pub query_alias: SimpleIdentifier,
pub table: TableReference,
pub search_condition: SQLExpression,
pub when_clauses: Vec<MergeWhenClause>,
pub query: SQLQuery,
}
impl Merge {
pub fn fmt_indented(&self, f: &mut Formatter<'_>, indentation: Indent) -> fmt::Result {
write!(f, "MERGE INTO ")?;
write!(f, "{} AS {}", self.table, self.table_alias.to_string())?;
newline_or_space(f, indentation)?;
write!(f, "USING (")?;
maybe_newline(f, indentation)?;
self.query.fmt_indented(f, indentation)?;
maybe_newline(f, indentation)?;
write!(f, ") AS {}", self.query_alias.to_string())?;
newline_or_space(f, indentation)?;
write!(f, "ON ")?;
self.search_condition.fmt_indented(f, indentation)?;
newline_or_space(f, indentation)?;
let clause_count = self.when_clauses.len();
for (i, mc) in self.when_clauses.iter().enumerate() {
mc.fmt_indented(f, indentation)?;
if i < clause_count - 1 {
newline_or_space(f, indentation)?;
} else {
maybe_newline(f, indentation)?;
}
}
Ok(())
}
}
impl Display for Merge {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.fmt_indented(f, Indent::default())
}
}
#[derive(Debug, Clone, From, PartialEq, Eq)]
pub enum MergeWhenClause {
Matched(MergeWhenMatched),
NotMatched(MergeWhenNotMatched),
}
impl MergeWhenClause {
pub fn fmt_indented(&self, f: &mut Formatter<'_>, indentation: Indent) -> fmt::Result {
match self {
MergeWhenClause::Matched(when_matched) => when_matched.fmt_indented(f, indentation),
MergeWhenClause::NotMatched(when_not_matched) => {
when_not_matched.fmt_indented(f, indentation)
}
}
}
}
impl Display for MergeWhenClause {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.fmt_indented(f, Indent::default())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MergeWhenMatched {
then: MergeAction,
}
impl MergeWhenMatched {
pub fn fmt_indented(&self, f: &mut Formatter<'_>, indentation: Indent) -> fmt::Result {
write!(f, "WHEN MATCHED")?;
newline_or_space(f, indentation)?;
maybe_pad(f, indentation.nested())?;
write!(f, "THEN ")?;
self.then.fmt_indented(f, indentation)
}
}
impl Display for MergeWhenMatched {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.fmt_indented(f, Indent::default())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MergeWhenNotMatched {
then: MergeAction,
}
impl MergeWhenNotMatched {
pub fn new(then: MergeAction) -> Self {
Self { then }
}
pub fn fmt_indented(&self, f: &mut Formatter<'_>, indentation: Indent) -> fmt::Result {
write!(f, "WHEN NOT MATCHED")?;
newline_or_space(f, indentation)?;
maybe_pad(f, indentation.nested())?;
write!(f, "THEN ")?;
self.then.fmt_indented(f, indentation)
}
}
impl Display for MergeWhenNotMatched {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.fmt_indented(f, Indent::default())
}
}
#[derive(Debug, Clone, From, PartialEq, Eq)]
pub enum MergeAction {
Delete,
Insert(MergeInsert),
Update(MergeUpdate),
}
impl MergeAction {
pub fn fmt_indented(&self, f: &mut Formatter<'_>, indentation: Indent) -> fmt::Result {
match self {
MergeAction::Delete => write!(f, "DELETE"),
MergeAction::Insert(insert) => insert.fmt_indented(f, indentation),
MergeAction::Update(update) => update.fmt_indented(f, indentation),
}
}
}
impl Display for MergeAction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.fmt_indented(f, Indent::default())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MergeInsert {
columns: Vec<ColumnReference>,
}
impl MergeInsert {
pub fn new(columns: Vec<ColumnReference>) -> Self {
Self { columns }
}
pub fn fmt_indented(&self, f: &mut Formatter<'_>, indentation: Indent) -> fmt::Result {
write!(f, "INSERT (")?;
let column_length = self.columns.len();
for (i, c) in self.columns.iter().enumerate() {
c.fmt_indented(f, indentation)?;
if i != column_length - 1 {
write!(f, ", ")?;
}
}
write!(f, ") VALUES (")?;
for (i, c) in self.columns.iter().enumerate() {
c.prefixed_with("source").fmt_indented(f, indentation)?;
if i != column_length - 1 {
write!(f, ", ")?;
}
}
write!(f, ")")
}
}
impl Display for MergeInsert {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.fmt_indented(f, Indent::default())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MergeUpdate {
columns: Vec<ColumnReference>,
}
impl MergeUpdate {
pub fn fmt_indented(&self, f: &mut Formatter<'_>, indentation: Indent) -> fmt::Result {
write!(f, "UPDATE SET (")?;
newline_or_space(f, indentation)?;
for (i, c) in self.columns.iter().enumerate() {
maybe_pad(f, indentation)?;
if i > 0 {
write!(f, ", ")?;
}
c.fmt_indented(f, indentation.nested())?;
write!(f, " = ",)?;
c.prefixed_with("source")
.fmt_indented(f, indentation.nested())?;
}
write!(f, ")")
}
}
impl Display for MergeUpdate {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.fmt_indented(f, Indent::default())
}
}