Skip to content

Commit 280e01c

Browse files
committed
Sanitize the database name in diesel_cli for CREATE / DROP database
operations. This allows the usage of database names like foo-bar. I chose not to use my query_helper functions and instead escape the names myself in the tests directory to avoid adding a lib.rs to diesel_cli. Fixes diesel-rs#350
1 parent e7ec7a1 commit 280e01c

7 files changed

Lines changed: 99 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ for Rust libraries in [RFC #1105](https://github.com/rust-lang/rfcs/blob/master/
3030

3131
* Diesel CLI: Support the `--migration-dir` argument and the `MIGRATION_DIRECTORY` on every migrations related command.
3232

33+
* Diesel CLI: Escape the database name for CREATE/DROP DATABASE operations. This allows you to have hyphens in your database name.
34+
3335
## [0.12.1] - 2017-05-07
3436

3537
### Changed

diesel_cli/src/database.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ use diesel::sqlite::SqliteConnection;
88
use diesel::mysql::MysqlConnection;
99
use diesel::types::Bool;
1010
use diesel::*;
11+
#[cfg(any(feature="postgres", feature="mysql"))]
12+
use super::query_helper;
13+
1114

1215
use database_error::{DatabaseError, DatabaseResult};
1316

@@ -131,7 +134,7 @@ fn create_database_if_needed(database_url: &str) -> DatabaseResult<()> {
131134
let (database, postgres_url) = change_database_of_url(database_url, "postgres");
132135
println!("Creating database: {}", database);
133136
let conn = try!(PgConnection::establish(&postgres_url));
134-
try!(conn.execute(&format!("CREATE DATABASE {}", database)));
137+
query_helper::create_database(&database).execute(&conn)?;
135138
}
136139
},
137140
#[cfg(feature="sqlite")]
@@ -147,7 +150,7 @@ fn create_database_if_needed(database_url: &str) -> DatabaseResult<()> {
147150
let (database, mysql_url) = change_database_of_url(database_url, "information_schema");
148151
println!("Creating database: {}", database);
149152
let conn = try!(MysqlConnection::establish(&mysql_url));
150-
try!(conn.execute(&format!("CREATE DATABASE {}", database)));
153+
query_helper::create_database(&database).execute(&conn)?;
151154
}
152155
},
153156
}
@@ -179,7 +182,7 @@ fn drop_database(database_url: &str) -> DatabaseResult<()> {
179182
let conn = try!(PgConnection::establish(&postgres_url));
180183
if try!(pg_database_exists(&conn, &database)) {
181184
println!("Dropping database: {}", database);
182-
try!(conn.execute(&format!("DROP DATABASE IF EXISTS {}", database)));
185+
query_helper::drop_database(&database).if_exists().execute(&conn)?;
183186
}
184187
},
185188
#[cfg(feature="sqlite")]
@@ -198,7 +201,7 @@ fn drop_database(database_url: &str) -> DatabaseResult<()> {
198201
let conn = try!(MysqlConnection::establish(&mysql_url));
199202
if try!(mysql_database_exists(&conn, &database)) {
200203
println!("Dropping database: {}", database);
201-
try!(conn.execute(&format!("DROP DATABASE IF EXISTS {}", database)));
204+
query_helper::drop_database(&database).if_exists().execute(&conn)?;
202205
}
203206
},
204207
}

diesel_cli/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ mod database_error;
2626
mod database;
2727
mod cli;
2828
mod pretty_printing;
29+
#[cfg(any(feature="postgres", feature="mysql"))]
30+
mod query_helper;
2931

3032
use chrono::*;
3133
use clap::{ArgMatches,Shell};

diesel_cli/src/query_helper.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use diesel::backend::Backend;
2+
use diesel::query_builder::*;
3+
use diesel::result::QueryResult;
4+
5+
#[derive(Debug, Clone)]
6+
pub struct DropDatabaseStatement {
7+
db_name: String,
8+
if_exists: bool,
9+
}
10+
11+
impl DropDatabaseStatement {
12+
pub fn new(db_name: &str) -> Self {
13+
DropDatabaseStatement {
14+
db_name: db_name.to_owned(),
15+
if_exists: false,
16+
}
17+
}
18+
19+
pub fn if_exists(self) -> Self {
20+
DropDatabaseStatement { if_exists: true, ..self }
21+
}
22+
}
23+
24+
impl<DB: Backend> QueryFragment<DB> for DropDatabaseStatement {
25+
fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
26+
out.push_sql("DROP DATABASE ");
27+
if self.if_exists {
28+
out.push_sql("IF EXISTS ");
29+
}
30+
out.push_identifier(&self.db_name)?;
31+
Ok(())
32+
}
33+
}
34+
35+
impl_query_id!(noop: DropDatabaseStatement);
36+
37+
#[derive(Debug, Clone)]
38+
pub struct CreateDatabaseStatement {
39+
db_name: String,
40+
}
41+
42+
impl CreateDatabaseStatement {
43+
pub fn new(db_name: &str) -> Self {
44+
CreateDatabaseStatement {
45+
db_name: db_name.to_owned(),
46+
}
47+
}
48+
}
49+
50+
impl<DB: Backend> QueryFragment<DB> for CreateDatabaseStatement {
51+
fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
52+
out.push_sql("CREATE DATABASE ");
53+
out.push_identifier(&self.db_name)?;
54+
Ok(())
55+
}
56+
}
57+
58+
impl_query_id!(noop: CreateDatabaseStatement);
59+
60+
pub fn drop_database(db_name: &str) -> DropDatabaseStatement {
61+
DropDatabaseStatement::new(db_name)
62+
}
63+
64+
pub fn create_database(db_name: &str) -> CreateDatabaseStatement {
65+
CreateDatabaseStatement::new(db_name)
66+
}

diesel_cli/tests/database_reset.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,21 @@ fn reset_works_with_migration_dir_by_env() {
131131
assert!(db.table_exists("users"));
132132
assert!(db.table_exists("__diesel_schema_migrations"));
133133
}
134+
135+
#[test]
136+
fn reset_sanitize_database_name() {
137+
let p = project("name-with-dashes")
138+
.folder("migrations")
139+
.build();
140+
let _db = database(&p.database_url()).create();
141+
142+
let result = p.command("database")
143+
.arg("reset")
144+
.run();
145+
146+
assert!(result.is_success(), "Result was unsuccessful {:?}", result.stdout());
147+
assert!(result.stdout().contains("Dropping database:"),
148+
"Unexpected stdout {}", result.stdout());
149+
assert!(result.stdout().contains("Creating database:"),
150+
"Unexpected stdout {}", result.stdout());
151+
}

diesel_cli/tests/support/mysql_database.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ impl Database {
1717
pub fn create(self) -> Self {
1818
let (database, mysql_url) = self.split_url();
1919
let conn = MysqlConnection::establish(&mysql_url).unwrap();
20-
conn.execute(&format!("CREATE DATABASE {}", database)).unwrap();
20+
conn.execute(&format!("CREATE DATABASE `{}`", database)).unwrap();
2121
self
2222
}
2323

@@ -56,6 +56,6 @@ impl Drop for Database {
5656
fn drop(&mut self) {
5757
let (database, mysql_url) = self.split_url();
5858
let conn = try_drop!(MysqlConnection::establish(&mysql_url), "Couldn't connect to database");
59-
try_drop!(conn.execute(&format!("DROP DATABASE IF EXISTS {}", database)), "Couldn't drop database");
59+
try_drop!(conn.execute(&format!("DROP DATABASE IF EXISTS `{}`", database)), "Couldn't drop database");
6060
}
6161
}

diesel_cli/tests/support/postgres_database.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ impl Database {
1717
pub fn create(self) -> Self {
1818
let (database, postgres_url) = self.split_url();
1919
let conn = PgConnection::establish(&postgres_url).unwrap();
20-
conn.execute(&format!("CREATE DATABASE {}", database)).unwrap();
20+
conn.execute(&format!(r#"CREATE DATABASE "{}""#, database)).unwrap();
2121
self
2222
}
2323

@@ -56,7 +56,7 @@ impl Drop for Database {
5656
let (database, postgres_url) = self.split_url();
5757
let conn = try_drop!(PgConnection::establish(&postgres_url), "Couldn't connect to database");
5858
conn.silence_notices(|| {
59-
try_drop!(conn.execute(&format!("DROP DATABASE IF EXISTS {}", database)), "Couldn't drop database");
59+
try_drop!(conn.execute(&format!(r#"DROP DATABASE IF EXISTS "{}""#, database)), "Couldn't drop database");
6060
});
6161
}
6262
}

0 commit comments

Comments
 (0)