#![deny(missing_docs)]
mod config;
mod db;
use sqlx::Executor;
pub use crate::config::Config as DbConfig;
pub use crate::db::DB;
pub async fn ensure(app_name: &str, cfgs: &[&DbConfig]) -> anyhow::Result<()> {
for cfg in cfgs {
let db = DB::new_root(app_name, cfg).await?;
let query_args = ::core::result::Result::<_, ::sqlx::error::BoxDynError>::Ok(
<sqlx::postgres::Postgres as ::sqlx::database::Database>::Arguments::default(),
);
let databases: Vec<String> =
sqlx::__query_with_result("SELECT datname FROM pg_database;", query_args)
.try_map(|v: sqlx::postgres::PgRow| {
use ::sqlx::Row as _;
v.try_get_unchecked::<String, _>(0usize)
})
.fetch_all(db.pool())
.await?;
if let Some(database) = cfg.database() {
if !databases.iter().any(|datname| datname == database) {
let q = format!("CREATE DATABASE {database}");
db.pool().execute(sqlx::AssertSqlSafe(q)).await?;
}
}
if let Some((username, password)) = cfg.username().zip(cfg.password()) {
let query_args = ::core::result::Result::<_, ::sqlx::error::BoxDynError>::Ok(
<sqlx::postgres::Postgres as ::sqlx::database::Database>::Arguments::default(),
);
let users: Vec<Option<String>> =
sqlx::__query_with_result("SELECT usename FROM pg_catalog.pg_user;", query_args)
.try_map(|v: sqlx::postgres::PgRow| {
use ::sqlx::Row as _;
v.try_get_unchecked::<Option<String>, _>(0usize)
})
.fetch_all(db.pool())
.await?;
if !users
.iter()
.any(|usename| usename.as_deref() == Some(username))
{
let q = format!("CREATE USER {username} WITH SUPERUSER PASSWORD '{password}'");
db.pool().execute(sqlx::AssertSqlSafe(q)).await?;
}
}
}
Ok(())
}