soma_schema/driver.rs
1use async_trait::async_trait;
2use chrono::{DateTime, Utc};
3
4use crate::error::Result;
5use crate::migration::Migration;
6
7/// A deployed migration row from the tracking table.
8#[non_exhaustive]
9#[derive(Debug)]
10pub struct AppliedMigration {
11 pub version: u32,
12 pub file: String,
13 pub name: String,
14 pub checksum: String,
15 pub description: Option<String>,
16 pub batch: i32,
17 pub applied_at: DateTime<Utc>,
18 pub applied_by: String,
19 pub execution_ms: Option<i32>,
20}
21
22impl AppliedMigration {
23 /// Construct a tracking-table row.
24 ///
25 /// Driver implementations use this inside `applied()` to build rows from
26 /// whatever backing store they query. The `#[non_exhaustive]` attribute on
27 /// the struct means struct-literal syntax is unavailable to external crates;
28 /// this constructor is the supported path for building `AppliedMigration` values.
29 #[allow(clippy::too_many_arguments)]
30 pub fn new(
31 version: u32,
32 file: String,
33 name: String,
34 checksum: String,
35 description: Option<String>,
36 batch: i32,
37 applied_at: DateTime<Utc>,
38 applied_by: String,
39 execution_ms: Option<i32>,
40 ) -> Self {
41 Self {
42 version,
43 file,
44 name,
45 checksum,
46 description,
47 batch,
48 applied_at,
49 applied_by,
50 execution_ms,
51 }
52 }
53}
54
55/// A lock guard. Releases the advisory lock on Drop.
56/// The concrete implementation keeps a dedicated connection alive.
57pub trait LockGuard: Send + Sync {}
58
59/// Object-safe driver trait. Implement for each database backend.
60#[async_trait]
61pub trait MigrationDriver: Send + Sync {
62 /// Acquire an advisory lock. The lock is held until the returned guard is dropped.
63 async fn acquire_lock(&self) -> Result<Box<dyn LockGuard>>;
64
65 /// Execute one 00_setup file's SQL in a single transaction (untracked).
66 async fn run_setup_sql(&self, name: &str, sql: &str) -> Result<()>;
67
68 /// Ensure the deployment tracking table (and schema, if configured) exist.
69 async fn ensure_tracking_table(&self) -> Result<()>;
70
71 /// Return all applied migrations, ordered by (version ASC, file ASC).
72 async fn applied(&self) -> Result<Vec<AppliedMigration>>;
73
74 /// Apply a migration: run UP SQL AND insert the tracking row in ONE transaction.
75 /// The `up_sql` is passed in rather than re-reading the file in the driver.
76 async fn apply(&self, migration: &Migration, up_sql: &str, batch: i32) -> Result<()>;
77
78 /// Revert an applied migration: run `down_sql` AND delete the tracking row in ONE transaction.
79 async fn revert(&self, applied: &AppliedMigration, down_sql: &str) -> Result<()>;
80}