Skip to main content

sqlx_repo/
migrator.rs

1use std::marker::PhantomData;
2
3use crate::{Result, SqlxDBNum};
4use futures::future::BoxFuture;
5use sqlx::{
6    SqlStr,
7    migrate::{Migration as SqlxMigration, MigrationSource, MigrationType},
8};
9
10#[derive(Debug)]
11pub struct RepoMigrationSource<D> {
12    migrations: Vec<Migration>,
13    marker: PhantomData<D>,
14}
15
16#[derive(Debug, Clone, Copy)]
17pub struct Migration {
18    pub name: &'static str,
19    pub queries: &'static [&'static str],
20}
21
22impl<'a, D: SqlxDBNum> MigrationSource<'a> for RepoMigrationSource<D> {
23    fn resolve(self) -> BoxFuture<'a, Result<Vec<SqlxMigration>, sqlx::error::BoxDynError>> {
24        Box::pin(async move {
25            let migrations = self.migrations
26                .iter()
27                .enumerate()
28                .map(|(pos, migration)| {
29                    let query_pos = D::pos();
30                    let query = match migration.queries.get(query_pos) {
31                        Some(&query) => query,
32                        None => Err("failed to generate migration, tried to get query at index {query_pos}, which doesn't exist")?
33                    };
34                    #[allow(clippy::cast_possible_wrap)]
35                    Ok(SqlxMigration::new(pos as _, migration.name.into(), MigrationType::Simple, SqlStr::from_static(query), false))
36                })
37                .collect::<Result<_>>()?;
38            Ok(migrations)
39        })
40    }
41}
42
43impl<D: SqlxDBNum> Default for RepoMigrationSource<D> {
44    fn default() -> Self {
45        Self::new()
46    }
47}
48
49impl<D: SqlxDBNum> RepoMigrationSource<D> {
50    pub fn new() -> Self {
51        Self {
52            migrations: vec![],
53            marker: PhantomData,
54        }
55    }
56
57    pub fn add_migration(&mut self, migration: Migration) {
58        self.migrations.push(migration);
59    }
60}
61
62pub async fn init_migrator<D: SqlxDBNum>(
63    migrations: &[Migration],
64) -> Result<sqlx::migrate::Migrator, sqlx::migrate::MigrateError> {
65    let mut source = RepoMigrationSource::<D>::new();
66    for migration in migrations {
67        source.add_migration(*migration);
68    }
69    sqlx::migrate::Migrator::new(source).await
70}