qm_pg/
lib.rs

1mod config;
2mod db;
3
4use sqlx::Executor;
5
6pub use crate::config::Config as DbConfig;
7pub use crate::db::DB;
8
9pub async fn ensure(app_name: &str, cfgs: &[&DbConfig]) -> anyhow::Result<()> {
10    for cfg in cfgs {
11        let db = DB::new_root(app_name, cfg).await?;
12        let query_args = ::core::result::Result::<_, ::sqlx::error::BoxDynError>::Ok(
13            <sqlx::postgres::Postgres as ::sqlx::database::Database>::Arguments::<'_>::default(),
14        );
15        let databases: Vec<String> =
16            sqlx::__query_with_result("SELECT datname FROM pg_database;", query_args)
17                .try_map(|v: sqlx::postgres::PgRow| {
18                    use ::sqlx::Row as _;
19                    v.try_get_unchecked::<String, _>(0usize)
20                })
21                .fetch_all(db.pool())
22                .await?;
23
24        if let Some(database) = cfg.database() {
25            if !databases.iter().any(|datname| datname == database) {
26                db.pool()
27                    .execute(format!("CREATE DATABASE {database}").as_str())
28                    .await?;
29            }
30        }
31
32        if let Some((username, password)) = cfg.username().zip(cfg.password()) {
33            let query_args = ::core::result::Result::<_, ::sqlx::error::BoxDynError>::Ok(
34                <sqlx::postgres::Postgres as ::sqlx::database::Database>::Arguments::<'_>::default(
35                ),
36            );
37            let users: Vec<Option<String>> =
38                sqlx::__query_with_result("SELECT usename FROM pg_catalog.pg_user;", query_args)
39                    .try_map(|v: sqlx::postgres::PgRow| {
40                        use ::sqlx::Row as _;
41                        v.try_get_unchecked::<Option<String>, _>(0usize)
42                    })
43                    .fetch_all(db.pool())
44                    .await?;
45            if !users
46                .iter()
47                .any(|usename| usename.as_deref() == Some(username))
48            {
49                db.pool()
50                    .execute(
51                        format!("CREATE USER {username} WITH SUPERUSER PASSWORD '{password}'")
52                            .as_str(),
53                    )
54                    .await?;
55            }
56        }
57    }
58    Ok(())
59}