diff --git a/diesel_cli/src/infer_schema_internals/sqlite.rs b/diesel_cli/src/infer_schema_internals/sqlite.rs index 3db89e26a933..144cdd50393f 100644 --- a/diesel_cli/src/infer_schema_internals/sqlite.rs +++ b/diesel_cli/src/infer_schema_internals/sqlite.rs @@ -31,7 +31,7 @@ table! { seq -> Integer, _table -> VarChar, from -> VarChar, - to -> VarChar, + to -> Nullable, on_update -> VarChar, on_delete -> VarChar, _match -> VarChar, @@ -71,20 +71,37 @@ pub fn load_foreign_key_constraints( .into_iter() .map(|child_table| { let query = format!("PRAGMA FOREIGN_KEY_LIST('{}')", child_table.sql_name); - Ok(sql::(&query) + sql::(&query) .load::(connection)? .into_iter() .map(|row| { let parent_table = TableName::from_name(row.parent_table); - ForeignKeyConstraint { + let primary_key = if let Some(primary_key) = row.primary_key { + primary_key + } else { + let mut primary_keys = get_primary_keys(connection, &parent_table)?; + if primary_keys.len() == 1 { + primary_keys + .pop() + .expect("There is exactly one primary key in this list") + } else { + return Err(diesel::result::Error::DatabaseError( + diesel::result::DatabaseErrorKind::Unknown, + Box::new(String::from( + "Found more than one primary key for an implicit reference", + )), + )); + } + }; + Ok(ForeignKeyConstraint { child_table: child_table.clone(), parent_table, foreign_key: row.foreign_key.clone(), foreign_key_rust_name: row.foreign_key, - primary_key: row.primary_key, - } + primary_key, + }) }) - .collect()) + .collect::>() }) .collect::>>>()?; Ok(rows.into_iter().flatten().collect()) @@ -163,7 +180,7 @@ struct ForeignKeyListRow { _seq: i32, parent_table: String, foreign_key: String, - primary_key: String, + primary_key: Option, _on_update: String, _on_delete: String, _match: String, diff --git a/diesel_cli/tests/print_schema.rs b/diesel_cli/tests/print_schema.rs index 9381b84750e5..35026da3986f 100644 --- a/diesel_cli/tests/print_schema.rs +++ b/diesel_cli/tests/print_schema.rs @@ -223,6 +223,12 @@ fn print_schema_array_type() { test_print_schema("print_schema_array_type", vec![]) } +#[test] +#[cfg(feature = "sqlite")] +fn print_schema_sqlite_implicit_foreign_key_reference() { + test_print_schema("print_schema_sqlite_implicit_foreign_key_reference", vec![]); +} + #[cfg(feature = "sqlite")] const BACKEND: &str = "sqlite"; #[cfg(feature = "postgres")] diff --git a/diesel_cli/tests/print_schema/print_schema_sqlite_implicit_foreign_key_reference/diesel.toml b/diesel_cli/tests/print_schema/print_schema_sqlite_implicit_foreign_key_reference/diesel.toml new file mode 100644 index 000000000000..f57985adb185 --- /dev/null +++ b/diesel_cli/tests/print_schema/print_schema_sqlite_implicit_foreign_key_reference/diesel.toml @@ -0,0 +1,2 @@ +[print_schema] +file = "src/schema.rs" diff --git a/diesel_cli/tests/print_schema/print_schema_sqlite_implicit_foreign_key_reference/sqlite/expected.rs b/diesel_cli/tests/print_schema/print_schema_sqlite_implicit_foreign_key_reference/sqlite/expected.rs new file mode 100644 index 000000000000..f791e8ac91f7 --- /dev/null +++ b/diesel_cli/tests/print_schema/print_schema_sqlite_implicit_foreign_key_reference/sqlite/expected.rs @@ -0,0 +1,24 @@ +// @generated automatically by Diesel CLI. + +diesel::table! { + accounts (id) { + id -> Integer, + account -> Text, + data_center_id -> Integer, + auth_key -> Binary, + } +} + +diesel::table! { + data_centers (id) { + id -> Integer, + name -> Text, + } +} + +diesel::joinable!(accounts -> data_centers (data_center_id)); + +diesel::allow_tables_to_appear_in_same_query!( + accounts, + data_centers, +); diff --git a/diesel_cli/tests/print_schema/print_schema_sqlite_implicit_foreign_key_reference/sqlite/schema.sql b/diesel_cli/tests/print_schema/print_schema_sqlite_implicit_foreign_key_reference/sqlite/schema.sql new file mode 100644 index 000000000000..0680c88cbf80 --- /dev/null +++ b/diesel_cli/tests/print_schema/print_schema_sqlite_implicit_foreign_key_reference/sqlite/schema.sql @@ -0,0 +1,13 @@ +CREATE TABLE data_centers ( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL +); + +CREATE TABLE accounts ( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + account TEXT NOT NULL, + data_center_id INTEGER NOT NULL, + auth_key BLOB NOT NULL, + UNIQUE (account, data_center_id), + FOREIGN KEY (data_center_id) REFERENCES data_centers +);