mod active_value;
pub use active_value::ActiveValue;
use std::borrow::Cow;
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum Value {
Bool(bool),
TinyInt(i8),
SmallInt(i16),
Int(i32),
BigInt(i64),
TinyUnsigned(u8),
SmallUnsigned(u16),
Unsigned(u32),
BigUnsigned(u64),
Float(f32),
Double(f64),
Char(char),
String(Box<String>),
#[allow(clippy::box_collection)]
Bytes(Box<bytes::Bytes>),
Array(Box<Vec<Value>>),
#[cfg(feature = "with-json")]
#[cfg_attr(docsrs, doc(cfg(feature = "with-json")))]
Json(Box<serde_json::Value>),
#[cfg(feature = "with-chrono")]
#[cfg_attr(docsrs, doc(cfg(feature = "with-chrono")))]
ChronoDateTime(Box<chrono::DateTime<chrono::FixedOffset>>),
Null,
}
impl From<bool> for Value {
fn from(val: bool) -> Self {
Value::Bool(val)
}
}
impl From<i8> for Value {
fn from(val: i8) -> Self {
Value::TinyInt(val)
}
}
impl From<i16> for Value {
fn from(val: i16) -> Self {
Value::SmallInt(val)
}
}
impl From<i32> for Value {
fn from(val: i32) -> Self {
Value::Int(val)
}
}
impl From<i64> for Value {
fn from(val: i64) -> Self {
Value::BigInt(val)
}
}
impl From<u8> for Value {
fn from(val: u8) -> Self {
Value::TinyUnsigned(val)
}
}
impl From<u16> for Value {
fn from(val: u16) -> Self {
Value::SmallUnsigned(val)
}
}
impl From<u32> for Value {
fn from(val: u32) -> Self {
Value::Unsigned(val)
}
}
impl From<u64> for Value {
fn from(val: u64) -> Self {
Value::BigUnsigned(val)
}
}
impl From<f32> for Value {
fn from(val: f32) -> Self {
Value::Float(val)
}
}
impl From<f64> for Value {
fn from(val: f64) -> Self {
Value::Double(val)
}
}
impl From<char> for Value {
fn from(val: char) -> Self {
Value::Char(val)
}
}
impl From<&str> for Value {
fn from(val: &str) -> Self {
let string: String = val.into();
Value::String(Box::new(string))
}
}
impl From<String> for Value {
fn from(val: String) -> Self {
Value::String(Box::new(val))
}
}
impl From<Cow<'_, str>> for Value {
fn from(val: Cow<'_, str>) -> Self {
val.into_owned().into()
}
}
impl From<bytes::Bytes> for Value {
fn from(val: bytes::Bytes) -> Self {
Value::Bytes(Box::new(val))
}
}
impl<T: Into<Value>> From<Vec<T>> for Value {
fn from(vals: Vec<T>) -> Self {
let vals = vals.into_iter().map(|v| v.into()).collect();
Value::Array(Box::new(vals))
}
}
#[cfg(feature = "with-json")]
impl From<serde_json::Value> for Value {
fn from(val: serde_json::Value) -> Self {
Value::Json(Box::new(val))
}
}
#[cfg(feature = "with-chrono")]
impl From<chrono::DateTime<chrono::Utc>> for Value {
fn from(val: chrono::DateTime<chrono::Utc>) -> Self {
let value = chrono::DateTime::<chrono::FixedOffset>::from(val);
Value::ChronoDateTime(Box::new(value))
}
}
#[cfg(feature = "with-chrono")]
impl From<chrono::DateTime<chrono::FixedOffset>> for Value {
fn from(val: chrono::DateTime<chrono::FixedOffset>) -> Self {
Value::ChronoDateTime(Box::new(val))
}
}
impl<T> From<&T> for Value
where
T: Clone + Into<Value>,
{
fn from(value: &T) -> Self {
value.clone().into()
}
}
impl<T> From<Option<T>> for Value
where
T: Into<Value>,
{
fn from(value: Option<T>) -> Self {
match value {
Some(value) => value.into(),
None => Value::Null,
}
}
}
impl Value {
pub fn try_get_i32(&self) -> anyhow::Result<i32> {
match self {
Self::TinyInt(v) => Ok(*v as i32),
Self::SmallInt(v) => Ok(*v as i32),
Self::Int(v) => Ok(*v),
Self::BigInt(v) => Ok(*v as i32),
Self::TinyUnsigned(v) => Ok(*v as i32),
Self::SmallUnsigned(v) => Ok(*v as i32),
Self::Unsigned(v) => Ok(*v as i32),
Self::BigUnsigned(v) => Ok(*v as i32),
Self::Null => Ok(0),
_ => Err(anyhow::anyhow!("value type {:?} cant not to i32", self)),
}
}
pub fn to_sql(&self) -> Option<crate::Sql> {
let raw_sql_string = match self {
Value::Bool(val) => {
if *val {
Some(crate::Sql::new("1"))
} else {
Some(crate::Sql::new("0"))
}
}
Value::TinyInt(val) => Some(crate::Sql::new(format!("{}", val))),
Value::SmallInt(val) => Some(crate::Sql::new(format!("{}", val))),
Value::Int(val) => Some(crate::Sql::new(format!("{}", val))),
Value::BigInt(val) => Some(crate::Sql::new(format!("{}", val))),
Value::TinyUnsigned(val) => Some(crate::Sql::new(format!("{}", val))),
Value::SmallUnsigned(val) => Some(crate::Sql::new(format!("{}", val))),
Value::Unsigned(val) => Some(crate::Sql::new(format!("{}", val))),
Value::BigUnsigned(val) => Some(crate::Sql::new(format!("{}", val))),
Value::Float(val) => Some(crate::Sql::new(format!("{}", val))),
Value::Double(val) => Some(crate::Sql::new(format!("{}", val))),
Value::Char(val) => {
let mut sql = crate::Sql::default();
sql.push_str_with_prepare_value(sql.prepare_symbol(), *val);
Some(sql)
}
Value::String(val) => {
let mut sql = crate::Sql::default();
sql.push_str_with_prepare_value(sql.prepare_symbol(), val.to_string());
Some(sql)
}
Value::Bytes(val) => {
let mut sql = crate::Sql::default();
sql.push_str_with_prepare_value(sql.prepare_symbol(), bytes::Bytes::copy_from_slice(val));
Some(sql)
}
Value::Array(val) => {
let mut sql = crate::Sql::new("(");
let vec_sqls: Vec<crate::Sql> = val.iter().filter_map(|v| v.to_sql()).collect();
let vec_sqls_len = val.len();
for (idx, v_sql) in vec_sqls.into_iter().enumerate() {
sql.push_sql(v_sql);
if idx < vec_sqls_len - 1 {
sql.push(',');
}
}
sql.push(')');
Some(sql)
}
#[cfg(feature = "with-json")]
Value::Json(val) => {
let mut sql = crate::Sql::default();
sql.push_str_with_prepare_value(sql.prepare_symbol(), serde_json::to_string(val).unwrap());
Some(sql)
}
#[cfg(feature = "with-chrono")]
Value::ChronoDateTime(val) => {
let mut sql = crate::Sql::default();
sql.push_str_with_prepare_value(sql.prepare_symbol(), format!("{}", val));
Some(sql)
}
Value::Null => None,
};
raw_sql_string
}
}