Skip to main content

force_sync/store/pg/
migrate.rs

1//! Embedded Postgres migration runner for force-sync.
2
3use deadpool_postgres::Pool;
4
5use crate::error::ForceSyncError;
6
7const MIGRATIONS: &[(i32, &str)] = &[
8    (1, include_str!("../../../migrations/0001_init.sql")),
9    (
10        2,
11        include_str!("../../../migrations/0002_force_sync_outbox.sql"),
12    ),
13];
14
15/// Applies the force-sync schema migrations in version order.
16///
17/// # Errors
18///
19/// Returns a database or pool error if the migration cannot be applied.
20pub async fn migrate(pool: &Pool) -> Result<(), ForceSyncError> {
21    let mut client = pool.get().await?;
22    let transaction = client.transaction().await?;
23
24    let mut migration_table_exists: bool = transaction
25        .query_one(
26            "select to_regclass('public.force_sync_schema_migrations') is not null",
27            &[],
28        )
29        .await?
30        .get(0);
31
32    for &(version, sql) in MIGRATIONS {
33        let already_applied = if migration_table_exists {
34            transaction
35                .query_opt(
36                    "select 1 from force_sync_schema_migrations where version = $1",
37                    &[&version],
38                )
39                .await?
40                .is_some()
41        } else {
42            false
43        };
44
45        if already_applied {
46            continue;
47        }
48
49        transaction.batch_execute(sql).await?;
50        migration_table_exists = true;
51    }
52
53    transaction.commit().await?;
54    Ok(())
55}