Skip to content

Commit

Permalink
feat: adding Display implementation to DELETE and INSERT (#1427)
Browse files Browse the repository at this point in the history
Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
  • Loading branch information
seve-martinez and alamb authored Oct 21, 2024
1 parent a8432b5 commit 38f1e57
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 127 deletions.
115 changes: 114 additions & 1 deletion src/ast/dml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@
// under the License.

#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, string::String, vec::Vec};
use alloc::{
boxed::Box,
format,
string::{String, ToString},
vec::Vec,
};

use core::fmt::{self, Display};
#[cfg(feature = "serde")]
Expand Down Expand Up @@ -492,6 +497,81 @@ pub struct Insert {
pub insert_alias: Option<InsertAliases>,
}

impl Display for Insert {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let table_name = if let Some(alias) = &self.table_alias {
format!("{0} AS {alias}", self.table_name)
} else {
self.table_name.to_string()
};

if let Some(action) = self.or {
write!(f, "INSERT OR {action} INTO {table_name} ")?;
} else {
write!(
f,
"{start}",
start = if self.replace_into {
"REPLACE"
} else {
"INSERT"
},
)?;
if let Some(priority) = self.priority {
write!(f, " {priority}",)?;
}

write!(
f,
"{ignore}{over}{int}{tbl} {table_name} ",
table_name = table_name,
ignore = if self.ignore { " IGNORE" } else { "" },
over = if self.overwrite { " OVERWRITE" } else { "" },
int = if self.into { " INTO" } else { "" },
tbl = if self.table { " TABLE" } else { "" },
)?;
}
if !self.columns.is_empty() {
write!(f, "({}) ", display_comma_separated(&self.columns))?;
}
if let Some(ref parts) = self.partitioned {
if !parts.is_empty() {
write!(f, "PARTITION ({}) ", display_comma_separated(parts))?;
}
}
if !self.after_columns.is_empty() {
write!(f, "({}) ", display_comma_separated(&self.after_columns))?;
}

if let Some(source) = &self.source {
write!(f, "{source}")?;
}

if self.source.is_none() && self.columns.is_empty() {
write!(f, "DEFAULT VALUES")?;
}

if let Some(insert_alias) = &self.insert_alias {
write!(f, " AS {0}", insert_alias.row_alias)?;

if let Some(col_aliases) = &insert_alias.col_aliases {
if !col_aliases.is_empty() {
write!(f, " ({})", display_comma_separated(col_aliases))?;
}
}
}

if let Some(on) = &self.on {
write!(f, "{on}")?;
}

if let Some(returning) = &self.returning {
write!(f, " RETURNING {}", display_comma_separated(returning))?;
}
Ok(())
}
}

/// DELETE statement.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
Expand All @@ -512,3 +592,36 @@ pub struct Delete {
/// LIMIT (MySQL)
pub limit: Option<Expr>,
}

impl Display for Delete {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "DELETE ")?;
if !self.tables.is_empty() {
write!(f, "{} ", display_comma_separated(&self.tables))?;
}
match &self.from {
FromTable::WithFromKeyword(from) => {
write!(f, "FROM {}", display_comma_separated(from))?;
}
FromTable::WithoutKeyword(from) => {
write!(f, "{}", display_comma_separated(from))?;
}
}
if let Some(using) = &self.using {
write!(f, " USING {}", display_comma_separated(using))?;
}
if let Some(selection) = &self.selection {
write!(f, " WHERE {selection}")?;
}
if let Some(returning) = &self.returning {
write!(f, " RETURNING {}", display_comma_separated(returning))?;
}
if !self.order_by.is_empty() {
write!(f, " ORDER BY {}", display_comma_separated(&self.order_by))?;
}
if let Some(limit) = &self.limit {
write!(f, " LIMIT {limit}")?;
}
Ok(())
}
}
140 changes: 14 additions & 126 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2176,6 +2176,18 @@ pub enum FromTable {
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
WithoutKeyword(Vec<TableWithJoins>),
}
impl Display for FromTable {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FromTable::WithFromKeyword(tables) => {
write!(f, "FROM {}", display_comma_separated(tables))
}
FromTable::WithoutKeyword(tables) => {
write!(f, "{}", display_comma_separated(tables))
}
}
}
}

/// Policy type for a `CREATE POLICY` statement.
/// ```sql
Expand Down Expand Up @@ -3533,93 +3545,7 @@ impl fmt::Display for Statement {
}
Ok(())
}
Statement::Insert(insert) => {
let Insert {
or,
ignore,
into,
table_name,
table_alias,
overwrite,
partitioned,
columns,
after_columns,
source,
table,
on,
returning,
replace_into,
priority,
insert_alias,
} = insert;
let table_name = if let Some(alias) = table_alias {
format!("{table_name} AS {alias}")
} else {
table_name.to_string()
};

if let Some(action) = or {
write!(f, "INSERT OR {action} INTO {table_name} ")?;
} else {
write!(
f,
"{start}",
start = if *replace_into { "REPLACE" } else { "INSERT" },
)?;
if let Some(priority) = priority {
write!(f, " {priority}",)?;
}

write!(
f,
"{ignore}{over}{int}{tbl} {table_name} ",
table_name = table_name,
ignore = if *ignore { " IGNORE" } else { "" },
over = if *overwrite { " OVERWRITE" } else { "" },
int = if *into { " INTO" } else { "" },
tbl = if *table { " TABLE" } else { "" },
)?;
}
if !columns.is_empty() {
write!(f, "({}) ", display_comma_separated(columns))?;
}
if let Some(ref parts) = partitioned {
if !parts.is_empty() {
write!(f, "PARTITION ({}) ", display_comma_separated(parts))?;
}
}
if !after_columns.is_empty() {
write!(f, "({}) ", display_comma_separated(after_columns))?;
}

if let Some(source) = source {
write!(f, "{source}")?;
}

if source.is_none() && columns.is_empty() {
write!(f, "DEFAULT VALUES")?;
}

if let Some(insert_alias) = insert_alias {
write!(f, " AS {0}", insert_alias.row_alias)?;

if let Some(col_aliases) = &insert_alias.col_aliases {
if !col_aliases.is_empty() {
write!(f, " ({})", display_comma_separated(col_aliases))?;
}
}
}

if let Some(on) = on {
write!(f, "{on}")?;
}

if let Some(returning) = returning {
write!(f, " RETURNING {}", display_comma_separated(returning))?;
}

Ok(())
}
Statement::Insert(insert) => write!(f, "{insert}"),
Statement::Install {
extension_name: name,
} => write!(f, "INSTALL {name}"),
Expand Down Expand Up @@ -3696,45 +3622,7 @@ impl fmt::Display for Statement {
}
Ok(())
}
Statement::Delete(delete) => {
let Delete {
tables,
from,
using,
selection,
returning,
order_by,
limit,
} = delete;
write!(f, "DELETE ")?;
if !tables.is_empty() {
write!(f, "{} ", display_comma_separated(tables))?;
}
match from {
FromTable::WithFromKeyword(from) => {
write!(f, "FROM {}", display_comma_separated(from))?;
}
FromTable::WithoutKeyword(from) => {
write!(f, "{}", display_comma_separated(from))?;
}
}
if let Some(using) = using {
write!(f, " USING {}", display_comma_separated(using))?;
}
if let Some(selection) = selection {
write!(f, " WHERE {selection}")?;
}
if let Some(returning) = returning {
write!(f, " RETURNING {}", display_comma_separated(returning))?;
}
if !order_by.is_empty() {
write!(f, " ORDER BY {}", display_comma_separated(order_by))?;
}
if let Some(limit) = limit {
write!(f, " LIMIT {limit}")?;
}
Ok(())
}
Statement::Delete(delete) => write!(f, "{delete}"),
Statement::Close { cursor } => {
write!(f, "CLOSE {cursor}")?;

Expand Down

0 comments on commit 38f1e57

Please sign in to comment.