Skip to main content

doido_model/
schema.rs

1//! Schema dump/load (Rails `db:schema:dump` / `db:schema:load`). `dump` reads a
2//! SQLite database's table definitions; `load` replays them into a database.
3
4use crate::sea_orm::{ConnectionTrait, DatabaseConnection, DbBackend, Statement};
5use doido_core::Result;
6
7/// Dump the SQLite schema: the `CREATE TABLE` statements, one per line.
8pub async fn dump(conn: &DatabaseConnection) -> Result<String> {
9    let stmt = Statement::from_string(
10        DbBackend::Sqlite,
11        "SELECT sql FROM sqlite_master WHERE type = 'table' \
12         AND name NOT LIKE 'sqlite_%' AND sql IS NOT NULL ORDER BY name",
13    );
14    let rows = conn
15        .query_all_raw(stmt)
16        .await
17        .map_err(|e| doido_core::anyhow::anyhow!("schema dump failed: {e}"))?;
18    let mut out = String::new();
19    for row in rows {
20        let sql: String = row
21            .try_get("", "sql")
22            .map_err(|e| doido_core::anyhow::anyhow!("schema row: {e}"))?;
23        out.push_str(sql.trim());
24        out.push_str(";\n");
25    }
26    Ok(out)
27}
28
29/// Load a schema (as produced by [`dump`]) into `conn`, executing each statement.
30pub async fn load(conn: &DatabaseConnection, schema: &str) -> Result<()> {
31    for statement in schema.split(';') {
32        let sql = statement.trim();
33        if sql.is_empty() {
34            continue;
35        }
36        conn.execute_unprepared(sql)
37            .await
38            .map_err(|e| doido_core::anyhow::anyhow!("schema load failed on `{sql}`: {e}"))?;
39    }
40    Ok(())
41}