Skip to content

Commit 3e96c0c

Browse files
committed
Incompatible set_grouped with no transaction
1 parent d107bed commit 3e96c0c

File tree

5 files changed

+50
-3
lines changed

5 files changed

+50
-3
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ This would stop developer 1's migration from ever running if you were using cont
9696

9797
refinery works by creating a table that keeps all the applied migrations' versions and their metadata. When you [run](https://docs.rs/refinery/latest/refinery/struct.Runner.html#method.run) the migrations `Runner`, refinery compares the applied migrations with the ones to be applied, checking for [divergent](https://docs.rs/refinery/latest/refinery/struct.Runner.html#method.set_abort_divergent) and [missing](https://docs.rs/refinery/latest/refinery/struct.Runner.html#method.set_abort_missing) and executing unapplied migrations.\
9898
By default, refinery runs each migration in a single transaction. Alternatively, you can also configure refinery to wrap the entire execution of all migrations in a single transaction by setting [set_grouped](https://docs.rs/refinery/latest/refinery/struct.Runner.html#method.set_grouped) to true.
99-
Directive `-- +refinery NO TRANSACTION` can be used to escape running a migration within a transaction. [!IMPORTANT]: `set_grouped` takes precedence over no transaction directive.
99+
Directive `-- +refinery NO TRANSACTION` can be used to escape running a migration within a transaction. [!IMPORTANT]: `set_grouped` is incompatible with the no transaction directive.
100100
The rust crate intentionally ignores new migration files until your sourcecode is rebuild. This prevents accidental migrations and altering the database schema without any code changes. We can also bake the migrations into the binary, so no additional files are needed when deployed.
101101

102102
### Rollback

refinery/tests/postgres.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,37 @@ mod postgres {
384384
});
385385
}
386386

387+
#[test]
388+
fn no_transaction_fails_in_set_grouped() {
389+
run_test(|| {
390+
let mut client = Client::connect(&db_uri(), NoTls).unwrap();
391+
392+
embedded::migrations::runner().run(&mut client).unwrap();
393+
394+
let migrations = get_migrations();
395+
396+
let mchecksum = migrations[5].checksum();
397+
let err = client
398+
.migrate(
399+
&migrations,
400+
true,
401+
true,
402+
true,
403+
Target::Latest,
404+
DEFAULT_TABLE_NAME,
405+
)
406+
.unwrap_err();
407+
408+
match err.kind() {
409+
Kind::NoTransactionGroupedMigration(last) => {
410+
assert_eq!(6, last.version());
411+
assert_eq!(mchecksum, last.checksum());
412+
}
413+
_ => panic!("failed test"),
414+
}
415+
});
416+
}
417+
387418
#[test]
388419
fn migrates_to_target_migration() {
389420
run_test(|| {

refinery_core/src/error.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ pub enum Kind {
5757
/// An Error from an divergent version, the applied version is different to the filesystem one
5858
#[error("applied migration {0} is different than filesystem one {1}")]
5959
DivergentVersion(Migration, Migration),
60+
/// An Error from running in grouped mode with a migration that opts out of transactions
61+
#[error("migration {0} opts out of transactions, cannot run with `set-grouped`")]
62+
NoTransactionGroupedMigration(Migration),
6063
/// An Error from an divergent version, the applied version is missing on the filesystem
6164
#[error("migration {0} is missing from the filesystem")]
6265
MissingVersion(Migration),

refinery_core/src/traits/async.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::error::WrapMigrationError;
1+
use crate::error::{Kind, WrapMigrationError};
22
use crate::traits::{
33
insert_migration_query, verify_migrations, ASSERT_MIGRATIONS_TABLE_QUERY,
44
GET_APPLIED_MIGRATIONS_QUERY, GET_LAST_APPLIED_MIGRATION_QUERY,
@@ -83,6 +83,12 @@ async fn migrate_grouped<T: AsyncExecutor>(
8383
break;
8484
}
8585
}
86+
if !migration.flags().run_in_transaction {
87+
return Err(Error::new(
88+
Kind::NoTransactionGroupedMigration(migration),
89+
None,
90+
));
91+
}
8692

8793
migration.set_applied();
8894
let query = insert_migration_query(&migration, migration_table_name);

refinery_core/src/traits/sync.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::error::WrapMigrationError;
1+
use crate::error::{Kind, WrapMigrationError};
22
use crate::traits::{
33
insert_migration_query, verify_migrations, ASSERT_MIGRATIONS_TABLE_QUERY,
44
GET_APPLIED_MIGRATIONS_QUERY, GET_LAST_APPLIED_MIGRATION_QUERY,
@@ -41,6 +41,13 @@ fn migrate_grouped<T: Executor>(
4141
}
4242
}
4343

44+
if !migration.flags().run_in_transaction {
45+
return Err(Error::new(
46+
Kind::NoTransactionGroupedMigration(migration),
47+
None,
48+
));
49+
}
50+
4451
migration.set_applied();
4552
let query = insert_migration_query(&migration, migration_table_name);
4653

0 commit comments

Comments
 (0)