Skip to content

Commit feda6ce

Browse files
authored
fix(schema-engine): fix migrate diff on MySQL for foreign key index removals (#5020)
1 parent dc59d1c commit feda6ce

File tree

2 files changed

+94
-0
lines changed
  • schema-engine
    • connectors/sql-schema-connector/src/sql_schema_differ
    • sql-migration-tests/tests/migrations

2 files changed

+94
-0
lines changed

schema-engine/connectors/sql-schema-connector/src/sql_schema_differ/index.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
use sql_schema_describer::walkers::{IndexWalker, TableWalker};
22

33
pub(super) fn index_covers_fk(table: TableWalker<'_>, index: IndexWalker<'_>) -> bool {
4+
// Only normal indexes can cover foreign keys.
5+
if index.index_type() != sql_schema_describer::IndexType::Normal {
6+
return false;
7+
}
8+
49
table.foreign_keys().any(|fk| {
510
let fk_cols = fk.constrained_columns().map(|col| col.name());
611
let index_cols = index.column_names();

schema-engine/sql-migration-tests/tests/migrations/diff.rs

+89
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,95 @@ use schema_core::{
77
use sql_migration_tests::{test_api::*, utils::to_schema_containers};
88
use std::sync::Arc;
99

10+
#[test_connector(tags(Sqlite, Mysql, Postgres, CockroachDb, Mssql))]
11+
fn from_unique_index_to_without(mut api: TestApi) {
12+
let tempdir = tempfile::tempdir().unwrap();
13+
let host = Arc::new(TestConnectorHost::default());
14+
15+
api.connector.set_host(host.clone());
16+
17+
let from_schema = api.datamodel_with_provider(
18+
r#"
19+
model Post {
20+
id Int @id
21+
title String
22+
author User? @relation(fields: [authorId], references: [id])
23+
authorId Int? @unique
24+
// ^^^^^^^ this will be removed later
25+
}
26+
27+
model User {
28+
id Int @id
29+
name String?
30+
posts Post[]
31+
}
32+
"#,
33+
);
34+
35+
let to_schema = api.datamodel_with_provider(
36+
r#"
37+
model Post {
38+
id Int @id
39+
title String
40+
author User? @relation(fields: [authorId], references: [id])
41+
authorId Int?
42+
}
43+
44+
model User {
45+
id Int @id
46+
name String?
47+
posts Post[]
48+
}
49+
"#,
50+
);
51+
52+
let from_file = write_file_to_tmp(&from_schema, &tempdir, "from");
53+
let to_file = write_file_to_tmp(&to_schema, &tempdir, "to");
54+
55+
api.diff(DiffParams {
56+
exit_code: None,
57+
from: DiffTarget::SchemaDatamodel(SchemasContainer {
58+
files: vec![SchemaContainer {
59+
path: from_file.to_string_lossy().into_owned(),
60+
content: from_schema.to_string(),
61+
}],
62+
}),
63+
shadow_database_url: None,
64+
to: DiffTarget::SchemaDatamodel(SchemasContainer {
65+
files: vec![SchemaContainer {
66+
path: to_file.to_string_lossy().into_owned(),
67+
content: to_schema.to_string(),
68+
}],
69+
}),
70+
script: true,
71+
})
72+
.unwrap();
73+
74+
let expected_printed_messages = if api.is_mysql() {
75+
expect![[r#"
76+
[
77+
"-- DropIndex\nDROP INDEX `Post_authorId_key` ON `Post`;\n",
78+
]
79+
"#]]
80+
} else if api.is_sqlite() || api.is_postgres() || api.is_cockroach() {
81+
expect![[r#"
82+
[
83+
"-- DropIndex\nDROP INDEX \"Post_authorId_key\";\n",
84+
]
85+
"#]]
86+
} else if api.is_mssql() {
87+
expect![[r#"
88+
[
89+
"BEGIN TRY\n\nBEGIN TRAN;\n\n-- DropIndex\nDROP INDEX [Post_authorId_key] ON [dbo].[Post];\n\nCOMMIT TRAN;\n\nEND TRY\nBEGIN CATCH\n\nIF @@TRANCOUNT > 0\nBEGIN\n ROLLBACK TRAN;\nEND;\nTHROW\n\nEND CATCH\n",
90+
]
91+
"#]]
92+
} else {
93+
unreachable!()
94+
};
95+
96+
expected_printed_messages.assert_debug_eq(&host.printed_messages.lock().unwrap());
97+
}
98+
1099
#[test_connector(tags(Sqlite))]
11100
fn diffing_postgres_schemas_when_initialized_on_sqlite(mut api: TestApi) {
12101
// We should get a postgres diff.

0 commit comments

Comments
 (0)