#![expect(deprecated)]
use deadpool_postgres::*;
use eyre::*;
use postgres_from_row::FromRow;
use secrecy::SecretString;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::path::Path;
use std::process::Command;
use std::time::Duration;
pub use tokio_postgres::Row;
pub use tokio_postgres::types::ToSql;
mod data_thread;
mod pooled;
pub use data_thread::*;
pub use pooled::*;
use super::datatable::RDataTable;
#[derive(Clone, Debug, Default, Deserialize)]
pub struct DatabaseConfig {
pub user: Option<String>,
pub password: Option<SecretString>,
pub dbname: Option<String>,
pub options: Option<String>,
pub application_name: Option<String>,
pub ssl_mode: Option<SslMode>,
pub host: Option<String>,
pub hosts: Option<Vec<String>>,
pub port: Option<u16>,
pub ports: Option<Vec<u16>>,
pub connect_timeout: Option<Duration>,
pub keepalives: Option<bool>,
pub keepalives_idle: Option<Duration>,
pub target_session_attrs: Option<TargetSessionAttrs>,
pub channel_binding: Option<ChannelBinding>,
pub manager: Option<ManagerConfig>,
pub pool: Option<PoolConfig>,
}
pub trait DatabaseRequest: Send {
type ResponseRow: Send + Sync + Clone + Serialize + DeserializeOwned + FromRow;
fn statement(&self) -> &str;
fn params(&self) -> Vec<&(dyn ToSql + Sync)>;
}
pub type DatabaseRequestBoxed = Box<dyn DatabaseRequest<ResponseRow = Row>>;
#[derive(Clone)]
pub enum DbClient {
Pooled(PooledDbClient),
Threaded(ThreadedDbClient),
}
impl From<PooledDbClient> for DbClient {
fn from(client: PooledDbClient) -> Self {
Self::Pooled(client)
}
}
impl From<ThreadedDbClient> for DbClient {
fn from(value: ThreadedDbClient) -> Self {
Self::Threaded(value)
}
}
impl DbClient {
pub async fn execute<T>(&self, req: T) -> Result<RDataTable<T::ResponseRow>>
where
T: DatabaseRequest + Sync + Send + Debug + 'static,
T::ResponseRow: FromRow + Sync + Send + Clone + Debug + Sized + 'static,
{
match self {
DbClient::Pooled(client) => client.execute(req).await,
DbClient::Threaded(client) => client.execute(req).await,
}
}
}
pub fn database_test_config() -> DatabaseConfig {
DatabaseConfig {
user: Some("postgres".to_string()),
password: Some("123456".to_string().into()),
dbname: Some("red_alert".to_string()),
host: Some("localhost".to_string()),
..Default::default()
}
}
pub fn drop_and_recreate_database() -> Result<()> {
let script = Path::new("scripts/drop_and_recreate_database.sh");
Command::new("bash")
.arg(script)
.arg("etc/config.json")
.status()?;
Ok(())
}