use std::fmt::{self, Display, Formatter};
use crate::postgres::general::{Condition, OutputExpression, TableName, WithClause};
use crate::tools::{joined, IntoIteratorOfSameType};
pub fn delete_from(table_name: impl Into<TableName>) -> DeleteFrom {
DeleteFrom::new(table_name.into(), None)
}
pub(crate) fn delete_from_with(table_name: TableName, with: WithClause) -> DeleteFrom {
DeleteFrom::new(table_name, Some(with))
}
#[must_use = "Making a DELETE FROM without using it is pointless"]
#[derive(Debug, Clone)]
pub struct DeleteFrom {
table_name: TableName,
with: Option<WithClause>,
where_: Vec<Condition>,
returning: Vec<OutputExpression>,
}
impl DeleteFrom {
fn new(table_name: TableName, with: Option<WithClause>) -> DeleteFrom {
DeleteFrom {
table_name,
with,
where_: Vec::new(),
returning: Vec::new(),
}
}
pub fn where_(mut self, conditions: impl IntoIteratorOfSameType<Condition>) -> Self {
self.where_.extend(conditions.into_some_iter());
self
}
pub fn returning(mut self, expressions: impl IntoIteratorOfSameType<OutputExpression>) -> Self {
self.returning.extend(expressions.into_some_iter());
self
}
}
impl Display for DeleteFrom {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if let Some(with_clause) = &self.with {
write!(f, "{} ", with_clause)?;
}
write!(f, "DELETE FROM {}", self.table_name,)?;
if !self.where_.is_empty() {
write!(f, " WHERE {}", joined(&self.where_, " AND "))?;
}
if !self.returning.is_empty() {
write!(f, " RETURNING {}", joined(&self.returning, ", "))?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::postgres::tools::tests::assert_correct_postgresql;
use crate::postgres::{delete_from, select, with};
#[test]
fn everything() {
let sql = delete_from("Dummy").to_string();
assert_correct_postgresql(&sql, "DELETE FROM Dummy");
}
#[test]
fn where_one() {
let sql = delete_from("Dummy").where_("x > 0").to_string();
assert_correct_postgresql(&sql, "DELETE FROM Dummy WHERE x > 0");
}
#[test]
fn where_many() {
let sql = delete_from("Dummy").where_(("x > 0", "y > 30")).to_string();
assert_correct_postgresql(&sql, "DELETE FROM Dummy WHERE x > 0 AND y > 30");
}
#[test]
fn where_chain() {
let sql = delete_from("Dummy")
.where_("x > 0")
.where_("y < 10")
.to_string();
assert_correct_postgresql(&sql, "DELETE FROM Dummy WHERE x > 0 AND y < 10");
}
#[test]
fn returning() {
let sql = delete_from("Dummy").returning("id").to_string();
assert_correct_postgresql(&sql, "DELETE FROM Dummy RETURNING id");
}
#[test]
fn returning_two() {
let sql = delete_from("Dummy").returning(("id", "place")).to_string();
assert_correct_postgresql(&sql, "DELETE FROM Dummy RETURNING id, place");
}
#[test]
fn cte() {
let sql = with("thing")
.as_(select("1 + 1"))
.delete_from("Dummy")
.to_string();
assert_correct_postgresql(&sql, "WITH thing AS (SELECT 1 + 1) DELETE FROM Dummy");
}
}