-
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Load migrations from *.sql files in a directory
- Loading branch information
Showing
41 changed files
with
850 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
[package] | ||
name = "example-from-directory" | ||
version = "0.1.0" | ||
edition = "2018" | ||
publish = false | ||
|
||
[dependencies] | ||
rusqlite_migration = { path = "../../rusqlite_migration", features = [ | ||
"from-directory", | ||
] } | ||
log = "0.4" | ||
simple-logging = "2.0.2" | ||
env_logger = "0.10" | ||
anyhow = "1" | ||
lazy_static = "1.4.0" | ||
mktemp = "0.5" | ||
include_dir = "0.7.3" | ||
|
||
[dependencies.rusqlite] | ||
version = ">=0.23.0" | ||
default-features = false | ||
features = [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
CREATE TABLE friend( | ||
friend_id INTEGER PRIMARY KEY, | ||
name TEXT NOT NULL, | ||
email TEXT UNIQUE, | ||
phone TEXT UNIQUE, | ||
picture BLOB | ||
); | ||
|
||
CREATE TABLE car( | ||
registration_plate TEXT PRIMARY KEY, | ||
cost REAL NOT NULL, | ||
bought_on TEXT NOT NULL | ||
); |
2 changes: 2 additions & 0 deletions
2
examples/from-directory/migrations/02-add_birthday_column/up.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
ALTER TABLE friend ADD COLUMN birthday TEXT; | ||
ALTER TABLE friend ADD COLUMN comment TEXT; |
1 change: 1 addition & 0 deletions
1
examples/from-directory/migrations/03-add_animal_table/down.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
DROP TABLE animal; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
CREATE TABLE animal(name TEXT); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
use anyhow::Result; | ||
use include_dir::{include_dir, Dir}; | ||
use lazy_static::lazy_static; | ||
use rusqlite::{params, Connection}; | ||
use rusqlite_migration::Migrations; | ||
|
||
static MIGRATIONS_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/migrations"); | ||
|
||
// Define migrations. These are applied atomically. | ||
lazy_static! { | ||
static ref MIGRATIONS: Migrations<'static> = | ||
Migrations::from_directory(&MIGRATIONS_DIR).unwrap(); | ||
} | ||
|
||
pub fn init_db() -> Result<Connection> { | ||
let mut conn = Connection::open("./my_db.db3")?; | ||
|
||
// Update the database schema, atomically | ||
MIGRATIONS.to_latest(&mut conn)?; | ||
|
||
Ok(conn) | ||
} | ||
|
||
pub fn main() { | ||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")).init(); | ||
|
||
let mut conn = init_db().unwrap(); | ||
|
||
// Apply some PRAGMA. These are often better applied outside of migrations, as some needs to be | ||
// executed for each connection (like `foreign_keys`) or to be executed outside transactions | ||
// (`journal_mode` is a noop in a transaction). | ||
conn.pragma_update(None, "journal_mode", "WAL").unwrap(); | ||
conn.pragma_update(None, "foreign_keys", "ON").unwrap(); | ||
|
||
// Use the db 🥳 | ||
conn.execute( | ||
"INSERT INTO friend (name, birthday) VALUES (?1, ?2)", | ||
params!["John", "1970-01-01"], | ||
) | ||
.unwrap(); | ||
|
||
conn.execute("INSERT INTO animal (name) VALUES (?1)", params!["dog"]) | ||
.unwrap(); | ||
|
||
// If we want to revert the last migration | ||
MIGRATIONS.to_version(&mut conn, 2).unwrap(); | ||
|
||
// The table was removed | ||
conn.execute("INSERT INTO animal (name) VALUES (?1)", params!["cat"]) | ||
.unwrap_err(); | ||
} | ||
|
||
// Test that migrations are working | ||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn migrations_test() { | ||
assert!(MIGRATIONS.validate().is_ok()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
use std::iter::FromIterator; | ||
|
||
use include_dir::Dir; | ||
|
||
use crate::{loader::from_directory, Error, MigrationHook, Result, M}; | ||
|
||
/// Allows to build a `Vec<M<'u>>` with additional edits. | ||
#[derive(Default, Debug)] | ||
pub struct MigrationsBuilder<'u> { | ||
migrations: Vec<M<'u>>, | ||
} | ||
|
||
impl<'u> MigrationsBuilder<'u> { | ||
/// Creates a set of migrations from a given directory by scanning subdirectories with a specified name pattern. | ||
/// The migrations are loaded and stored in the binary. | ||
/// | ||
/// See the [`Migrations::from_directory`] method for additional information regarding the directory structure. | ||
/// | ||
/// # Example | ||
/// | ||
/// ``` | ||
/// use rusqlite_migration::{Migrations, MigrationsBuilder}; | ||
/// use include_dir::{Dir, include_dir}; | ||
/// | ||
/// static MIGRATION_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/../examples/from-directory/migrations"); | ||
/// let migrations: Migrations = MigrationsBuilder::from_directory(&MIGRATION_DIR).unwrap().finalize(); | ||
/// ``` | ||
/// | ||
/// Errors: | ||
/// | ||
/// Returns [`Error::FileLoad`] in case the subdirectory names are incorrect, | ||
/// or don't contain at least a valid `up.sql` file. | ||
pub fn from_directory(dir: &'static Dir<'static>) -> Result<Self> { | ||
Ok(Self { | ||
migrations: from_directory(dir)?, | ||
}) | ||
} | ||
|
||
/// Allows to edit a migration with a given `id`. | ||
/// | ||
/// Errors: | ||
/// | ||
/// Return [`Error::FileLoad`] in case a migration with a given `id` does not exist. | ||
pub fn edit(mut self, id: usize, f: impl Fn(&mut M)) -> Result<Self> { | ||
if id < 1 { | ||
return Err(Error::FileLoad("id cannot be equal to 0".to_string())); | ||
} | ||
f(self.migrations.get_mut(id - 1).ok_or(Error::FileLoad( | ||
"No migration with the given index".to_string(), | ||
))?); | ||
Ok(self) | ||
} | ||
|
||
/// Finalizes the builder and creates a either a [`crate::Migrations`] or [`crate::asynch::AsyncMigration`] instance. | ||
pub fn finalize<T: FromIterator<M<'u>>>(self) -> T { | ||
T::from_iter(self.migrations) | ||
} | ||
} | ||
|
||
impl<'u> FromIterator<M<'u>> for MigrationsBuilder<'u> { | ||
fn from_iter<T: IntoIterator<Item = M<'u>>>(iter: T) -> Self { | ||
Self { | ||
migrations: Vec::from_iter(iter), | ||
} | ||
} | ||
} | ||
|
||
impl<'u> M<'u> { | ||
/// Replace the `up_hook` in the given migration with the provided one. | ||
/// | ||
/// # Warning | ||
/// | ||
/// Use [`M::up_with_hook`] instead if you're creating a new migration. | ||
/// This method is meant for editing existing transactions | ||
/// when using the [`MigrationsBuilder`]. | ||
pub fn set_up_hook(&mut self, hook: impl MigrationHook + 'static) { | ||
self.up_hook = Some(hook.clone_box()); | ||
} | ||
|
||
/// Replace the `down_hook` in the given migration with the provided one. | ||
/// | ||
/// # Warning | ||
/// | ||
/// Use [`M::down_with_hook`] instead if you're creating a new migration. | ||
/// This method is meant for editing existing transactions | ||
/// when using the [`MigrationsBuilder`]. | ||
pub fn set_down_hook(&mut self, hook: impl MigrationHook + 'static) { | ||
self.down_hook = Some(hook.clone_box()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.