parent
155b2e6aa2
commit
8f06b69f5d
4 changed files with 137 additions and 12 deletions
|
@ -12,17 +12,25 @@ pub(crate) fn apply_sql(app: &App, cmd_opts: ApplyCommandOpt) -> StdResult<()> {
|
|||
|
||||
let migration_manager = MigrationManager::new();
|
||||
|
||||
let file_path = {
|
||||
let mut file_path = config.directory_path().join(cmd_opts.file_name);
|
||||
if file_path.extension().is_none() {
|
||||
file_path.set_extension("sql");
|
||||
}
|
||||
file_path
|
||||
};
|
||||
let file_contents = cmd_opts
|
||||
.file_paths
|
||||
.into_iter()
|
||||
.map(|file_path| {
|
||||
let mut file_path = config.directory_path().join(file_path);
|
||||
if file_path.extension().is_none() {
|
||||
file_path.set_extension("sql");
|
||||
}
|
||||
dbg!(&file_path);
|
||||
file_path
|
||||
})
|
||||
.map(std::fs::read_to_string)
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let content = std::fs::read_to_string(file_path)?;
|
||||
with_transaction(conn, &mut |conn| {
|
||||
migration_manager.apply_sql(conn, &content)
|
||||
file_contents
|
||||
.iter()
|
||||
.try_for_each(|content| migration_manager.apply_sql(conn, content))?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -176,7 +176,7 @@ impl Config {
|
|||
Err(e) if e.kind() == io::ErrorKind::NotFound => return Ok(Vec::new()),
|
||||
entries => entries?
|
||||
.map(|res| res.map(|e| e.path()))
|
||||
.collect::<Result<Vec<_>, io::Error>>()?,
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
};
|
||||
|
||||
if entries.is_empty() {
|
||||
|
|
|
@ -34,8 +34,8 @@ pub(crate) enum Command {
|
|||
|
||||
#[derive(Debug, StructOpt, Clone)]
|
||||
pub(crate) struct ApplyCommandOpt {
|
||||
#[structopt(parse(from_str))]
|
||||
pub file_name: String,
|
||||
#[structopt(parse(from_os_str), required = true)]
|
||||
pub file_paths: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt, Clone)]
|
||||
|
|
|
@ -448,3 +448,120 @@ mod upgrade {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
mod apply {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn apply_files() -> TestResult {
|
||||
fn inner<ValidateFn>(
|
||||
database_name: &'static str,
|
||||
file_paths: Vec<&'static str>,
|
||||
validate: ValidateFn,
|
||||
) -> TestResult
|
||||
where
|
||||
ValidateFn: Fn() -> TestResult,
|
||||
{
|
||||
let manifest_path = database_manifest_path(database_name);
|
||||
|
||||
Command::cargo_bin("migra")?
|
||||
.arg("-c")
|
||||
.arg(&manifest_path)
|
||||
.arg("apply")
|
||||
.args(file_paths)
|
||||
.assert()
|
||||
.success();
|
||||
|
||||
validate()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "postgres")] {
|
||||
inner(
|
||||
"postgres",
|
||||
vec![
|
||||
"migrations/210218232851_create_articles/up",
|
||||
"migrations/210218233414_create_persons/up",
|
||||
],
|
||||
|| {
|
||||
let mut conn = postgres::Client::connect(POSTGRES_URL, postgres::NoTls)?;
|
||||
let res = conn.query("SELECT p.id, a.id FROM persons AS p, articles AS a", &[])?;
|
||||
|
||||
assert_eq!(
|
||||
res.into_iter()
|
||||
.map(|row| (row.get(0), row.get(1)))
|
||||
.collect::<Vec<(i32, i32)>>(),
|
||||
Vec::new()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
inner(
|
||||
"postgres",
|
||||
vec![
|
||||
"migrations/210218233414_create_persons/down",
|
||||
"migrations/210218232851_create_articles/down",
|
||||
],
|
||||
|| {
|
||||
let mut conn = postgres::Client::connect(POSTGRES_URL, postgres::NoTls)?;
|
||||
let res = conn.query("SELECT p.id, a.id FROM persons AS p, articles AS a", &[]);
|
||||
|
||||
assert!(res.is_err());
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "mysql")] {
|
||||
inner(
|
||||
"mysql",
|
||||
vec![
|
||||
"migrations/210218232851_create_articles/up",
|
||||
"migrations/210218233414_create_persons/up",
|
||||
],
|
||||
|| {
|
||||
use mysql::prelude::*;
|
||||
|
||||
let pool = mysql::Pool::new(MYSQL_URL)?;
|
||||
let mut conn = pool.get_conn()?;
|
||||
|
||||
let res = conn.query_drop("SELECT p.id, a.id FROM persons AS p, articles AS a")?;
|
||||
|
||||
assert_eq!(res, ());
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
inner(
|
||||
"mysql",
|
||||
vec![
|
||||
"migrations/210218233414_create_persons/down",
|
||||
"migrations/210218232851_create_articles/down",
|
||||
],
|
||||
|| {
|
||||
use mysql::prelude::*;
|
||||
|
||||
let pool = mysql::Pool::new(MYSQL_URL)?;
|
||||
let mut conn = pool.get_conn()?;
|
||||
|
||||
let res = conn.query_drop("SELECT p.id, a.id FROM persons AS p, articles AS a");
|
||||
|
||||
assert!(res.is_err());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue