use mysql::*;
pub use mysql::{prelude::*, PooledConn, Transaction, TxOpts};
use serde::de::DeserializeOwned;
use std::fmt::Display;
#[derive(Debug)]
pub struct Sql<T: Into<String>>(pub T);
impl<T: Into<String> + Display> Display for Sql<T> {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(fmt, "Sql({})", self.0)
}
}
pub struct MysqlQuick {
pub pool: Pool,
}
impl MysqlQuick {
pub fn new(url: &str) -> anyhow::Result<MysqlQuick> {
let pool = Pool::new(url)?;
Ok(MysqlQuick { pool })
}
}
pub fn my_run_drop(conn: &mut PooledConn, sql: String) -> anyhow::Result<u64> {
conn.query_drop(sql)?;
Ok(conn.last_insert_id())
}
pub fn my_run_vec<U>(conn: &mut PooledConn, sql: String) -> anyhow::Result<Vec<U>>
where
U: DeserializeOwned,
{
let rows: Vec<Row> = conn.exec(sql, ())?;
let j_res: Vec<U> = rows_to_json(rows)?;
Ok(j_res)
}
pub fn my_run_tran_drop(tran: &mut Transaction, sql: String) -> anyhow::Result<u64> {
tran.query_drop(sql)?;
let id = tran.last_insert_id();
let id = if let Some(i) = id { i } else { 0 };
Ok(id)
}
pub fn my_run_tran_vec<U>(tran: &mut Transaction, sql: String) -> anyhow::Result<Vec<U>>
where
U: DeserializeOwned,
{
let rows: Vec<Row> = tran.exec(sql, ())?;
let j_res: Vec<U> = rows_to_json(rows)?;
Ok(j_res)
}
fn rows_to_json<U>(rows: Vec<Row>) -> anyhow::Result<Vec<U>>
where
U: DeserializeOwned,
{
if rows.len() == 0 {
return Ok(vec![]);
}
let mut j_st = String::from("[");
for row in rows.into_iter() {
let mut one = "{".to_string();
for column in row.columns_ref() {
let column_name = column.name_str().to_string();
let column_value = &row[column.name_str().as_ref()];
let tmp = row_value_as_string(column_value)?;
one = one + "\"" + column_name.as_str() + "\": " + tmp.as_str() + ",";
}
one.pop();
one.push('}');
one.push(',');
j_st = j_st + one.as_str();
}
j_st.pop();
j_st.push(']');
let json_result: Vec<U> = serde_json::from_str(j_st.as_str())?;
Ok(json_result)
}
fn row_value_as_string(value: &Value) -> anyhow::Result<String> {
match value {
Value::NULL => Ok(String::from("null")),
Value::Bytes(v) => {
let mut info = String::from_utf8_lossy(v.as_slice())
.into_owned()
.to_string();
info = serde_json::to_string(&info)?;
Ok(format!(r#"{info}"#))
}
Value::Int(v) => Ok(format!("{v}")),
Value::UInt(v) => Ok(format!("{v}")),
Value::Float(v) => Ok(format!("{v}")),
Value::Double(v) => Ok(format!("{v}")),
Value::Date(year, month, day, hour, minutes, seconds, _micro) => {
let m = if month < &10 {
format!("0{month}")
} else {
format!("{month}")
};
let d = if day < &10 {
format!("0{day}")
} else {
format!("{day}")
};
let h = if hour < &10 {
format!("0{hour}")
} else {
format!("{hour}")
};
let min = if minutes < &10 {
format!("0{minutes}")
} else {
format!("{minutes}")
};
let s = if seconds < &10 {
format!("0{seconds}")
} else {
format!("{seconds}")
};
Ok(format!("\"{year}-{m}-{d} {h}:{min}:{s}\""))
}
Value::Time(negative, days, hours, minutes, seconds, micro) => Ok(format!(
"\"{negative} {days} {hours}:{minutes}:{seconds}.{micro}\""
)),
}
}
fn _type_of<T>(_: T) -> &'static str {
std::any::type_name::<T>()
}