Skip to content

implement fmt::Display instead of ToString #124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 38 additions & 31 deletions src/ast/data_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// limitations under the License.

use super::ObjectName;
use std::fmt;

/// SQL data types
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -65,47 +66,53 @@ pub enum DataType {
Array(Box<DataType>),
}

impl ToString for DataType {
fn to_string(&self) -> String {
impl fmt::Display for DataType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
DataType::Char(size) => format_type_with_optional_length("char", size),
DataType::Varchar(size) => format_type_with_optional_length("character varying", size),
DataType::Uuid => "uuid".to_string(),
DataType::Clob(size) => format!("clob({})", size),
DataType::Binary(size) => format!("binary({})", size),
DataType::Varbinary(size) => format!("varbinary({})", size),
DataType::Blob(size) => format!("blob({})", size),
DataType::Char(size) => format_type_with_optional_length(f, "char", size),
DataType::Varchar(size) => {
format_type_with_optional_length(f, "character varying", size)
}
DataType::Uuid => write!(f, "uuid"),
DataType::Clob(size) => write!(f, "clob({})", size),
DataType::Binary(size) => write!(f, "binary({})", size),
DataType::Varbinary(size) => write!(f, "varbinary({})", size),
DataType::Blob(size) => write!(f, "blob({})", size),
DataType::Decimal(precision, scale) => {
if let Some(scale) = scale {
format!("numeric({},{})", precision.unwrap(), scale)
write!(f, "numeric({},{})", precision.unwrap(), scale)
} else {
format_type_with_optional_length("numeric", precision)
format_type_with_optional_length(f, "numeric", precision)
}
}
DataType::Float(size) => format_type_with_optional_length("float", size),
DataType::SmallInt => "smallint".to_string(),
DataType::Int => "int".to_string(),
DataType::BigInt => "bigint".to_string(),
DataType::Real => "real".to_string(),
DataType::Double => "double".to_string(),
DataType::Boolean => "boolean".to_string(),
DataType::Date => "date".to_string(),
DataType::Time => "time".to_string(),
DataType::Timestamp => "timestamp".to_string(),
DataType::Interval => "interval".to_string(),
DataType::Regclass => "regclass".to_string(),
DataType::Text => "text".to_string(),
DataType::Bytea => "bytea".to_string(),
DataType::Array(ty) => format!("{}[]", ty.to_string()),
DataType::Custom(ty) => ty.to_string(),
DataType::Float(size) => format_type_with_optional_length(f, "float", size),
DataType::SmallInt => write!(f, "smallint"),
DataType::Int => write!(f, "int"),
DataType::BigInt => write!(f, "bigint"),
DataType::Real => write!(f, "real"),
DataType::Double => write!(f, "double"),
DataType::Boolean => write!(f, "boolean"),
DataType::Date => write!(f, "date"),
DataType::Time => write!(f, "time"),
DataType::Timestamp => write!(f, "timestamp"),
DataType::Interval => write!(f, "interval"),
DataType::Regclass => write!(f, "regclass"),
DataType::Text => write!(f, "text"),
DataType::Bytea => write!(f, "bytea"),
DataType::Array(ty) => write!(f, "{}[]", ty),
DataType::Custom(ty) => write!(f, "{}", ty),
}
}
}

fn format_type_with_optional_length(sql_type: &str, len: &Option<u64>) -> String {
let mut s = sql_type.to_string();
fn format_type_with_optional_length(
f: &mut fmt::Formatter,
sql_type: &'static str,
len: &Option<u64>,
) -> fmt::Result {
write!(f, "{}", sql_type)?;
if let Some(len) = len {
s += &format!("({})", len);
write!(f, "({})", len)?;
}
s
Ok(())
}
110 changes: 53 additions & 57 deletions src/ast/ddl.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! AST types specific to CREATE/ALTER variants of `SQLStatement`
//! (commonly referred to as Data Definition Language, or DDL)
use super::{DataType, Expr, Ident, ObjectName};
use super::{display_comma_separated, DataType, Expr, Ident, ObjectName};
use std::fmt;

/// An `ALTER TABLE` (`SQLStatement::SQLAlterTable`) operation
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
Expand All @@ -11,11 +12,11 @@ pub enum AlterTableOperation {
DropConstraint { name: Ident },
}

impl ToString for AlterTableOperation {
fn to_string(&self) -> String {
impl fmt::Display for AlterTableOperation {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
AlterTableOperation::AddConstraint(c) => format!("ADD {}", c.to_string()),
AlterTableOperation::DropConstraint { name } => format!("DROP CONSTRAINT {}", name),
AlterTableOperation::AddConstraint(c) => write!(f, "ADD {}", c),
AlterTableOperation::DropConstraint { name } => write!(f, "DROP CONSTRAINT {}", name),
}
}
}
Expand Down Expand Up @@ -46,36 +47,36 @@ pub enum TableConstraint {
},
}

impl ToString for TableConstraint {
fn to_string(&self) -> String {
impl fmt::Display for TableConstraint {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
TableConstraint::Unique {
name,
columns,
is_primary,
} => format!(
} => write!(
f,
"{}{} ({})",
format_constraint_name(name),
display_constraint_name(name),
if *is_primary { "PRIMARY KEY" } else { "UNIQUE" },
columns.join(", ")
display_comma_separated(columns)
),
TableConstraint::ForeignKey {
name,
columns,
foreign_table,
referred_columns,
} => format!(
} => write!(
f,
"{}FOREIGN KEY ({}) REFERENCES {}({})",
format_constraint_name(name),
columns.join(", "),
foreign_table.to_string(),
referred_columns.join(", ")
),
TableConstraint::Check { name, expr } => format!(
"{}CHECK ({})",
format_constraint_name(name),
expr.to_string()
display_constraint_name(name),
display_comma_separated(columns),
foreign_table,
display_comma_separated(referred_columns)
),
TableConstraint::Check { name, expr } => {
write!(f, "{}CHECK ({})", display_constraint_name(name), expr)
}
}
}
}
Expand All @@ -89,18 +90,13 @@ pub struct ColumnDef {
pub options: Vec<ColumnOptionDef>,
}

impl ToString for ColumnDef {
fn to_string(&self) -> String {
format!(
"{} {}{}",
self.name,
self.data_type.to_string(),
self.options
.iter()
.map(|c| format!(" {}", c.to_string()))
.collect::<Vec<_>>()
.join("")
)
impl fmt::Display for ColumnDef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} {}", self.name, self.data_type)?;
for option in &self.options {
write!(f, " {}", option)?;
}
Ok(())
}
}

Expand All @@ -126,13 +122,9 @@ pub struct ColumnOptionDef {
pub option: ColumnOption,
}

impl ToString for ColumnOptionDef {
fn to_string(&self) -> String {
format!(
"{}{}",
format_constraint_name(&self.name),
self.option.to_string()
)
impl fmt::Display for ColumnOptionDef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}{}", display_constraint_name(&self.name), self.option)
}
}

Expand Down Expand Up @@ -160,35 +152,39 @@ pub enum ColumnOption {
Check(Expr),
}

impl ToString for ColumnOption {
fn to_string(&self) -> String {
impl fmt::Display for ColumnOption {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use ColumnOption::*;
match self {
Null => "NULL".to_string(),
NotNull => "NOT NULL".to_string(),
Default(expr) => format!("DEFAULT {}", expr.to_string()),
Null => write!(f, "NULL"),
NotNull => write!(f, "NOT NULL"),
Default(expr) => write!(f, "DEFAULT {}", expr),
Unique { is_primary } => {
if *is_primary {
"PRIMARY KEY".to_string()
} else {
"UNIQUE".to_string()
}
write!(f, "{}", if *is_primary { "PRIMARY KEY" } else { "UNIQUE" })
}
ForeignKey {
foreign_table,
referred_columns,
} => format!(
} => write!(
f,
"REFERENCES {} ({})",
foreign_table.to_string(),
referred_columns.join(", ")
foreign_table,
display_comma_separated(referred_columns)
),
Check(expr) => format!("CHECK ({})", expr.to_string(),),
Check(expr) => write!(f, "CHECK ({})", expr),
}
}
}

fn format_constraint_name(name: &Option<Ident>) -> String {
name.as_ref()
.map(|name| format!("CONSTRAINT {} ", name))
.unwrap_or_default()
fn display_constraint_name<'a>(name: &'a Option<Ident>) -> impl fmt::Display + 'a {
struct ConstraintName<'a>(&'a Option<Ident>);
impl<'a> fmt::Display for ConstraintName<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(name) = self.0 {
write!(f, "CONSTRAINT {} ", name)?;
}
Ok(())
}
}
ConstraintName(name)
}
Loading