diff --git a/sqlx-cli/src/database.rs b/sqlx-cli/src/database.rs index 1970826b..6babb21a 100644 --- a/sqlx-cli/src/database.rs +++ b/sqlx-cli/src/database.rs @@ -40,5 +40,5 @@ pub async fn reset(migration_source: &str, uri: &str, confirm: bool) -> anyhow:: pub async fn setup(migration_source: &str, uri: &str) -> anyhow::Result<()> { create(uri).await?; - migrate::run(migration_source, uri, false).await + migrate::run(migration_source, uri, false, false).await } diff --git a/sqlx-cli/src/lib.rs b/sqlx-cli/src/lib.rs index 2dae5520..7ff1cf0c 100644 --- a/sqlx-cli/src/lib.rs +++ b/sqlx-cli/src/lib.rs @@ -27,12 +27,14 @@ pub async fn run(opt: Opt) -> anyhow::Result<()> { description, reversible, } => migrate::add(&migrate.source, &description, reversible).await?, - MigrateCommand::Run { dry_run } => { - migrate::run(&migrate.source, &database_url, dry_run).await? - } - MigrateCommand::Revert { dry_run } => { - migrate::revert(&migrate.source, &database_url, dry_run).await? - } + MigrateCommand::Run { + dry_run, + ignore_missing, + } => migrate::run(&migrate.source, &database_url, dry_run, ignore_missing).await?, + MigrateCommand::Revert { + dry_run, + ignore_missing, + } => migrate::revert(&migrate.source, &database_url, dry_run, ignore_missing).await?, MigrateCommand::Info => migrate::info(&migrate.source, &database_url).await?, }, diff --git a/sqlx-cli/src/migrate.rs b/sqlx-cli/src/migrate.rs index d75746dd..20d61f19 100644 --- a/sqlx-cli/src/migrate.rs +++ b/sqlx-cli/src/migrate.rs @@ -109,7 +109,12 @@ pub async fn info(migration_source: &str, uri: &str) -> anyhow::Result<()> { fn validate_applied_migrations( applied_migrations: &[AppliedMigration], migrator: &Migrator, + ignore_missing: bool, ) -> Result<(), MigrateError> { + if ignore_missing { + return Ok(()); + } + let migrations: HashSet<_> = migrator.iter().map(|m| m.version).collect(); for applied_migration in applied_migrations { @@ -121,7 +126,12 @@ fn validate_applied_migrations( Ok(()) } -pub async fn run(migration_source: &str, uri: &str, dry_run: bool) -> anyhow::Result<()> { +pub async fn run( + migration_source: &str, + uri: &str, + dry_run: bool, + ignore_missing: bool, +) -> anyhow::Result<()> { let migrator = Migrator::new(Path::new(migration_source)).await?; let mut conn = AnyConnection::connect(uri).await?; @@ -133,7 +143,7 @@ pub async fn run(migration_source: &str, uri: &str, dry_run: bool) -> anyhow::Re } let applied_migrations = conn.list_applied_migrations().await?; - validate_applied_migrations(&applied_migrations, &migrator)?; + validate_applied_migrations(&applied_migrations, &migrator, ignore_missing)?; let applied_migrations: HashMap<_, _> = applied_migrations .into_iter() @@ -175,7 +185,12 @@ pub async fn run(migration_source: &str, uri: &str, dry_run: bool) -> anyhow::Re Ok(()) } -pub async fn revert(migration_source: &str, uri: &str, dry_run: bool) -> anyhow::Result<()> { +pub async fn revert( + migration_source: &str, + uri: &str, + dry_run: bool, + ignore_missing: bool, +) -> anyhow::Result<()> { let migrator = Migrator::new(Path::new(migration_source)).await?; let mut conn = AnyConnection::connect(uri).await?; @@ -187,7 +202,7 @@ pub async fn revert(migration_source: &str, uri: &str, dry_run: bool) -> anyhow: } let applied_migrations = conn.list_applied_migrations().await?; - validate_applied_migrations(&applied_migrations, &migrator)?; + validate_applied_migrations(&applied_migrations, &migrator, ignore_missing)?; let applied_migrations: HashMap<_, _> = applied_migrations .into_iter() diff --git a/sqlx-cli/src/opt.rs b/sqlx-cli/src/opt.rs index 594981ef..72958f26 100644 --- a/sqlx-cli/src/opt.rs +++ b/sqlx-cli/src/opt.rs @@ -111,6 +111,10 @@ pub enum MigrateCommand { /// List all the migrations to be run without applying #[clap(long)] dry_run: bool, + + /// Ignore applied migrations that missing in the resolved migrations + #[clap(long)] + ignore_missing: bool, }, /// Revert the latest migration with a down file. @@ -118,6 +122,10 @@ pub enum MigrateCommand { /// List the migration to be reverted without applying #[clap(long)] dry_run: bool, + + /// Ignore applied migrations that missing in the resolved migrations + #[clap(long)] + ignore_missing: bool, }, /// List all available migrations. diff --git a/sqlx-core/src/migrate/migrator.rs b/sqlx-core/src/migrate/migrator.rs index dc77fe7c..2669dd72 100644 --- a/sqlx-core/src/migrate/migrator.rs +++ b/sqlx-core/src/migrate/migrator.rs @@ -8,12 +8,17 @@ use std::slice; #[derive(Debug)] pub struct Migrator { pub migrations: Cow<'static, [Migration]>, + pub ignore_missing: bool, } fn validate_applied_migrations( applied_migrations: &[AppliedMigration], migrator: &Migrator, ) -> Result<(), MigrateError> { + if migrator.ignore_missing { + return Ok(()); + } + let migrations: HashSet<_> = migrator.iter().map(|m| m.version).collect(); for applied_migration in applied_migrations { @@ -50,9 +55,15 @@ impl Migrator { { Ok(Self { migrations: Cow::Owned(source.resolve().await.map_err(MigrateError::Source)?), + ignore_missing: false, }) } + /// Specify should ignore applied migrations that missing in the resolved migrations. + pub fn set_ignore_missing(&mut self, ignore_missing: bool) { + self.ignore_missing = ignore_missing; + } + /// Get an iterator over all known migrations. pub fn iter(&self) -> slice::Iter<'_, Migration> { self.migrations.iter()