Skip to main content

doido_model/
tasks.rs

1//! Database task orchestration (Rails `db:reset`/`db:setup`/`db:prepare`),
2//! composing the schema/seed primitives.
3
4use crate::schema;
5use crate::sea_orm::{ConnectionTrait, DatabaseConnection, DbBackend, Statement};
6use doido_core::Result;
7
8/// Drop every user table in a SQLite database.
9pub async fn drop_all_tables(conn: &DatabaseConnection) -> Result<()> {
10    let stmt = Statement::from_string(
11        DbBackend::Sqlite,
12        "SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'",
13    );
14    let rows = conn
15        .query_all_raw(stmt)
16        .await
17        .map_err(|e| doido_core::anyhow::anyhow!("list tables failed: {e}"))?;
18    for row in rows {
19        let name: String = row
20            .try_get("", "name")
21            .map_err(|e| doido_core::anyhow::anyhow!("table row: {e}"))?;
22        conn.execute_unprepared(&format!("DROP TABLE IF EXISTS \"{name}\""))
23            .await
24            .map_err(|e| doido_core::anyhow::anyhow!("drop {name} failed: {e}"))?;
25    }
26    Ok(())
27}
28
29/// `db:reset` — drop everything, then load `schema`.
30pub async fn reset(conn: &DatabaseConnection, schema: &str) -> Result<()> {
31    drop_all_tables(conn).await?;
32    schema::load(conn, schema).await
33}
34
35/// `db:setup` — load `schema`, then run the seeder.
36pub async fn setup(
37    conn: &DatabaseConnection,
38    schema: &str,
39    seeder: impl AsyncFnOnce(&DatabaseConnection) -> Result<()>,
40) -> Result<()> {
41    schema::load(conn, schema).await?;
42    seeder(conn).await
43}
44
45/// `db:prepare` — load `schema` only if the database has no user tables yet
46/// (idempotent).
47pub async fn prepare(conn: &DatabaseConnection, schema: &str) -> Result<()> {
48    let stmt = Statement::from_string(
49        DbBackend::Sqlite,
50        "SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'",
51    );
52    let rows = conn
53        .query_all_raw(stmt)
54        .await
55        .map_err(|e| doido_core::anyhow::anyhow!("list tables failed: {e}"))?;
56    if rows.is_empty() {
57        schema::load(conn, schema).await?;
58    }
59    Ok(())
60}