use std::str::FromStr;
use mysql_async::{prelude::Queryable, Params};
use crate::mysql::con_value::ValueConv;
use crate::OrmR;
#[allow(async_fn_in_trait)]
pub trait OrmMySqlTrait {
type IdType: Into<mysql_async::Value> + Send;
async fn query<C>(
comm: &mut C,
where_sql: &str,
limit: Option<usize>,
) -> OrmR<Vec<Self>>
where
Self: Sized,
C: mysql_async::prelude::Queryable + Send + Sync;
async fn query_first<C>(comm: &mut C, where_sql: &str) -> OrmR<Option<Self>>
where
Self: Sized,
C: mysql_async::prelude::Queryable + Send + Sync;
async fn find_by_id<C>(comm: &mut C, id: Self::IdType) -> OrmR<Option<Self>>
where
Self: Sized,
C: mysql_async::prelude::Queryable + Send + Sync;
async fn delete_by_id<C>(comm: &mut C, id: Self::IdType) -> OrmR<i64>
where
Self: Sized,
C: mysql_async::prelude::Queryable + Send + Sync;
async fn insert<C>(self, comm: &mut C) -> OrmR<i64>
where
Self: Sized,
C: mysql_async::prelude::Queryable + Send + Sync;
fn insert_sql() -> String
where
Self: Sized;
async fn update<C>(self, comm: &mut C) -> OrmR<i64>
where
Self: Sized,
C: mysql_async::prelude::Queryable + Send + Sync;
async fn delete<C>(&self, comm: &mut C) -> OrmR<i64>
where
Self: Sized,
C: mysql_async::prelude::Queryable + Send + Sync;
async fn delete_where<C>(comm: &mut C, where_sql: &str) -> OrmR<i64>
where
Self: Sized,
C: mysql_async::prelude::Queryable + Send + Sync;
fn delete_sql() -> String
where
Self: Sized;
fn where_id(&self) -> impl Into<mysql_async::Value>
where
Self: Sized;
}
#[allow(async_fn_in_trait)]
pub trait OrmMySqlTraitConn<
T: OrmMySqlTrait + Send + Sync + Into<Params>,
C: mysql_async::prelude::Queryable + Send + Sync,
> where
Self: Queryable + Sized + Send + Sync,
{
async fn insert_arr(&mut self, arr: Vec<T>) -> OrmR<i64> {
if arr.is_empty() {
return Ok(0);
}
let sql = T::insert_sql();
let len = arr.len();
self.exec_batch(sql, arr).await?;
Ok(len as i64)
}
async fn delete_arr(&mut self, arr: Vec<T>) -> OrmR<i64> {
if arr.is_empty() {
return Ok(0);
}
let sql = T::delete_sql();
let params: Vec<(mysql_async::Value,)> = arr
.iter()
.map(|x| (x.where_id().into(),))
.collect::<Vec<_>>();
self.exec_batch(sql, params).await?;
Ok(arr.len() as i64)
}
}
impl<T: OrmMySqlTrait + Send + Sync + Into<Params>> OrmMySqlTraitConn<T, Self>
for mysql_async::Conn
{
}
impl<'a, T: OrmMySqlTrait + Send + Sync + Clone + Into<Params>> OrmMySqlTraitConn<T, Self>
for mysql_async::Transaction<'a>
{
}
pub mod con_value {
use std::str::FromStr;
use crate::OrmR;
pub trait ValueConv<T> {
fn conv(&self) -> OrmR<T>;
}
#[cfg(feature = "chrono")]
impl ValueConv<chrono::NaiveTime> for mysql_async::Value {
fn conv(&self) -> OrmR<chrono::NaiveTime> {
let v = match self.clone() {
mysql_async::Value::Bytes(bytes) => {
let s = String::from_utf8(bytes)?;
let v = chrono::NaiveTime::parse_from_str(&s, "%H:%M:%S")?;
v
}
mysql_async::Value::Time(_is_negative, days, hours, minutes, seconds, micro) => {
let mut v = chrono::NaiveTime::from_hms(0, 0, 0);
v = v + chrono::Duration::days(days as i64);
v = v + chrono::Duration::hours(hours as i64);
v = v + chrono::Duration::minutes(minutes as i64);
v = v + chrono::Duration::seconds(seconds as i64);
v = v + chrono::Duration::microseconds(micro as i64);
v
}
_ => {
return Err("mysql_async::Value::Time")?;
}
};
Ok(v)
}
}
#[cfg(feature = "chrono")]
impl ValueConv<Option<chrono::NaiveTime>> for mysql_async::Value {
fn conv(&self) -> OrmR<Option<chrono::NaiveTime>> {
let v = match self.clone() {
mysql_async::Value::NULL => return Ok(None),
other => other.conv(),
}?;
Ok(Some(v))
}
}
#[cfg(feature = "chrono")]
impl ValueConv<chrono::NaiveDateTime> for mysql_async::Value {
fn conv(&self) -> OrmR<chrono::NaiveDateTime> {
let v = match self.clone() {
mysql_async::Value::Bytes(bytes) => {
let s = String::from_utf8(bytes)?;
chrono::NaiveDateTime::parse_from_str(&s, "%Y-%m-%d %H:%M:%S")
}
mysql_async::Value::Date(year, month, day, hour, minutes, seconds, micro) => {
chrono::NaiveDateTime::parse_from_str(
&format!("{year}-{month}-{day} {hour}:{minutes}:{seconds}.{micro:0>6}"),
"%Y-%m-%d %H:%M:%S.f6",
)
}
_ => {
return Err("mysql_async::Value::Date")?;
}
}?;
Ok(v)
}
}
#[cfg(feature = "chrono")]
impl ValueConv<Option<chrono::NaiveDateTime>> for mysql_async::Value {
fn conv(&self) -> OrmR<Option<chrono::NaiveDateTime>> {
let v = match self.clone() {
mysql_async::Value::NULL => return Ok(None),
other => other.conv(),
}?;
Ok(Some(v))
}
}
#[cfg(feature = "chrono")]
impl ValueConv<chrono::NaiveDate> for mysql_async::Value {
fn conv(&self) -> OrmR<chrono::NaiveDate> {
let v = match self.clone() {
mysql_async::Value::Bytes(bytes) => {
let s = String::from_utf8(bytes)?;
chrono::NaiveDate::parse_from_str(&s, "%Y-%m-%d")
}
mysql_async::Value::Date(year, month, day, hour, minutes, seconds, micro) => {
chrono::NaiveDate::parse_from_str(&format!("{year}-{month}-{day}"), "%Y-%m-%d")
}
mysql_async::Value::Time(_is_negative, days, hours, minutes, seconds, micro) => {
let mut v = chrono::NaiveDate::from_ymd(1970, 1, 1);
v = v + chrono::Duration::days(days as i64);
Ok(v)
}
_ => {
return Err("mysql_async deser tos chrono::NaiveDate")?;
}
}?;
Ok(v)
}
}
#[cfg(feature = "chrono")]
impl ValueConv<Option<chrono::NaiveDate>> for mysql_async::Value {
fn conv(&self) -> OrmR<Option<chrono::NaiveDate>> {
let v = match self.clone() {
mysql_async::Value::NULL => return Ok(None),
other => other.conv(),
}?;
Ok(Some(v))
}
}
#[cfg(feature = "chrono")]
impl ValueConv<chrono::DateTime<chrono::Local>> for mysql_async::Value {
fn conv(&self) -> OrmR<chrono::DateTime<chrono::Local>> {
let v = match self.clone() {
mysql_async::Value::Int(timestament) => {
use chrono::TimeZone;
let dt = chrono::Local.timestamp(timestament as i64, 0);
dt
}
mysql_async::Value::UInt(timestament) => {
use chrono::TimeZone;
let dt = chrono::Local.timestamp(timestament as i64, 0);
dt
}
mysql_async::Value::Time(_is_negative, days, hours, minutes, seconds, micro) => {
let mut v = chrono::NaiveTime::from_hms(0, 0, 0);
v = v + chrono::Duration::days(days as i64);
v = v + chrono::Duration::hours(hours as i64);
v = v + chrono::Duration::minutes(minutes as i64);
v = v + chrono::Duration::seconds(seconds as i64);
v = v + chrono::Duration::microseconds(micro as i64);
chrono::Local::now().date().and_time(v).unwrap_or_default()
}
mysql_async::Value::Date(year, month, day, hour, minutes, seconds, micro) => {
use chrono::TimeZone;
let dt = chrono::Local
.ymd(year as i32, month as u32, day as u32)
.and_hms_micro(hour as u32, minutes as u32, seconds as u32, micro as u32);
dt
}
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
#[cfg(feature = "chrono")]
impl ValueConv<Option<chrono::DateTime<chrono::Local>>> for mysql_async::Value {
fn conv(&self) -> OrmR<Option<chrono::DateTime<chrono::Local>>> {
let v = match self.clone() {
mysql_async::Value::NULL => {
return Ok(None);
}
other => other.conv()?,
};
Ok(v)
}
}
#[cfg(feature = "chrono")]
impl ValueConv<Option<chrono::DateTime<chrono::Utc>>> for mysql_async::Value {
fn conv(&self) -> OrmR<Option<chrono::DateTime<chrono::Utc>>> {
let v = match self.clone() {
mysql_async::Value::NULL => {
return Ok(None);
}
other => other.conv()?,
};
Ok(v)
}
}
#[cfg(feature = "rust_decimal")]
impl ValueConv<Option<rust_decimal::Decimal>> for mysql_async::Value {
fn conv(&self) -> OrmR<Option<rust_decimal::Decimal>> {
use rust_decimal::prelude::*;
let v = match self.clone() {
mysql_async::Value::NULL => None,
mysql_async::Value::Bytes(v) => {
Some(rust_decimal::Decimal::from_str(&(String::from_utf8(v)?))?)
}
mysql_async::Value::Int(v) => rust_decimal::Decimal::from_i64(v),
mysql_async::Value::UInt(v) => Decimal::from_i64(v as i64),
mysql_async::Value::Float(v) => Decimal::from_f32(v),
mysql_async::Value::Double(v) => Decimal::from_f64(v),
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
#[cfg(feature = "rust_decimal")]
impl ValueConv<rust_decimal::Decimal> for mysql_async::Value {
fn conv(&self) -> OrmR<rust_decimal::Decimal> {
use rust_decimal::prelude::*;
let v = match self.clone() {
mysql_async::Value::NULL => None,
mysql_async::Value::Bytes(v) => {
Some(rust_decimal::Decimal::from_str(&(String::from_utf8(v)?))?)
}
mysql_async::Value::Int(v) => rust_decimal::Decimal::from_i64(v),
mysql_async::Value::UInt(v) => Decimal::from_i64(v as i64),
mysql_async::Value::Float(v) => Decimal::from_f32(v),
mysql_async::Value::Double(v) => Decimal::from_f64(v),
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v.unwrap_or_else(|| rust_decimal::Decimal::ZERO))
}
}
#[cfg(feature = "bigdecimal")]
impl ValueConv<Option<bigdecimal::BigDecimal>> for mysql_async::Value {
fn conv(&self) -> OrmR<Option<bigdecimal::BigDecimal>> {
use bigdecimal::BigDecimal as Decimal;
use bigdecimal::FromPrimitive;
let v = match self.clone() {
mysql_async::Value::NULL => None,
mysql_async::Value::Bytes(v) => Some(Decimal::from_str(&(String::from_utf8(v)?))?),
mysql_async::Value::Int(v) => Decimal::from_i64(v),
mysql_async::Value::UInt(v) => Decimal::from_i64(v as i64),
mysql_async::Value::Float(v) => Decimal::from_f32(v),
mysql_async::Value::Double(v) => Decimal::from_f64(v),
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
#[cfg(feature = "bigdecimal")]
impl ValueConv<bigdecimal::BigDecimal> for mysql_async::Value {
fn conv(&self) -> OrmR<bigdecimal::BigDecimal> {
use bigdecimal::BigDecimal as Decimal;
use bigdecimal::FromPrimitive;
let v = match self.clone() {
mysql_async::Value::NULL => None,
mysql_async::Value::Bytes(v) => Some(Decimal::from_str(&(String::from_utf8(v)?))?),
mysql_async::Value::Int(v) => Decimal::from_i64(v),
mysql_async::Value::UInt(v) => Decimal::from_i64(v as i64),
mysql_async::Value::Float(v) => Decimal::from_f32(v),
mysql_async::Value::Double(v) => Decimal::from_f64(v),
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v.unwrap_or_else(|| Decimal::default()))
}
}
impl ValueConv<f64> for mysql_async::Value {
fn conv(&self) -> OrmR<f64> {
let v = match self.clone() {
mysql_async::Value::NULL => 0.0,
mysql_async::Value::Bytes(v) => String::from_utf8(v)?.parse()?,
mysql_async::Value::Int(v) => v as f64,
mysql_async::Value::UInt(v) => v as f64,
mysql_async::Value::Float(v) => v as f64,
mysql_async::Value::Double(v) => v,
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
impl ValueConv<Option<f64>> for mysql_async::Value {
fn conv(&self) -> OrmR<Option<f64>> {
let v = match self.clone() {
mysql_async::Value::NULL => None,
mysql_async::Value::Bytes(v) => Some(String::from_utf8(v)?.parse()?),
mysql_async::Value::Int(v) => Some(v as f64),
mysql_async::Value::UInt(v) => Some(v as f64),
mysql_async::Value::Float(v) => Some(v as f64),
mysql_async::Value::Double(v) => Some(v),
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
impl ValueConv<f32> for mysql_async::Value {
fn conv(&self) -> OrmR<f32> {
let v = match self.clone() {
mysql_async::Value::NULL => 0.0,
mysql_async::Value::Bytes(v) => String::from_utf8(v)?.parse()?,
mysql_async::Value::Int(v) => v as f32,
mysql_async::Value::UInt(v) => v as f32,
mysql_async::Value::Float(v) => v,
mysql_async::Value::Double(v) => v as f32,
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
impl ValueConv<Option<f32>> for mysql_async::Value {
fn conv(&self) -> OrmR<Option<f32>> {
let v = match self.clone() {
mysql_async::Value::NULL => None,
mysql_async::Value::Bytes(v) => Some(String::from_utf8(v)?.parse()?),
mysql_async::Value::Int(v) => Some(v as f32),
mysql_async::Value::UInt(v) => Some(v as f32),
mysql_async::Value::Float(v) => Some(v),
mysql_async::Value::Double(v) => Some(v as f32),
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
impl ValueConv<isize> for mysql_async::Value {
fn conv(&self) -> OrmR<isize> {
let v = match self.clone() {
mysql_async::Value::NULL => 0,
mysql_async::Value::Bytes(v) => String::from_utf8(v)?.parse()?,
mysql_async::Value::Int(v) => v as isize,
mysql_async::Value::UInt(v) => v as isize,
mysql_async::Value::Float(v) => v as isize,
mysql_async::Value::Double(v) => v as isize,
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
impl ValueConv<Option<isize>> for mysql_async::Value {
fn conv(&self) -> OrmR<Option<isize>> {
let v = match self.clone() {
mysql_async::Value::NULL => None,
mysql_async::Value::Bytes(v) => Some(String::from_utf8(v)?.parse()?),
mysql_async::Value::Int(v) => Some(v as isize),
mysql_async::Value::UInt(v) => Some(v as isize),
mysql_async::Value::Float(v) => Some(v as isize),
mysql_async::Value::Double(v) => Some(v as isize),
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
impl ValueConv<u64> for mysql_async::Value {
fn conv(&self) -> OrmR<u64> {
let v = match self.clone() {
mysql_async::Value::NULL => 0,
mysql_async::Value::Bytes(v) => String::from_utf8(v)?.parse()?,
mysql_async::Value::Int(v) => v as u64,
mysql_async::Value::UInt(v) => v as u64,
mysql_async::Value::Float(v) => v as u64,
mysql_async::Value::Double(v) => v as u64,
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
impl ValueConv<Option<u64>> for mysql_async::Value {
fn conv(&self) -> OrmR<Option<u64>> {
let v = match self.clone() {
mysql_async::Value::NULL => None,
mysql_async::Value::Bytes(v) => Some(String::from_utf8(v)?.parse()?),
mysql_async::Value::Int(v) => Some(v as u64),
mysql_async::Value::UInt(v) => Some(v as u64),
mysql_async::Value::Float(v) => Some(v as u64),
mysql_async::Value::Double(v) => Some(v as u64),
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
impl ValueConv<u32> for mysql_async::Value {
fn conv(&self) -> OrmR<u32> {
let v = match self.clone() {
mysql_async::Value::NULL => 0,
mysql_async::Value::Bytes(v) => String::from_utf8(v)?.parse()?,
mysql_async::Value::Int(v) => v as u32,
mysql_async::Value::UInt(v) => v as u32,
mysql_async::Value::Float(v) => v as u32,
mysql_async::Value::Double(v) => v as u32,
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
impl ValueConv<Option<u32>> for mysql_async::Value {
fn conv(&self) -> OrmR<Option<u32>> {
let v = match self.clone() {
mysql_async::Value::NULL => None,
mysql_async::Value::Bytes(v) => Some(String::from_utf8(v)?.parse()?),
mysql_async::Value::Int(v) => Some(v as u32),
mysql_async::Value::UInt(v) => Some(v as u32),
mysql_async::Value::Float(v) => Some(v as u32),
mysql_async::Value::Double(v) => Some(v as u32),
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
impl ValueConv<usize> for mysql_async::Value {
fn conv(&self) -> OrmR<usize> {
let v = match self.clone() {
mysql_async::Value::NULL => 0,
mysql_async::Value::Bytes(v) => String::from_utf8(v)?.parse()?,
mysql_async::Value::Int(v) => v as usize,
mysql_async::Value::UInt(v) => v as usize,
mysql_async::Value::Float(v) => v as usize,
mysql_async::Value::Double(v) => v as usize,
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
impl ValueConv<Option<usize>> for mysql_async::Value {
fn conv(&self) -> OrmR<Option<usize>> {
let v = match self.clone() {
mysql_async::Value::NULL => None,
mysql_async::Value::Bytes(v) => Some(String::from_utf8(v)?.parse()?),
mysql_async::Value::Int(v) => Some(v as usize),
mysql_async::Value::UInt(v) => Some(v as usize),
mysql_async::Value::Float(v) => Some(v as usize),
mysql_async::Value::Double(v) => Some(v as usize),
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
impl ValueConv<u8> for mysql_async::Value {
fn conv(&self) -> OrmR<u8> {
let v = match self.clone() {
mysql_async::Value::NULL => 0,
mysql_async::Value::Bytes(v) => String::from_utf8(v)?.parse()?,
mysql_async::Value::Int(v) => v as u8,
mysql_async::Value::UInt(v) => v as u8,
mysql_async::Value::Float(v) => v as u8,
mysql_async::Value::Double(v) => v as u8,
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
impl ValueConv<Option<u8>> for mysql_async::Value {
fn conv(&self) -> OrmR<Option<u8>> {
let v = match self.clone() {
mysql_async::Value::NULL => None,
mysql_async::Value::Bytes(v) => Some(String::from_utf8(v)?.parse()?),
mysql_async::Value::Int(v) => Some(v as u8),
mysql_async::Value::UInt(v) => Some(v as u8),
mysql_async::Value::Float(v) => Some(v as u8),
mysql_async::Value::Double(v) => Some(v as u8),
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
impl ValueConv<i32> for mysql_async::Value {
fn conv(&self) -> OrmR<i32> {
let v = match self.clone() {
mysql_async::Value::NULL => 0,
mysql_async::Value::Bytes(v) => String::from_utf8(v)?.parse()?,
mysql_async::Value::Int(v) => v as i32,
mysql_async::Value::UInt(v) => v as i32,
mysql_async::Value::Float(v) => v as i32,
mysql_async::Value::Double(v) => v as i32,
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
impl ValueConv<Option<i32>> for mysql_async::Value {
fn conv(&self) -> OrmR<Option<i32>> {
let v = match self.clone() {
mysql_async::Value::NULL => None,
mysql_async::Value::Bytes(v) => Some(String::from_utf8(v)?.parse()?),
mysql_async::Value::Int(v) => Some(v as i32),
mysql_async::Value::UInt(v) => Some(v as i32),
mysql_async::Value::Float(v) => Some(v as i32),
mysql_async::Value::Double(v) => Some(v as i32),
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
impl ValueConv<i64> for mysql_async::Value {
fn conv(&self) -> OrmR<i64> {
let v = match self.clone() {
mysql_async::Value::NULL => 0,
mysql_async::Value::Bytes(v) => String::from_utf8(v)?.parse()?,
mysql_async::Value::Int(v) => v,
mysql_async::Value::UInt(v) => v as i64,
mysql_async::Value::Float(v) => v as i64,
mysql_async::Value::Double(v) => v as i64,
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
impl ValueConv<Option<i64>> for mysql_async::Value {
fn conv(&self) -> OrmR<Option<i64>> {
let v = match self.clone() {
mysql_async::Value::NULL => None,
mysql_async::Value::Bytes(v) => Some(String::from_utf8(v)?.parse()?),
mysql_async::Value::Int(v) => Some(v),
mysql_async::Value::UInt(v) => Some(v as i64),
mysql_async::Value::Float(v) => Some(v as i64),
mysql_async::Value::Double(v) => Some(v as i64),
other => Err(format!("ValueConv Error: {:?}", other))?,
};
Ok(v)
}
}
impl ValueConv<String> for mysql_async::Value {
fn conv(&self) -> OrmR<String> {
let v = match self.clone() {
mysql_async::Value::NULL => "".into(),
mysql_async::Value::Bytes(v) => String::from_utf8(v)?,
mysql_async::Value::Int(v) => v.to_string(),
mysql_async::Value::UInt(v) => v.to_string(),
mysql_async::Value::Float(v) => v.to_string(),
mysql_async::Value::Double(v) => v.to_string(),
other => format!("{:?}", other),
};
Ok(v)
}
}
impl ValueConv<Option<String>> for mysql_async::Value {
fn conv(&self) -> OrmR<Option<String>> {
let v = match self.clone() {
mysql_async::Value::NULL => return Ok(None),
mysql_async::Value::Bytes(v) => String::from_utf8(v)?,
mysql_async::Value::Int(v) => v.to_string(),
mysql_async::Value::UInt(v) => v.to_string(),
mysql_async::Value::Float(v) => v.to_string(),
mysql_async::Value::Double(v) => v.to_string(),
other => format!("{:?}", other),
};
Ok(Some(v))
}
}
}