use super::ArrayType;
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
Bool(Option<bool>),
TinyInt(Option<i8>),
SmallInt(Option<i16>),
Int(Option<i32>),
BigInt(Option<i64>),
TinyUnsigned(Option<u8>),
SmallUnsigned(Option<u16>),
Unsigned(Option<u32>),
BigUnsigned(Option<u64>),
Float(Option<f32>),
Double(Option<f64>),
Char(Option<char>),
String(Option<Box<String>>),
Bytes(Option<Box<Vec<u8>>>),
#[cfg(feature = "with-chrono")]
ChronoDate(Option<Box<chrono::NaiveDate>>),
#[cfg(feature = "with-chrono")]
ChronoTime(Option<Box<chrono::NaiveTime>>),
#[cfg(feature = "with-chrono")]
ChronoDateTime(Option<Box<chrono::NaiveDateTime>>),
#[cfg(feature = "with-chrono")]
ChronoDateTimeUtc(Option<Box<chrono::DateTime<chrono::Utc>>>),
#[cfg(feature = "with-chrono")]
ChronoDateTimeLocal(Option<Box<chrono::DateTime<chrono::Local>>>),
#[cfg(feature = "with-chrono")]
ChronoDateTimeWithTimeZone(Option<Box<chrono::DateTime<chrono::FixedOffset>>>),
#[cfg(feature = "with-uuid")]
Uuid(Option<Box<uuid::Uuid>>),
#[cfg(feature = "with-json")]
Json(Option<Box<serde_json::Value>>),
#[cfg(feature = "with-rust_decimal")]
Decimal(Option<Box<rust_decimal::Decimal>>),
#[cfg(feature = "with-bigdecimal")]
BigDecimal(Option<Box<bigdecimal::BigDecimal>>),
Array(ArrayType, Option<Box<Vec<Value>>>),
}
impl Value {
#[must_use]
pub fn is_null(&self) -> bool {
match self {
Self::Bool(v) => v.is_none(),
Self::TinyInt(v) => v.is_none(),
Self::SmallInt(v) => v.is_none(),
Self::Int(v) => v.is_none(),
Self::BigInt(v) => v.is_none(),
Self::TinyUnsigned(v) => v.is_none(),
Self::SmallUnsigned(v) => v.is_none(),
Self::Unsigned(v) => v.is_none(),
Self::BigUnsigned(v) => v.is_none(),
Self::Float(v) => v.is_none(),
Self::Double(v) => v.is_none(),
Self::Char(v) => v.is_none(),
Self::String(v) => v.is_none(),
Self::Bytes(v) => v.is_none(),
#[cfg(feature = "with-chrono")]
Self::ChronoDate(v) => v.is_none(),
#[cfg(feature = "with-chrono")]
Self::ChronoTime(v) => v.is_none(),
#[cfg(feature = "with-chrono")]
Self::ChronoDateTime(v) => v.is_none(),
#[cfg(feature = "with-chrono")]
Self::ChronoDateTimeUtc(v) => v.is_none(),
#[cfg(feature = "with-chrono")]
Self::ChronoDateTimeLocal(v) => v.is_none(),
#[cfg(feature = "with-chrono")]
Self::ChronoDateTimeWithTimeZone(v) => v.is_none(),
#[cfg(feature = "with-uuid")]
Self::Uuid(v) => v.is_none(),
#[cfg(feature = "with-json")]
Self::Json(v) => v.is_none(),
#[cfg(feature = "with-rust_decimal")]
Self::Decimal(v) => v.is_none(),
#[cfg(feature = "with-bigdecimal")]
Self::BigDecimal(v) => v.is_none(),
Self::Array(_, v) => v.is_none(),
}
}
}
impl Value {
#[must_use]
pub fn to_sql_literal(&self) -> String {
match self {
Self::Bool(Some(v)) => {
if *v {
"TRUE".to_string()
} else {
"FALSE".to_string()
}
}
Self::Bool(None) => "NULL".to_string(),
Self::TinyInt(Some(v)) => v.to_string(),
Self::TinyInt(None) => "NULL".to_string(),
Self::SmallInt(Some(v)) => v.to_string(),
Self::SmallInt(None) => "NULL".to_string(),
Self::Int(Some(v)) => v.to_string(),
Self::Int(None) => "NULL".to_string(),
Self::BigInt(Some(v)) => v.to_string(),
Self::BigInt(None) => "NULL".to_string(),
Self::TinyUnsigned(Some(v)) => v.to_string(),
Self::TinyUnsigned(None) => "NULL".to_string(),
Self::SmallUnsigned(Some(v)) => v.to_string(),
Self::SmallUnsigned(None) => "NULL".to_string(),
Self::Unsigned(Some(v)) => v.to_string(),
Self::Unsigned(None) => "NULL".to_string(),
Self::BigUnsigned(Some(v)) => v.to_string(),
Self::BigUnsigned(None) => "NULL".to_string(),
Self::Float(Some(v)) => v.to_string(),
Self::Float(None) => "NULL".to_string(),
Self::Double(Some(v)) => v.to_string(),
Self::Double(None) => "NULL".to_string(),
Self::Char(Some(v)) => {
if *v == '\'' {
"''''".to_string()
} else {
format!("'{}'", v)
}
}
Self::Char(None) => "NULL".to_string(),
Self::String(Some(v)) => {
format!("'{}'", v.replace('\'', "''"))
}
Self::String(None) => "NULL".to_string(),
Self::Bytes(Some(v)) => {
let hex: String = v.iter().map(|b| format!("{:02X}", b)).collect();
format!("X'{}'", hex)
}
Self::Bytes(None) => "NULL".to_string(),
#[cfg(feature = "with-chrono")]
Self::ChronoDate(Some(v)) => format!("'{}'", v),
#[cfg(feature = "with-chrono")]
Self::ChronoDate(None) => "NULL".to_string(),
#[cfg(feature = "with-chrono")]
Self::ChronoTime(Some(v)) => format!("'{}'", v),
#[cfg(feature = "with-chrono")]
Self::ChronoTime(None) => "NULL".to_string(),
#[cfg(feature = "with-chrono")]
Self::ChronoDateTime(Some(v)) => format!("'{}'", v),
#[cfg(feature = "with-chrono")]
Self::ChronoDateTime(None) => "NULL".to_string(),
#[cfg(feature = "with-chrono")]
Self::ChronoDateTimeUtc(Some(v)) => format!("'{}'", v.to_rfc3339()),
#[cfg(feature = "with-chrono")]
Self::ChronoDateTimeUtc(None) => "NULL".to_string(),
#[cfg(feature = "with-chrono")]
Self::ChronoDateTimeLocal(Some(v)) => format!("'{}'", v.to_rfc3339()),
#[cfg(feature = "with-chrono")]
Self::ChronoDateTimeLocal(None) => "NULL".to_string(),
#[cfg(feature = "with-chrono")]
Self::ChronoDateTimeWithTimeZone(Some(v)) => format!("'{}'", v.to_rfc3339()),
#[cfg(feature = "with-chrono")]
Self::ChronoDateTimeWithTimeZone(None) => "NULL".to_string(),
#[cfg(feature = "with-uuid")]
Self::Uuid(Some(v)) => format!("'{}'", v),
#[cfg(feature = "with-uuid")]
Self::Uuid(None) => "NULL".to_string(),
#[cfg(feature = "with-json")]
Self::Json(Some(v)) => {
let json_str = serde_json::to_string(v.as_ref()).unwrap_or_default();
format!("'{}'", json_str.replace('\'', "''"))
}
#[cfg(feature = "with-json")]
Self::Json(None) => "NULL".to_string(),
#[cfg(feature = "with-rust_decimal")]
Self::Decimal(Some(v)) => v.to_string(),
#[cfg(feature = "with-rust_decimal")]
Self::Decimal(None) => "NULL".to_string(),
#[cfg(feature = "with-bigdecimal")]
Self::BigDecimal(Some(v)) => v.to_string(),
#[cfg(feature = "with-bigdecimal")]
Self::BigDecimal(None) => "NULL".to_string(),
Self::Array(_, Some(values)) => {
let items: Vec<String> = values.iter().map(|v| v.to_sql_literal()).collect();
format!("ARRAY[{}]", items.join(","))
}
Self::Array(_, None) => "NULL".to_string(),
}
}
}
impl Default for Value {
fn default() -> Self {
Self::String(None)
}
}