use {
crate::use_m::*,
mysql::{
params::Params,
prelude::{FromRow, Queryable},
OptsBuilder, Pool, PooledConn,
},
std::sync::MutexGuard,
};
pub trait CreateDbPool {
fn lock() -> Result<MutexGuard<'static, DbPool>, MoreError>;
}
#[cfg(feature = "use_sql")]
pub struct DbPool {
pool: Option<Pool>,
args: &'static DbPoolArgs,
}
#[cfg(feature = "use_sql")]
impl DbPool {
#[auto_func_name]
fn _create(&mut self) -> Result<Pool, MoreError> {
match &self.pool {
Some(pool) => Ok(pool.clone()),
None => {
let opts = OptsBuilder::new()
.ip_or_hostname(Some(&self.args.ip_or_hostname))
.tcp_port(self.args.port)
.user(Some(&self.args.user))
.pass(Some(&self.args.password))
.db_name(Some(&self.args.db_name));
let pool = Pool::new_manual(3, 5, opts).m(m!(fname))?;
self.pool = Some(pool.clone());
Ok(pool)
}
}
}
#[auto_func_name]
fn _get(&mut self) -> Result<PooledConn, MoreError> {
self._create().m(m!(fname))?.get_conn().m(m!(fname))
}
#[auto_func_name]
fn get_id(&mut self, sql: &str, params: Params) -> Result<Option<u64>, MoreError>
where
Self: 'static,
{
self._get()
.m(m!(fname))?
.exec_iter(sql, ¶ms)
.map(|x| x.last_insert_id())
.f(m!(fname, || { format!("{} {:?}", sql, params) }))
}
#[auto_func_name]
fn get_nothing(&mut self, sql: &str, params: Params) -> Result<(), MoreError>
where
Self: 'static,
{
self._get()
.m(m!(fname))?
.exec_drop(sql, ¶ms)
.f(m!(fname, || { format!("{}: {:?}", sql, ¶ms) }))
}
pub fn new(args: &'static DbPoolArgs) -> Self {
Self { pool: None, args }
}
}
#[derive(Default)]
pub struct DbPoolArgs {
pub ip_or_hostname: String, pub port: u16, pub user: String, pub password: String, pub db_name: String, }
pub trait SqlModel {
fn equal(&self, other: &Self) -> bool;
fn equal_without_id(&self, other: &Self) -> bool;
fn lock() -> Result<MutexGuard<'static, DbPool>, MoreError>;
fn make_create_table() -> &'static str;
fn make_fields_b() -> &'static str;
fn make_fields_bi() -> &'static str;
fn make_fields_e() -> &'static str;
fn make_fields_ei() -> &'static str;
fn make_fields_p() -> &'static str;
fn make_fields_pi() -> &'static str;
fn make_fields_q() -> &'static str;
fn make_fields_qc() -> &'static str;
fn make_fields_v(&self) -> Params;
fn make_fields_vi(&self) -> Params;
fn table_name() -> &'static str;
#[auto_func_name]
fn create(&self) -> Result<Option<u64>, MoreError> {
Self::lock()
.m(m!(fname))?
.get_id(
&format!(
"INSERT INTO {} ({}) VALUES ({})",
Self::table_name(),
Self::make_fields_bi(),
Self::make_fields_pi(),
),
self.make_fields_vi(),
)
.m(m!(fname))
}
#[auto_func_name]
fn delete(condition: &str, params: Params) -> Result<(), MoreError> {
Self::lock()
.m(m!(fname))?
.get_nothing(
&format!("DELETE FROM {} WHERE {}", Self::table_name(), condition),
params,
)
.m(m!(fname))
}
#[auto_func_name]
fn get_row<T>(sql: &str, params: Params) -> Result<Option<T>, MoreError>
where
Self: 'static,
T: FromRow,
{
match Self::lock()
.m(m!(fname))?
._get()
.m(m!(fname))?
.exec_first_opt(sql, ¶ms)
.f(m!(fname, || { format!("{}: {:?}", sql, ¶ms) }))?
{
Some(Ok(row)) => Ok(Some(row)),
Some(Err(err)) => Err(err).m(m!(fname)),
None => Ok(None),
}
}
#[auto_func_name]
fn get_rows<T>(sql: &str, params: Params) -> Result<Vec<T>, MoreError>
where
Self: 'static,
T: FromRow,
{
let rows = Self::lock()
.m(m!(fname))?
._get()
.m(m!(fname))?
.exec_opt(sql, ¶ms)
.f(m!(fname, || { format!("{}: {:?}", sql, ¶ms) }))?;
for (i, row) in rows.iter().enumerate() {
if let Err(err) = row {
return Err(err).f(m!(fname, || { format!("{}: {:?}, row[{}]", sql, ¶ms, i) }));
}
}
Ok(rows.into_iter().map(|x| x.unwrap()).collect())
}
#[auto_func_name]
fn save_as(&self, id: u32) -> Result<(), MoreError> {
Self::lock()
.m(m!(fname))?
.get_nothing(
&format!(
"UPDATE {} SET {} WHERE id={}",
Self::table_name(),
Self::make_fields_ei(),
id
),
self.make_fields_vi(),
)
.m(m!(fname))
}
#[auto_func_name]
fn select_one(where_sql: &str, params: Params) -> Result<Option<Self>, MoreError>
where
Self: 'static + Sized + FromRow,
{
match Self::lock()
.m(m!(fname))?
._get()
.m(m!(fname))?
.exec_first_opt(
&format!(
"SELECT {} FROM {} {}",
Self::make_fields_b(),
Self::table_name(),
where_sql
),
¶ms,
)
.f(m!(fname, || { format!("{}: {:?}", where_sql, ¶ms) }))?
{
Some(Ok(row)) => Ok(Some(row)),
Some(Err(err)) => Err(err).m(m!(fname)),
None => Ok(None),
}
}
#[auto_func_name]
fn select_some(where_sql: &str, params: Params) -> Result<Vec<Self>, MoreError>
where
Self: 'static + Sized + FromRow,
{
let rows = Self::lock()
.m(m!(fname))?
._get()
.m(m!(fname))?
.exec_opt(
&format!(
"SELECT {} FROM {} {}",
Self::make_fields_b(),
Self::table_name(),
where_sql
),
¶ms,
)
.f(m!(fname, || { format!("{}: {:?}", where_sql, ¶ms) }))?;
for (i, row) in rows.iter().enumerate() {
if let Err(err) = row {
return Err(err).f(m!(fname, || { format!("{}: {:?}, row[{}]", where_sql, ¶ms, i) }));
}
}
Ok(rows.into_iter().map(|x| x.unwrap()).collect())
}
#[auto_func_name]
fn update(fields_ei: &str, condition: &str, params: Params) -> Result<(), MoreError> {
Self::lock()
.m(m!(fname))?
.get_nothing(
&format!("UPDATE {} SET {} WHERE {}", Self::table_name(), fields_ei, condition),
params,
)
.m(m!(fname))
}
}