Skip to content

Commit 1277e3e

Browse files
committed
Support int8 migration versions via new int8-versions feature
This addresses, though does not really *fix* #83, because it doesn't make refinery support timestamped migrations *by default*, but only if you opt-in to the new feature. However, making it an optional feature neatly sidesteps the unanswered questions in the issue, and so makes the implementation easier to complete and land.
1 parent ff1c5c0 commit 1277e3e

21 files changed

+146
-33
lines changed

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,17 @@ fn main() {
5353
For more library examples, refer to the [`examples`](https://github.com/rust-db/refinery/tree/main/examples).
5454
### Example: CLI
5555

56-
NOTE:
56+
NOTE:
5757

58-
- Contiguous (adjacent) migration version numbers are restricted to `u32` (unsigned, 32-bit integers).
59-
- Non-contiguous (not adjacent) migration version numbers are restricted to `u32` (unsigned, 32-bit integers).
58+
- By default, migration version numbers are restricted to `i32` (signed, 32-bit integers).
59+
- If you enable the `int8-versions` feature, this restriction is lifted to being able to use `i64`s for your migration version numbers (yay timestamps!).
60+
Bear in mind that this feature must be enabled *before* you start using refinery on a given database.
61+
Migrating an existing database's `refinery_schema_history` table to use `int8` versions will break the checksums on all previously-applied migrations, which is... bad.
6062

6163
```bash
6264
export DATABASE_URL="postgres://postgres:secret@localhost:5432/your-db"
6365
pushd migrations
64-
# Runs ./src/V1__*.rs or ./src/V1__*.sql
66+
# Runs ./src/V1__*.rs or ./src/V1__*.sql
6567
refinery migrate -e DATABASE_URL -p ./src -t 1
6668
popd
6769
```

refinery/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ tiberius-config = ["refinery-core/tiberius", "refinery-core/tiberius-config"]
2525
serde = ["refinery-core/serde"]
2626
toml = ["refinery-core/toml"]
2727
enums = ["refinery-macros/enums"]
28+
int8-versions = ["refinery-core/int8-versions"]
2829

2930
[dependencies]
3031
refinery-core = { version = "0.8.14", path = "../refinery_core" }

refinery/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ for more examples refer to the [examples](https://github.com/rust-db/refinery/tr
3232
*/
3333

3434
pub use refinery_core::config;
35-
pub use refinery_core::{error, load_sql_migrations, Error, Migration, Report, Runner, Target};
35+
pub use refinery_core::{error, load_sql_migrations, Error, Migration, Report, Runner, SchemaVersion, Target};
3636
#[doc(hidden)]
3737
pub use refinery_core::{AsyncMigrate, Migrate};
3838
pub use refinery_macros::embed_migrations;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use barrel::{types, Migration};
2+
3+
use crate::Sql;
4+
5+
pub fn migration() -> String {
6+
let mut m = Migration::new();
7+
8+
m.create_table("persons", |t| {
9+
t.add_column("id", types::primary());
10+
t.add_column("name", types::varchar(255));
11+
t.add_column("city", types::varchar(255));
12+
});
13+
14+
m.make::<Sql>()
15+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CREATE TABLE cars (
2+
id int,
3+
name varchar(255)
4+
);
5+
CREATE TABLE motos (
6+
id int,
7+
name varchar(255)
8+
);
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE cars
2+
ADD brand varchar(255);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use barrel::{types, Migration};
2+
3+
use crate::Sql;
4+
5+
pub fn migration() -> String {
6+
let mut m = Migration::new();
7+
8+
m.change_table("motos", |t| {
9+
t.add_column("brand", types::varchar(255).nullable(true));
10+
});
11+
12+
m.make::<Sql>()
13+
}

refinery/tests/postgres.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ mod postgres {
3131
embed_migrations!("./tests/migrations_missing");
3232
}
3333

34+
#[cfg(feature = "int8-versions")]
35+
mod int8 {
36+
use refinery::embed_migrations;
37+
embed_migrations!("./tests/migrations_int8");
38+
}
39+
40+
fn db_uri() -> String {
41+
std::env::var("DB_URI").unwrap_or("postgres://postgres@localhost:5432/postgres".to_string())
42+
}
43+
3444
fn get_migrations() -> Vec<Migration> {
3545
embed_migrations!("./tests/migrations");
3646

@@ -189,6 +199,37 @@ mod postgres {
189199
});
190200
}
191201

202+
#[test]
203+
#[cfg(feature = "int8-versions")]
204+
fn applies_migration_int8() {
205+
run_test(|| {
206+
let mut client = Client::connect(&db_uri(), NoTls).unwrap();
207+
let report = int8::migrations::runner().run(&mut client).unwrap();
208+
209+
let applied_migrations = report.applied_migrations();
210+
211+
assert_eq!(4, applied_migrations.len());
212+
213+
assert_eq!(20240504090241, applied_migrations[0].version());
214+
assert_eq!(20240504090301, applied_migrations[1].version());
215+
assert_eq!(20240504090322, applied_migrations[2].version());
216+
assert_eq!(20240504090343, applied_migrations[3].version());
217+
218+
client
219+
.execute(
220+
"INSERT INTO persons (name, city) VALUES ($1, $2)",
221+
&[&"John Legend", &"New York"],
222+
)
223+
.unwrap();
224+
for row in &client.query("SELECT name, city FROM persons", &[]).unwrap() {
225+
let name: String = row.get(0);
226+
let city: String = row.get(1);
227+
assert_eq!("John Legend", name);
228+
assert_eq!("New York", city);
229+
}
230+
});
231+
}
232+
192233
#[test]
193234
fn applies_migration_grouped_transaction() {
194235
run_test(|| {
@@ -292,8 +333,15 @@ mod postgres {
292333
assert_eq!("initial", migrations[0].name());
293334
assert_eq!("add_cars_table", applied_migrations[1].name());
294335

336+
#[cfg(not(feature = "int8-versions"))]
295337
assert_eq!(2959965718684201605, applied_migrations[0].checksum());
338+
#[cfg(feature = "int8-versions")]
339+
assert_eq!(13938959368620441626, applied_migrations[0].checksum());
340+
341+
#[cfg(not(feature = "int8-versions"))]
296342
assert_eq!(8238603820526370208, applied_migrations[1].checksum());
343+
#[cfg(feature = "int8-versions")]
344+
assert_eq!(5394706226941044339, applied_migrations[1].checksum());
297345
});
298346
}
299347

refinery_cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ mysql = ["refinery-core/mysql"]
2121
sqlite = ["refinery-core/rusqlite"]
2222
sqlite-bundled = ["sqlite", "refinery-core/rusqlite-bundled"]
2323
mssql = ["refinery-core/tiberius-config", "tokio"]
24+
int8-versions = ["refinery-core/int8-versions"]
2425

2526
[dependencies]
2627
refinery-core = { version = "0.8.14", path = "../refinery_core", default-features = false, features = ["toml"] }

refinery_cli/src/cli.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use std::path::PathBuf;
44

55
use clap::{Args, Parser};
66

7+
use refinery_core::SchemaVersion;
8+
79
#[derive(Parser)]
810
#[clap(version)]
911
pub enum Cli {
@@ -38,7 +40,7 @@ pub struct MigrateArgs {
3840

3941
/// Migrate to the specified target version
4042
#[clap(short)]
41-
pub target: Option<u32>,
43+
pub target: Option<SchemaVersion>,
4244

4345
/// Set migration table name
4446
#[clap(long, default_value = "refinery_schema_history")]

0 commit comments

Comments
 (0)