use crate::config::filter::ObjectFilter;
use crate::config::types::{Objects, TrackingTable};
use crate::render::quote_ident;
use once_cell::sync::Lazy;
use sqlx::{Executor, PgPool, Row};
use std::collections::HashSet;
use std::format;
use std::sync::Mutex;
use tracing::debug;
static BRANCH_PROVISIONED: Lazy<Mutex<HashSet<(String, u16, String)>>> =
Lazy::new(|| Mutex::new(HashSet::new()));
pub fn mark_branch_provisioned(host: &str, port: u16, database: &str) {
BRANCH_PROVISIONED
.lock()
.unwrap()
.insert((host.to_string(), port, database.to_string()));
}
fn is_branch_provisioned(pool: &PgPool) -> bool {
let options = pool.connect_options();
let key = (
options.get_host().to_string(),
options.get_port(),
options.get_database().unwrap_or_default().to_string(),
);
BRANCH_PROVISIONED.lock().unwrap().contains(&key)
}
pub fn take_branch_provisioned(host: &str, port: u16, database: &str) -> bool {
BRANCH_PROVISIONED
.lock()
.unwrap()
.remove(&(host.to_string(), port, database.to_string()))
}
pub async fn clean_shadow_db(pool: &PgPool, objects: &Objects) -> anyhow::Result<()> {
if is_branch_provisioned(pool) {
debug!("Shadow is a fresh branch of its source; skipping clean");
return Ok(());
}
let filter = ObjectFilter::new(objects, &TrackingTable::default());
let schemas = sqlx::query(
"SELECT schema_name
FROM information_schema.schemata
WHERE schema_name NOT IN ('pg_catalog', 'information_schema', 'pg_toast', 'pg_temp_1', 'pg_toast_temp_1')"
)
.fetch_all(pool)
.await?;
for row in schemas {
let schema_name: &str = row.get("schema_name");
if filter.should_include_schema(schema_name) {
let quoted = quote_ident(schema_name);
let reassign = format!("ALTER SCHEMA {} OWNER TO CURRENT_USER", quoted);
let drop_stmt = format!("DROP SCHEMA IF EXISTS {} CASCADE", quoted);
pool.execute(reassign.as_str()).await?;
pool.execute(drop_stmt.as_str()).await?;
} else {
debug!("Preserving non-managed schema: {}", schema_name);
}
}
pool.execute("CREATE SCHEMA IF NOT EXISTS public").await?;
pool.execute("GRANT ALL ON SCHEMA public TO PUBLIC").await?;
Ok(())
}