Skip to content
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