Skip to content

Commit

Permalink
fix enum migrations
Browse files Browse the repository at this point in the history
  • Loading branch information
jxs committed Aug 14, 2024
1 parent ddb48dc commit 666cbd3
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 33 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ jobs:
- run: rustup self update
- run: cd refinery_core && cargo test --all-features -- --test-threads 1
- run: cd refinery && cargo build --all-features
- run: cd refinery_macros && cargo test --features=enums
- run: cd refinery_macros && cargo test --all-features
- run: cd refinery_macros && cargo test --features enums enum_fn
- run: cd refinery_cli && cargo test

test-sqlite:
Expand Down
3 changes: 2 additions & 1 deletion examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ edition = "2021"

[features]
enums = ["refinery/enums"]
int8-versions = ["refinery/int8-versions"]

[dependencies]
refinery = { path = "../refinery", features = ["rusqlite"] }
rusqlite = "0.31"
barrel = { version = "0.7", features = ["sqlite3"] }
log = "0.4"
env_logger = "0.11"
env_logger = "0.11"
2 changes: 1 addition & 1 deletion refinery/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ tiberius-config = ["refinery-core/tiberius", "refinery-core/tiberius-config"]
serde = ["refinery-core/serde"]
toml = ["refinery-core/toml"]
enums = ["refinery-macros/enums"]
int8-versions = ["refinery-core/int8-versions"]
int8-versions = ["refinery-core/int8-versions", "refinery-macros/int8-versions"]

[dependencies]
refinery-core = { version = "0.8.14", path = "../refinery_core" }
Expand Down
2 changes: 1 addition & 1 deletion refinery/tests/postgres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ mod postgres {
fn applies_migration_int8() {
run_test(|| {
let mut client = Client::connect(&db_uri(), NoTls).unwrap();
let report = int8::migrations::runner().run(&mut client).unwrap();
let report = embedded::migrations::runner().run(&mut client).unwrap();

let applied_migrations = report.applied_migrations();

Expand Down
5 changes: 3 additions & 2 deletions refinery_macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ repository = "https://github.com/rust-db/refinery"
edition = "2018"

[features]
enums = []
enums = ["dep:heck"]
int8-versions = ["refinery-core/int8-versions"]

[lib]
proc-macro = true
Expand All @@ -20,7 +21,7 @@ quote = "1"
syn = "2"
proc-macro2 = "1"
regex = "1"
heck = "0.5"
heck = { version = "0.5", optional = true }

[dev-dependencies]
tempfile = "3"
97 changes: 70 additions & 27 deletions refinery_macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Contains Refinery macros that are used to import and embed migration files.
#![recursion_limit = "128"]

#[cfg(feature = "enums")]
use heck::ToUpperCamelCase;
use proc_macro::TokenStream;
use proc_macro2::{Span as Span2, TokenStream as TokenStream2};
Expand Down Expand Up @@ -32,38 +33,53 @@ fn migration_fn_quoted<T: ToTokens>(_migrations: Vec<T>) -> TokenStream2 {
result
}

#[cfg(feature = "enums")]
fn migration_enum_quoted(migration_names: &[impl AsRef<str>]) -> TokenStream2 {
if cfg!(feature = "enums") {
let mut variants = Vec::new();
let mut discriminants = Vec::new();

for m in migration_names {
let m = m.as_ref();
let (_, version, name) = refinery_core::parse_migration_name(m)
.unwrap_or_else(|e| panic!("Couldn't parse migration filename '{}': {:?}", m, e));
let variant = Ident::new(name.to_upper_camel_case().as_str(), Span2::call_site());
variants.push(quote! { #variant(Migration) = #version });
discriminants.push(quote! { #version => Self::#variant(migration) });
use refinery_core::SchemaVersion;

let mut variants = Vec::new();
let mut discriminants = Vec::new();

for m in migration_names {
let m = m.as_ref();
let (_, version, name) = refinery_core::parse_migration_name(m)
.unwrap_or_else(|e| panic!("Couldn't parse migration filename '{}': {:?}", m, e));
let version: SchemaVersion = version;
let variant = Ident::new(name.to_upper_camel_case().as_str(), Span2::call_site());
variants.push(quote! { #variant(Migration) = #version });
discriminants.push(quote! { #version => Self::#variant(migration) });
}
discriminants.push(quote! { v => panic!("Invalid migration version '{}'", v) });

#[cfg(feature = "int8-versions")]
let embedded = quote! {
#[repr(i64)]
#[derive(Debug)]
pub enum EmbeddedMigration {
#(#variants),*
}
discriminants.push(quote! { v => panic!("Invalid migration version '{}'", v) });
};

let result = quote! {
#[derive(Debug)]
pub enum EmbeddedMigration {
#(#variants),*
}
#[cfg(not(feature = "int8-versions"))]
let embedded = quote! {
#[repr(i32)]
#[derive(Debug)]
pub enum EmbeddedMigration {
#(#variants),*
}
};

quote! {

#embedded

impl From<Migration> for EmbeddedMigration {
fn from(migration: Migration) -> Self {
match migration.version() as SchemaVersion {
#(#discriminants),*
}
impl From<Migration> for EmbeddedMigration {
fn from(migration: Migration) -> Self {
match migration.version() as SchemaVersion {
#(#discriminants),*
}
}
};
result
} else {
quote!()
}
}
}

Expand Down Expand Up @@ -123,7 +139,11 @@ pub fn embed_migrations(input: TokenStream) -> TokenStream {
}

let fnq = migration_fn_quoted(_migrations);
#[cfg(feature = "enums")]
let enums = migration_enum_quoted(migration_filenames.as_slice());
#[cfg(not(feature = "enums"))]
let enums = quote!();

(quote! {
pub mod migrations {
#(#migrations_mods)*
Expand All @@ -138,10 +158,33 @@ pub fn embed_migrations(input: TokenStream) -> TokenStream {
mod tests {
use super::{migration_fn_quoted, quote};

#[cfg(all(feature = "enums", feature = "int8-versions"))]
#[test]
fn test_enum_fn_i8() {
let expected = concat! {
"# [repr (i64)] ",
"# [derive (Debug)] ",
"pub enum EmbeddedMigration { ",
"Foo (Migration) = 1i64 , ",
"BarBaz (Migration) = 3i64 ",
"} ",
"impl From < Migration > for EmbeddedMigration { ",
"fn from (migration : Migration) -> Self { ",
"match migration . version () as SchemaVersion { ",
"1i64 => Self :: Foo (migration) , ",
"3i64 => Self :: BarBaz (migration) , ",
"v => panic ! (\"Invalid migration version '{}'\" , v) ",
"} } }"
};
let enums = super::migration_enum_quoted(&["V1__foo", "U3__barBAZ"]).to_string();
assert_eq!(expected, enums);
}

#[cfg(all(feature = "enums", not(feature = "int8-versions")))]
#[test]
#[cfg(feature = "enums")]
fn test_enum_fn() {
let expected = concat! {
"# [repr (i32)] ",
"# [derive (Debug)] ",
"pub enum EmbeddedMigration { ",
"Foo (Migration) = 1i32 , ",
Expand Down

0 comments on commit 666cbd3

Please sign in to comment.