use crate::serializer::ExprContext;
use super::{Flavor, ToSql};
use toasty_core::schema::db;
impl ToSql for &db::Type {
fn to_sql(self, cx: &ExprContext<'_>, f: &mut super::Formatter<'_>) {
match self {
db::Type::Boolean => fmt!(cx, f, "BOOLEAN"),
db::Type::Integer(1..=2) => fmt!(cx, f, "SMALLINT"),
db::Type::Integer(3..=4) => fmt!(cx, f, "INTEGER"),
db::Type::Integer(5..=8) => fmt!(cx, f, "BIGINT"),
db::Type::Integer(_) => todo!(),
db::Type::UnsignedInteger(size) => {
match f.serializer.flavor {
Flavor::Mysql => match size {
1 => fmt!(cx, f, "TINYINT UNSIGNED"),
2 => fmt!(cx, f, "SMALLINT UNSIGNED"),
3..=4 => fmt!(cx, f, "INT UNSIGNED"),
5..=8 => fmt!(cx, f, "BIGINT UNSIGNED"),
_ => todo!("Unsupported unsigned integer size: {}", size),
},
Flavor::Postgresql => {
match size {
1 => fmt!(cx, f, "SMALLINT"), 2 => fmt!(cx, f, "INTEGER"), 3..=4 => fmt!(cx, f, "BIGINT"), 5..=8 => fmt!(cx, f, "BIGINT"), _ => todo!("Unsupported unsigned integer size: {}", size),
}
}
Flavor::Sqlite => {
fmt!(cx, f, "INTEGER")
}
}
}
db::Type::Float(size) => match f.serializer.flavor {
Flavor::Sqlite => fmt!(cx, f, "REAL"),
Flavor::Postgresql => {
if *size <= 4 {
fmt!(cx, f, "REAL")
} else {
fmt!(cx, f, "DOUBLE PRECISION")
}
}
Flavor::Mysql => {
if *size <= 4 {
fmt!(cx, f, "FLOAT")
} else {
fmt!(cx, f, "DOUBLE")
}
}
},
db::Type::Text => fmt!(cx, f, "TEXT"),
db::Type::VarChar(size) => fmt!(cx, f, "VARCHAR(" size ")"),
db::Type::Uuid => {
fmt!(
cx,
f,
match f.serializer.flavor {
Flavor::Postgresql => "UUID",
_ => todo!("Unsupported type UUID"),
}
);
}
db::Type::Numeric(None) => match f.serializer.flavor {
Flavor::Postgresql => fmt!(cx, f, "NUMERIC"),
Flavor::Mysql => todo!(
"MySQL does not support arbitrary-precision NUMERIC; precision and scale must be specified"
),
Flavor::Sqlite => todo!("SQLite does not support NUMERIC type"),
},
db::Type::Numeric(Some((precision, scale))) => match f.serializer.flavor {
Flavor::Postgresql => fmt!(cx, f, "NUMERIC(" precision ", " scale ")"),
Flavor::Mysql => fmt!(cx, f, "DECIMAL(" precision ", " scale ")"),
Flavor::Sqlite => todo!("SQLite does not support NUMERIC type"),
},
db::Type::Binary(size) => match f.serializer.flavor {
Flavor::Mysql => fmt!(cx, f, "BINARY(" size ")"),
_ => todo!("Unsupported fixed size binary type"),
},
db::Type::Blob => match f.serializer.flavor {
Flavor::Postgresql => fmt!(cx, f, "BYTEA"),
Flavor::Mysql => fmt!(cx, f, "BLOB"),
Flavor::Sqlite => fmt!(cx, f, "BLOB"),
},
db::Type::Timestamp(precision) => match f.serializer.flavor {
Flavor::Postgresql => fmt!(cx, f, "TIMESTAMPTZ(" precision ")"),
Flavor::Mysql => fmt!(cx, f, "TIMESTAMP(" precision ")"),
Flavor::Sqlite => todo!("SQLite does not support Timestamp"),
},
db::Type::Date => match f.serializer.flavor {
Flavor::Postgresql | Flavor::Mysql => fmt!(cx, f, "DATE"),
Flavor::Sqlite => todo!("SQLite does not support Date"),
},
db::Type::Time(precision) => match f.serializer.flavor {
Flavor::Postgresql => fmt!(cx, f, "TIME(" precision ")"),
Flavor::Mysql => fmt!(cx, f, "TIME(" precision ")"),
Flavor::Sqlite => todo!("SQLite does not support Time"),
},
db::Type::DateTime(precision) => match f.serializer.flavor {
Flavor::Postgresql => fmt!(cx, f, "TIMESTAMP(" precision ")"),
Flavor::Mysql => fmt!(cx, f, "DATETIME(" precision ")"),
Flavor::Sqlite => todo!("SQLite does not support DateTime"),
},
db::Type::Enum(type_enum) => match f.serializer.flavor {
Flavor::Postgresql => {
let name = type_enum
.name
.as_deref()
.expect("PostgreSQL enums require a type name");
fmt!(cx, f, name);
}
Flavor::Mysql => {
use toasty_core::stmt::Value;
f.dst.push_str("ENUM(");
for (i, variant) in type_enum.variants.iter().enumerate() {
if i > 0 {
f.dst.push_str(", ");
}
Value::String(variant.name.clone()).to_sql(cx, f);
}
f.dst.push(')');
}
Flavor::Sqlite => fmt!(cx, f, "TEXT"),
},
db::Type::Custom(custom) => fmt!(cx, f, custom.as_str()),
}
}
}