diff --git a/migra/src/clients/mysql.rs b/migra/src/clients/mysql.rs index f2164ab..18f921e 100644 --- a/migra/src/clients/mysql.rs +++ b/migra/src/clients/mysql.rs @@ -70,8 +70,11 @@ impl ManageMigrations for Client { .map_err(|_| Error::FailedDeleteMigration) } - fn applied_migrations(&mut self) -> MigraResult { - let stmt = format!("SELECT name FROM {}", &self.migrations_table_name); + fn get_applied_migrations(&mut self) -> MigraResult { + let stmt = format!( + "SELECT name FROM {} ORDER BY id DESC", + &self.migrations_table_name + ); self.conn .query::(stmt) diff --git a/migra/src/clients/postgres.rs b/migra/src/clients/postgres.rs index 96b16ab..52358e3 100644 --- a/migra/src/clients/postgres.rs +++ b/migra/src/clients/postgres.rs @@ -73,8 +73,11 @@ impl ManageMigrations for Client { .map_err(|_| Error::FailedDeleteMigration) } - fn applied_migrations(&mut self) -> MigraResult { - let stmt = format!("SELECT name FROM {}", &self.migrations_table_name); + fn get_applied_migrations(&mut self) -> MigraResult { + let stmt = format!( + "SELECT name FROM {} ORDER BY id DESC", + &self.migrations_table_name + ); self.client .query(stmt.as_str(), &[]) diff --git a/migra/src/clients/sqlite.rs b/migra/src/clients/sqlite.rs index a7a9969..3d17040 100644 --- a/migra/src/clients/sqlite.rs +++ b/migra/src/clients/sqlite.rs @@ -67,8 +67,11 @@ impl ManageMigrations for Client { .map_err(|_| Error::FailedDeleteMigration) } - fn applied_migrations(&mut self) -> MigraResult { - let stmt = format!("SELECT name FROM {}", &self.migrations_table_name); + fn get_applied_migrations(&mut self) -> MigraResult { + let stmt = format!( + "SELECT name FROM {} ORDER BY id DESC", + &self.migrations_table_name + ); self.conn .prepare(&stmt) diff --git a/migra/src/fs.rs b/migra/src/fs.rs index 790974f..f6afbd2 100644 --- a/migra/src/fs.rs +++ b/migra/src/fs.rs @@ -24,14 +24,7 @@ pub fn get_all_migrations(dir_path: &Path) -> MigraResult { } entries.sort(); - - let file_names = entries - .iter() - .filter_map(|path| path.file_name()) - .filter_map(std::ffi::OsStr::to_str) - .collect::>(); - - Ok(migration::List::from(file_names)) + Ok(migration::List::from(entries)) } #[must_use] @@ -39,9 +32,5 @@ pub fn filter_pending_migrations( all_migrations: &migration::List, applied_migrations: &migration::List, ) -> migration::List { - all_migrations - .clone() - .iter() - .filter(|m| !applied_migrations.contains(m)) - .collect() + all_migrations.exclude(applied_migrations) } diff --git a/migra/src/managers.rs b/migra/src/managers.rs index 1ad9417..06ce79e 100644 --- a/migra/src/managers.rs +++ b/migra/src/managers.rs @@ -1,5 +1,6 @@ use crate::error::{Error, MigraResult, StdResult}; use crate::migration::{self, Migration}; +use std::path::Path; pub trait BatchExecute { fn batch_execute(&mut self, sql: &str) -> StdResult<()>; @@ -33,12 +34,16 @@ pub trait ManageMigrations: BatchExecute { fn delete_migration(&mut self, name: &str) -> MigraResult; - fn applied_migrations(&mut self) -> MigraResult; + fn get_applied_migrations(&mut self) -> MigraResult; + + fn get_extended_applied_migrations(&mut self, prefix: &Path) -> MigraResult { + self.get_applied_migrations() + .map(|migrations| migrations.extend_with_path_prefix(prefix)) + } fn apply_upgrade_migration(&mut self, migration: &Migration) -> MigraResult<()> { let content = migration.read_upgrade_migration_sql()?; - self.create_migrations_table()?; self.apply_sql(&content)?; self.insert_migration(migration.name())?; diff --git a/migra/src/migration.rs b/migra/src/migration.rs index d35fb80..bdd9db9 100644 --- a/migra/src/migration.rs +++ b/migra/src/migration.rs @@ -15,21 +15,37 @@ pub struct Migration { impl Migration { #[must_use] pub fn new(path: &Path) -> Self { + Migration::with_name( + path, + path.file_name() + .and_then(std::ffi::OsStr::to_str) + .expect("Cannot read migration name"), + ) + } + + #[must_use] + pub fn with_name(path: &Path, name: &str) -> Self { Migration { path: PathBuf::from(path), - name: path - .file_name() - .and_then(std::ffi::OsStr::to_str) - .expect("Cannot read migration name") - .to_string(), + name: name.to_owned(), } } + #[must_use] + pub fn path(&self) -> &Path { + &self.path + } + #[must_use] pub fn name(&self) -> &String { &self.name } + #[must_use] + pub fn extend_with_path_prefix(&self, prefix: &Path) -> Self { + Migration::with_name(&prefix.join(self.path()), self.name()) + } + pub fn read_upgrade_migration_sql(&self) -> io::Result { fs::read_to_string(self.path.join(UPGRADE_MIGRATION_FILE_NAME)) } @@ -136,8 +152,17 @@ impl List { #[must_use] pub fn exclude(&self, list: &List) -> List { - self.iter() - .filter(|migration| !list.contains(migration)) + self.inner + .iter() + .filter(|migration| !list.contains_name(migration.name())) + .collect() + } + + #[must_use] + pub fn extend_with_path_prefix(&self, prefix: &Path) -> Self { + self.inner + .iter() + .map(|m| m.extend_with_path_prefix(prefix)) .collect() } } diff --git a/migra_cli/src/app.rs b/migra_cli/src/app.rs index 8386e8a..f7dc945 100644 --- a/migra_cli/src/app.rs +++ b/migra_cli/src/app.rs @@ -25,7 +25,7 @@ impl App { } pub fn run_command(&self) -> StdResult<()> { - match dbg!(self.app_opt.command.clone()) { + match self.app_opt.command.clone() { Command::Init => { commands::initialize_migra_manifest(self)?; } diff --git a/migra_cli/src/commands/downgrade.rs b/migra_cli/src/commands/downgrade.rs index 0eff571..26ce1b4 100644 --- a/migra_cli/src/commands/downgrade.rs +++ b/migra_cli/src/commands/downgrade.rs @@ -12,7 +12,10 @@ pub(crate) fn rollback_applied_migrations(app: &App, opts: &DowngradeCommandOpt) &config.database.connection_string()?, )?; - let applied_migrations = client.applied_migrations()?; + client.create_migrations_table()?; + + let applied_migrations = + client.get_extended_applied_migrations(&config.migration_dir_path())?; let all_migrations = migra::fs::get_all_migrations(&config.migration_dir_path())?; let rollback_migrations_number = if opts.all_migrations { @@ -21,6 +24,8 @@ pub(crate) fn rollback_applied_migrations(app: &App, opts: &DowngradeCommandOpt) cmp::min(opts.migrations_number, applied_migrations.len()) }; + dbg!(&rollback_migrations_number); + maybe_with_transaction( opts.transaction_opts.single_transaction, &mut client, @@ -28,7 +33,7 @@ pub(crate) fn rollback_applied_migrations(app: &App, opts: &DowngradeCommandOpt) applied_migrations[..rollback_migrations_number] .iter() .try_for_each(|applied_migration| { - if all_migrations.contains(applied_migration) { + if all_migrations.contains_name(applied_migration.name()) { println!("downgrade {}...", applied_migration.name()); maybe_with_transaction( !opts.transaction_opts.single_transaction, diff --git a/migra_cli/src/commands/list.rs b/migra_cli/src/commands/list.rs index 9d9f80a..da70a3c 100644 --- a/migra_cli/src/commands/list.rs +++ b/migra_cli/src/commands/list.rs @@ -10,7 +10,9 @@ pub(crate) fn print_migration_lists(app: &App) -> StdResult<()> { let applied_migrations = match config.database.connection_string() { Ok(ref database_connection_string) => { let mut client = client::create(&config.database.client(), database_connection_string)?; - let applied_migrations = client.applied_migrations()?; + let applied_migrations = client + .get_applied_migrations() + .unwrap_or_else(|_| migration::List::new()); show_applied_migrations(&applied_migrations); diff --git a/migra_cli/src/commands/upgrade.rs b/migra_cli/src/commands/upgrade.rs index 65bdfef..5298773 100644 --- a/migra_cli/src/commands/upgrade.rs +++ b/migra_cli/src/commands/upgrade.rs @@ -12,7 +12,10 @@ pub(crate) fn upgrade_pending_migrations(app: &App, opts: &UpgradeCommandOpt) -> &config.database.connection_string()?, )?; - let applied_migration_names = client.applied_migrations()?; + client.create_migrations_table()?; + + let applied_migration_names = + client.get_extended_applied_migrations(&config.migration_dir_path())?; let all_migrations = migra::fs::get_all_migrations(&config.migration_dir_path())?; let pending_migrations =