From 38f1e573fe9e176582f0b03867439548e5fd9922 Mon Sep 17 00:00:00 2001 From: Seve Martinez <20816697+seve-martinez@users.noreply.github.com> Date: Mon, 21 Oct 2024 11:52:17 -0700 Subject: [PATCH] feat: adding Display implementation to DELETE and INSERT (#1427) Co-authored-by: Andrew Lamb --- src/ast/dml.rs | 115 +++++++++++++++++++++++++++++++++++++++- src/ast/mod.rs | 140 +++++-------------------------------------------- 2 files changed, 128 insertions(+), 127 deletions(-) diff --git a/src/ast/dml.rs b/src/ast/dml.rs index 8121f2c5b..2932fafb5 100644 --- a/src/ast/dml.rs +++ b/src/ast/dml.rs @@ -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")] @@ -492,6 +497,81 @@ pub struct Insert { pub insert_alias: Option, } +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))] @@ -512,3 +592,36 @@ pub struct Delete { /// LIMIT (MySQL) pub limit: Option, } + +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(()) + } +} diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 4900307e5..790a39bdb 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -2176,6 +2176,18 @@ pub enum FromTable { /// WithoutKeyword(Vec), } +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 @@ -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}"), @@ -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}")?;