use super::postgresql::postgre_interface::{create_postgre_interface, get_postgre_interface};
use crate::database::errors::DatabaseError;
use crate::database::queries_result_views::utils::QueryResult;
use crate::database::QUERY;
use async_trait::async_trait;
use std::error::Error;
use std::sync::{LazyLock, Mutex};
use tokio_postgres::Client;
static DB_INTERFACE: LazyLock<Mutex<Option<DbInterface>>> = LazyLock::new(|| Mutex::new(None));
pub async fn init_db_interface() {
let db_interface = DbInterface::new().await;
let mut guard = DB_INTERFACE.lock().unwrap();
*guard = Some(db_interface);
}
pub fn get_db_interface() -> &'static Mutex<Option<DbInterface>> {
&DB_INTERFACE
}
pub trait QueryResultView {
fn get_result(&self) -> QueryResult;
}
pub trait DatabaseQueryView: Send {
fn get_request(&self) -> String;
fn get_raw_request(&self) -> String;
fn get_query_type(&self) -> QUERY;
}
#[async_trait]
pub trait Query {
type Output: QueryResultView;
type Error: Error + Send + Sync + 'static;
async fn execute(&self, client: &Client) -> Result<Self::Output, Self::Error>;
}
#[async_trait]
pub trait DatabaseInterfaceActions: Send {
async fn connect(&mut self) -> Result<String, DatabaseError>;
async fn disconnect(&mut self) -> Result<String, DatabaseError>;
async fn execute_query<Q>(&self, query: Q) -> Result<Q::Output, Box<dyn Error + Send + Sync>>
where
Q: Query + Send + 'static;
}
pub struct DbInterface {
}
impl DbInterface {
pub async fn new() -> Self {
create_postgre_interface().await;
DbInterface {}
}
pub async fn connect(&mut self) -> Result<String, DatabaseError> {
let mut guard = get_postgre_interface().await;
if let Some(ref mut postgre_interface) = *guard {
match postgre_interface.connect().await {
Ok(message) => Ok(message),
Err(e) => Err(e),
}
} else {
Err(DatabaseError::Internal(
"PostgreInterface not initialized".to_string(),
))
}
}
pub async fn disconnect(&mut self) -> Result<String, DatabaseError> {
let mut guard = get_postgre_interface().await;
if let Some(ref mut postgre_interface) = *guard {
match postgre_interface.disconnect().await {
Ok(message) => Ok(message),
Err(e) => Err(e),
}
} else {
Err(DatabaseError::Internal(
"PostgreInterface not initialized".to_string(),
))
}
}
pub async fn execute_query<Q>(
&self,
query: Q,
) -> Result<Q::Output, Box<dyn Error + Send + Sync>>
where
Q: Query + Send + 'static,
{
let guard = get_postgre_interface().await;
if let Some(ref postgre_interface) = *guard {
postgre_interface.execute_query(query).await
} else {
Err(Box::new(DatabaseError::Internal(
"PostgreInterface not initialized".to_string(),
)) as Box<dyn Error + Send + Sync>)
}
}
}