Skip to content

Commit 08dffff

Browse files
committed
fix(cli): test migrate.ignored-chars, fix bugs
1 parent 940d4d0 commit 08dffff

21 files changed

+245
-72
lines changed

sqlx-cli/src/migrate.rs

+8-16
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ use crate::config::Config;
22
use crate::opt::{AddMigrationOpts, ConnectOpts, MigrationSourceOpt};
33
use anyhow::{bail, Context};
44
use console::style;
5-
use sqlx::migrate::{
6-
AppliedMigration, Migrate, MigrateError, MigrationType, Migrator, ResolveWith,
7-
};
5+
use sqlx::migrate::{AppliedMigration, Migrate, MigrateError, MigrationType, Migrator};
86
use sqlx::Connection;
97
use std::borrow::Cow;
108
use std::collections::{HashMap, HashSet};
@@ -16,11 +14,11 @@ use std::time::Duration;
1614
pub async fn add(opts: AddMigrationOpts) -> anyhow::Result<()> {
1715
let config = opts.config.load_config().await?;
1816

19-
let source = opts.source.resolve(config);
17+
let source = opts.source.resolve_path(config);
2018

2119
fs::create_dir_all(source).context("Unable to create migrations directory")?;
2220

23-
let migrator = Migrator::new(Path::new(source)).await?;
21+
let migrator = opts.source.resolve(config).await?;
2422

2523
let version_prefix = opts.version_prefix(config, &migrator);
2624

@@ -130,13 +128,8 @@ pub async fn info(
130128
migration_source: &MigrationSourceOpt,
131129
connect_opts: &ConnectOpts,
132130
) -> anyhow::Result<()> {
133-
let source = migration_source.resolve(config);
131+
let migrator = migration_source.resolve(config).await?;
134132

135-
let migrator = Migrator::new(ResolveWith(
136-
Path::new(source),
137-
config.migrate.to_resolve_config(),
138-
))
139-
.await?;
140133
let mut conn = crate::connect(connect_opts).await?;
141134

142135
// FIXME: we shouldn't actually be creating anything here
@@ -228,9 +221,8 @@ pub async fn run(
228221
ignore_missing: bool,
229222
target_version: Option<i64>,
230223
) -> anyhow::Result<()> {
231-
let source = migration_source.resolve(config);
224+
let migrator = migration_source.resolve(config).await?;
232225

233-
let migrator = Migrator::new(Path::new(source)).await?;
234226
if let Some(target_version) = target_version {
235227
if !migrator.version_exists(target_version) {
236228
bail!(MigrateError::VersionNotPresent(target_version));
@@ -331,8 +323,8 @@ pub async fn revert(
331323
ignore_missing: bool,
332324
target_version: Option<i64>,
333325
) -> anyhow::Result<()> {
334-
let source = migration_source.resolve(config);
335-
let migrator = Migrator::new(Path::new(source)).await?;
326+
let migrator = migration_source.resolve(config).await?;
327+
336328
if let Some(target_version) = target_version {
337329
if target_version != 0 && !migrator.version_exists(target_version) {
338330
bail!(MigrateError::VersionNotPresent(target_version));
@@ -432,7 +424,7 @@ pub fn build_script(
432424
migration_source: &MigrationSourceOpt,
433425
force: bool,
434426
) -> anyhow::Result<()> {
435-
let source = migration_source.resolve(config);
427+
let source = migration_source.resolve_path(config);
436428

437429
anyhow::ensure!(
438430
Path::new("Cargo.toml").exists(),

sqlx-cli/src/opt.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use clap::{
88
};
99
#[cfg(feature = "completions")]
1010
use clap_complete::Shell;
11-
use sqlx::migrate::Migrator;
11+
use sqlx::migrate::{MigrateError, Migrator, ResolveWith};
1212
use std::env;
1313
use std::ops::{Deref, Not};
1414
use std::path::PathBuf;
@@ -342,13 +342,21 @@ pub struct MigrationSourceOpt {
342342
}
343343

344344
impl MigrationSourceOpt {
345-
pub fn resolve<'a>(&'a self, config: &'a Config) -> &'a str {
345+
pub fn resolve_path<'a>(&'a self, config: &'a Config) -> &'a str {
346346
if let Some(source) = &self.source {
347347
return source;
348348
}
349349

350350
config.migrate.migrations_dir()
351351
}
352+
353+
pub async fn resolve(&self, config: &Config) -> Result<Migrator, MigrateError> {
354+
Migrator::new(ResolveWith(
355+
self.resolve_path(config),
356+
config.migrate.to_resolve_config(),
357+
))
358+
.await
359+
}
352360
}
353361

354362
/// Argument for the database URL.

sqlx-cli/tests/common/mod.rs

+80-42
Original file line numberDiff line numberDiff line change
@@ -3,75 +3,89 @@ use assert_cmd::{assert::Assert, Command};
33
use sqlx::_unstable::config::Config;
44
use sqlx::{migrate::Migrate, Connection, SqliteConnection};
55
use std::{
6-
env::temp_dir,
7-
fs::remove_file,
6+
env, fs,
87
path::{Path, PathBuf},
98
};
109

1110
pub struct TestDatabase {
1211
file_path: PathBuf,
13-
migrations: String,
12+
migrations_path: PathBuf,
13+
pub config_path: Option<PathBuf>,
1414
}
1515

1616
impl TestDatabase {
1717
pub fn new(name: &str, migrations: &str) -> Self {
18-
let migrations_path = Path::new("tests").join(migrations);
19-
let file_path = Path::new(&temp_dir()).join(format!("test-{}.db", name));
20-
let ret = Self {
18+
// Note: only set when _building_
19+
let temp_dir = option_env!("CARGO_TARGET_TMPDIR").map_or_else(env::temp_dir, PathBuf::from);
20+
21+
let test_dir = temp_dir.join("migrate");
22+
23+
fs::create_dir_all(&test_dir)
24+
.unwrap_or_else(|e| panic!("error creating directory: {test_dir:?}: {e}"));
25+
26+
let file_path = test_dir.join(format!("test-{name}.db"));
27+
28+
if file_path.exists() {
29+
fs::remove_file(&file_path)
30+
.unwrap_or_else(|e| panic!("error deleting test database {file_path:?}: {e}"));
31+
}
32+
33+
let this = Self {
2134
file_path,
22-
migrations: String::from(migrations_path.to_str().unwrap()),
35+
migrations_path: Path::new("tests").join(migrations),
36+
config_path: None,
2337
};
38+
2439
Command::cargo_bin("cargo-sqlx")
2540
.unwrap()
2641
.args([
2742
"sqlx",
2843
"database",
2944
"create",
3045
"--database-url",
31-
&ret.connection_string(),
46+
&this.connection_string(),
3247
])
3348
.assert()
3449
.success();
35-
ret
50+
this
51+
}
52+
53+
pub fn set_migrations(&mut self, migrations: &str) {
54+
self.migrations_path = Path::new("tests").join(migrations);
3655
}
3756

3857
pub fn connection_string(&self) -> String {
3958
format!("sqlite://{}", self.file_path.display())
4059
}
4160

4261
pub fn run_migration(&self, revert: bool, version: Option<i64>, dry_run: bool) -> Assert {
43-
let ver = match version {
44-
Some(v) => v.to_string(),
45-
None => String::from(""),
46-
};
47-
Command::cargo_bin("cargo-sqlx")
48-
.unwrap()
49-
.args(
50-
[
51-
vec![
52-
"sqlx",
53-
"migrate",
54-
match revert {
55-
true => "revert",
56-
false => "run",
57-
},
58-
"--database-url",
59-
&self.connection_string(),
60-
"--source",
61-
&self.migrations,
62-
],
63-
match version {
64-
Some(_) => vec!["--target-version", &ver],
65-
None => vec![],
66-
},
67-
match dry_run {
68-
true => vec!["--dry-run"],
69-
false => vec![],
70-
},
71-
]
72-
.concat(),
73-
)
74-
.assert()
62+
let mut command = Command::cargo_bin("sqlx").unwrap();
63+
command
64+
.args([
65+
"migrate",
66+
match revert {
67+
true => "revert",
68+
false => "run",
69+
},
70+
"--database-url",
71+
&self.connection_string(),
72+
"--source",
73+
])
74+
.arg(&self.migrations_path);
75+
76+
if let Some(config_path) = &self.config_path {
77+
command.arg("--config").arg(config_path);
78+
}
79+
80+
if let Some(version) = version {
81+
command.arg("--target-version").arg(version.to_string());
82+
}
83+
84+
if dry_run {
85+
command.arg("--dry-run");
86+
}
87+
88+
command.assert()
7589
}
7690

7791
pub async fn applied_migrations(&self) -> Vec<i64> {
@@ -88,10 +102,34 @@ impl TestDatabase {
88102
.map(|m| m.version)
89103
.collect()
90104
}
105+
106+
pub fn migrate_info(&self) -> Assert {
107+
let mut command = Command::cargo_bin("sqlx").unwrap();
108+
command
109+
.args([
110+
"migrate",
111+
"info",
112+
"--database-url",
113+
&self.connection_string(),
114+
"--source",
115+
])
116+
.arg(&self.migrations_path);
117+
118+
if let Some(config_path) = &self.config_path {
119+
command.arg("--config").arg(config_path);
120+
}
121+
122+
command.assert()
123+
}
91124
}
92125

93126
impl Drop for TestDatabase {
94127
fn drop(&mut self) {
95-
remove_file(&self.file_path).unwrap();
128+
// Only remove the database if there isn't a failure.
129+
if !std::thread::panicking() {
130+
fs::remove_file(&self.file_path).unwrap_or_else(|e| {
131+
panic!("error deleting test database {:?}: {e}", self.file_path)
132+
});
133+
}
96134
}
97135
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.sql text eol=lf
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
create table user
2+
(
3+
-- integer primary keys are the most efficient in SQLite
4+
user_id integer primary key,
5+
username text unique not null
6+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
create table post
2+
(
3+
post_id integer primary key,
4+
user_id integer not null references user (user_id),
5+
content text not null,
6+
-- Defaults have to be wrapped in parenthesis
7+
created_at datetime default (datetime('now'))
8+
);
9+
10+
create index post_created_at on post (created_at desc);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
create table comment
2+
(
3+
comment_id integer primary key,
4+
post_id integer not null references post (post_id),
5+
user_id integer not null references "user" (user_id),
6+
content text not null,
7+
created_at datetime default (datetime('now'))
8+
);
9+
10+
create index comment_created_at on comment (created_at desc);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.sql text eol=crlf
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
create table user
2+
(
3+
-- integer primary keys are the most efficient in SQLite
4+
user_id integer primary key,
5+
username text unique not null
6+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
create table post
2+
(
3+
post_id integer primary key,
4+
user_id integer not null references user (user_id),
5+
content text not null,
6+
-- Defaults have to be wrapped in parenthesis
7+
created_at datetime default (datetime('now'))
8+
);
9+
10+
create index post_created_at on post (created_at desc);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
create table comment
2+
(
3+
comment_id integer primary key,
4+
post_id integer not null references post (post_id),
5+
user_id integer not null references "user" (user_id),
6+
content text not null,
7+
created_at datetime default (datetime('now'))
8+
);
9+
10+
create index comment_created_at on comment (created_at desc);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.sql text eol=lf
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
create table user
2+
(
3+
-- integer primary keys are the most efficient in SQLite
4+
user_id integer primary key,
5+
username text unique not null
6+
);
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
create table post
2+
(
3+
post_id integer primary key,
4+
user_id integer not null references user (user_id),
5+
content text not null,
6+
-- Defaults have to be wrapped in parenthesis
7+
created_at datetime default (datetime('now'))
8+
);
9+
10+
create index post_created_at on post (created_at desc);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
create table comment
2+
(
3+
comment_id integer primary key,
4+
post_id integer not null references post (post_id),
5+
user_id integer not null references "user" (user_id),
6+
content text not null,
7+
created_at datetime default (datetime('now'))
8+
);
9+
10+
create index comment_created_at on comment (created_at desc);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.sql text eol=lf
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
create table user
2+
(
3+
-- integer primary keys are the most efficient in SQLite
4+
user_id integer primary key,
5+
username text unique not null
6+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
create table post
2+
(
3+
post_id integer primary key,
4+
user_id integer not null references user (user_id),
5+
content text not null,
6+
-- Defaults have to be wrapped in parenthesis
7+
created_at datetime default (datetime('now'))
8+
);
9+
10+
create index post_created_at on post (created_at desc);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
create table comment
2+
(
3+
comment_id integer primary key,
4+
post_id integer not null references post (post_id),
5+
user_id integer not null references "user" (user_id),
6+
content text not null,
7+
created_at datetime default (datetime('now'))
8+
);
9+
10+
create index comment_created_at on comment (created_at desc);

0 commit comments

Comments
 (0)