use crate::{DbError, DjogiError};
use deadpool_postgres::Object;
use postgres_types::ToSql;
use tokio_postgres::{Row, Statement};
pub struct PgConnection {
obj: Option<Object>,
}
#[allow(clippy::disallowed_methods)]
impl PgConnection {
pub fn new(obj: Object) -> Self {
PgConnection { obj: Some(obj) }
}
pub(crate) fn detach(self) {
if let Some(obj) = self.obj {
let _client_wrapper = Object::take(obj);
}
}
pub(crate) fn detach_mut(&mut self) {
if let Some(obj) = std::mem::take(&mut self.obj) {
let _client_wrapper = Object::take(obj);
}
}
fn obj_mut(&mut self) -> &mut Object {
self.obj.as_mut().expect("PgConnection used after detach")
}
pub async fn prepare_cached(&mut self, sql: &str) -> Result<Statement, DjogiError> {
self.obj_mut()
.prepare_cached(sql)
.await
.map_err(|e| DjogiError::Db(DbError::other(e.to_string())))
}
pub async fn batch_execute(&mut self, sql: &str) -> Result<(), DjogiError> {
self.obj_mut()
.batch_execute(sql)
.await
.map_err(pg_err_to_djogi)
}
pub async fn query(
&mut self,
sql: &str,
params: &[&(dyn ToSql + Sync)],
) -> Result<Vec<Row>, DjogiError> {
let stmt = self.prepare_cached(sql).await?;
self.obj_mut()
.query(&stmt, params)
.await
.map_err(pg_err_to_djogi)
}
pub async fn query_opt(
&mut self,
sql: &str,
params: &[&(dyn ToSql + Sync)],
) -> Result<Option<Row>, DjogiError> {
let stmt = self.prepare_cached(sql).await?;
self.obj_mut()
.query_opt(&stmt, params)
.await
.map_err(pg_err_to_djogi)
}
pub async fn query_one(
&mut self,
sql: &str,
params: &[&(dyn ToSql + Sync)],
) -> Result<Row, DjogiError> {
let stmt = self.prepare_cached(sql).await?;
self.obj_mut()
.query_one(&stmt, params)
.await
.map_err(pg_err_to_djogi)
}
pub async fn execute(
&mut self,
sql: &str,
params: &[&(dyn ToSql + Sync)],
) -> Result<u64, DjogiError> {
let stmt = self.prepare_cached(sql).await?;
self.obj_mut()
.execute(&stmt, params)
.await
.map_err(pg_err_to_djogi)
}
}
pub(crate) fn pg_err_to_djogi(e: tokio_postgres::Error) -> DjogiError {
crate::error::map_pg_err(e)
}