Skip to content

Commit d992dc8

Browse files
committed
Include inferred joinable! in diesel print-schema
This was a pretty straightforward addition. I've not included an explicit test that the filtering is applied, or that the unsafe constraints are removed here. It may be worth more exhaustively testing this.
1 parent f3e5d20 commit d992dc8

2 files changed

Lines changed: 109 additions & 9 deletions

File tree

diesel_cli/src/print_schema.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,20 @@ pub fn run_print_schema(
2525
schema_name: Option<&str>,
2626
filtering: &Filtering
2727
) -> Result<(), Box<Error>> {
28-
let table_data = load_table_names(database_url, schema_name)?
28+
let table_names = load_table_names(database_url, schema_name)?
2929
.into_iter()
3030
.filter(|t| !filtering.should_ignore_table(t))
31+
.collect::<Vec<_>>();
32+
let foreign_keys = load_foreign_key_constraints(database_url, schema_name)?;
33+
let foreign_keys = remove_unsafe_foreign_keys_for_codegen(
34+
database_url,
35+
&foreign_keys,
36+
&table_names,
37+
);
38+
let table_data = table_names.into_iter()
3139
.map(|t| load_table_data(database_url, t))
3240
.collect::<Result<_, Box<Error>>>()?;
33-
let definitions = TableDefinitions(table_data);
41+
let definitions = TableDefinitions(table_data, foreign_keys);
3442

3543
if let Some(schema_name) = schema_name {
3644
print!("{}", ModuleDefinition(schema_name, definitions));
@@ -54,7 +62,7 @@ impl<'a> Display for ModuleDefinition<'a> {
5462
}
5563
}
5664

57-
struct TableDefinitions(Vec<TableData>);
65+
struct TableDefinitions(Vec<TableData>, Vec<ForeignKeyConstraint>);
5866

5967
impl Display for TableDefinitions {
6068
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
@@ -67,6 +75,14 @@ impl Display for TableDefinitions {
6775
}
6876
writeln!(f, "{}", TableDefinition(table))?;
6977
}
78+
79+
if !self.1.is_empty() {
80+
write!(f, "\n")?;
81+
}
82+
83+
for foreign_key in &self.1 {
84+
writeln!(f, "{}", Joinable(foreign_key))?;
85+
}
7086
Ok(())
7187
}
7288
}
@@ -118,6 +134,20 @@ impl<'a> Display for ColumnDefinitions<'a> {
118134
}
119135
}
120136

137+
struct Joinable<'a>(&'a ForeignKeyConstraint);
138+
139+
impl<'a> Display for Joinable<'a> {
140+
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
141+
write!(
142+
f,
143+
"joinable!({} -> {} ({}));",
144+
self.0.child_table,
145+
self.0.parent_table,
146+
self.0.foreign_key,
147+
)
148+
}
149+
}
150+
121151
/// Lifted directly from libcore/fmt/builders.rs
122152
struct PadAdapter<'a, 'b: 'a> {
123153
fmt: &'a mut Formatter<'b>,

diesel_cli/tests/print_schema.rs

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ fn run_infer_schema() {
55
let p = project("print_schema").build();
66
let db = database(&p.database_url());
77

8-
// Make sure the project is setup
98
p.command("setup").run();
109

1110
db.execute("CREATE TABLE users1 (id INTEGER PRIMARY KEY);");
@@ -85,7 +84,6 @@ fn run_infer_schema_whitelist() {
8584
let p = project("print_schema_whitelist").build();
8685
let db = database(&p.database_url());
8786

88-
// Make sure the project is setup
8987
p.command("setup").run();
9088

9189
db.execute("CREATE TABLE users1 (id INTEGER PRIMARY KEY);");
@@ -137,7 +135,6 @@ fn run_infer_schema_blacklist() {
137135
let p = project("print_schema_blacklist").build();
138136
let db = database(&p.database_url());
139137

140-
// Make sure the project is setup
141138
p.command("setup").run();
142139

143140
db.execute("CREATE TABLE users1 (id INTEGER PRIMARY KEY);");
@@ -189,7 +186,6 @@ fn run_infer_schema_order() {
189186
let p = project("print_schema_order").build();
190187
let db = database(&p.database_url());
191188

192-
// Make sure the project is setup
193189
p.command("setup").run();
194190

195191
db.execute("CREATE TABLE def (id INTEGER PRIMARY KEY);");
@@ -299,7 +295,6 @@ fn run_infer_schema_compound_primary_key() {
299295
let p = project("print_schema_compound_primary_key").build();
300296
let db = database(&p.database_url());
301297

302-
// Make sure the project is setup
303298
p.command("setup").run();
304299

305300
db.execute("CREATE TABLE asd (id INTEGER, qsd INTEGER, PRIMARY KEY (id, qsd));");
@@ -361,7 +356,6 @@ fn print_schema_specifying_schema_name() {
361356
let p = project("print_schema_specifying_schema_name").build();
362357
let db = database(&p.database_url());
363358

364-
// Make sure the project is setup
365359
p.command("setup").run();
366360

367361
db.execute("CREATE SCHEMA custom_schema");
@@ -390,3 +384,79 @@ r"pub mod custom_schema {
390384
}
391385
");
392386
}
387+
388+
#[test]
389+
#[cfg(feature = "postgres")]
390+
fn print_schema_with_foreign_keys() {
391+
let p = project("print_schema_with_foreign_keys").build();
392+
let db = database(&p.database_url());
393+
394+
p.command("setup").run();
395+
396+
db.execute("CREATE TABLE users (id SERIAL PRIMARY KEY)");
397+
db.execute("CREATE TABLE posts (id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL REFERENCES users)");
398+
db.execute("CREATE TABLE comments (id SERIAL PRIMARY KEY, post_id INTEGER NOT NULL REFERENCES posts)");
399+
400+
let result = p.command("print-schema").run();
401+
402+
assert!(result.is_success(), "Result was unsuccessful {:?}", result);
403+
404+
assert_eq!(result.stdout(),
405+
r"table! {
406+
/// Representation of the `comments` table.
407+
///
408+
/// (Automatically generated by Diesel.)
409+
comments (id) {
410+
/// The `id` column of the `comments` table.
411+
///
412+
/// Its SQL type is `Int4`.
413+
///
414+
/// (Automatically generated by Diesel.)
415+
id -> Int4,
416+
/// The `post_id` column of the `comments` table.
417+
///
418+
/// Its SQL type is `Int4`.
419+
///
420+
/// (Automatically generated by Diesel.)
421+
post_id -> Int4,
422+
}
423+
}
424+
425+
table! {
426+
/// Representation of the `posts` table.
427+
///
428+
/// (Automatically generated by Diesel.)
429+
posts (id) {
430+
/// The `id` column of the `posts` table.
431+
///
432+
/// Its SQL type is `Int4`.
433+
///
434+
/// (Automatically generated by Diesel.)
435+
id -> Int4,
436+
/// The `user_id` column of the `posts` table.
437+
///
438+
/// Its SQL type is `Int4`.
439+
///
440+
/// (Automatically generated by Diesel.)
441+
user_id -> Int4,
442+
}
443+
}
444+
445+
table! {
446+
/// Representation of the `users` table.
447+
///
448+
/// (Automatically generated by Diesel.)
449+
users (id) {
450+
/// The `id` column of the `users` table.
451+
///
452+
/// Its SQL type is `Int4`.
453+
///
454+
/// (Automatically generated by Diesel.)
455+
id -> Int4,
456+
}
457+
}
458+
459+
joinable!(posts -> users (user_id));
460+
joinable!(comments -> posts (post_id));
461+
");
462+
}

0 commit comments

Comments
 (0)