fix: scope merge request foreign key checks

This commit is contained in:
2026-08-17 01:09:05 +09:00
parent 46a44b232b
commit 0b954c1ab6
+48 -1
View File
@@ -1003,7 +1003,11 @@ fn replace_schema_marker(conn: &Connection, version: i64) -> Result<()> {
} }
fn ensure_foreign_key_integrity(conn: &Connection) -> Result<()> { fn ensure_foreign_key_integrity(conn: &Connection) -> Result<()> {
let mut statement = conn.prepare("PRAGMA foreign_key_check").map_err(db)?; for table in merge_request_domain_table_names(conn)? {
let quoted = table.replace('\'', "''");
let mut statement = conn
.prepare(&format!("PRAGMA foreign_key_check('{quoted}')"))
.map_err(db)?;
let mut rows = statement.query([]).map_err(db)?; let mut rows = statement.query([]).map_err(db)?;
if let Some(row) = rows.next().map_err(db)? { if let Some(row) = rows.next().map_err(db)? {
let table: String = row.get(0).map_err(db)?; let table: String = row.get(0).map_err(db)?;
@@ -1013,9 +1017,27 @@ fn ensure_foreign_key_integrity(conn: &Connection) -> Result<()> {
"foreign key integrity check failed for table {table}, row {row_id:?}, parent {parent}" "foreign key integrity check failed for table {table}, row {row_id:?}, parent {parent}"
))); )));
} }
}
Ok(()) Ok(())
} }
fn merge_request_domain_table_names(conn: &Connection) -> Result<Vec<String>> {
let mut statement = conn
.prepare(
"SELECT name FROM sqlite_master
WHERE type='table'
AND name LIKE 'merge_request_%'
AND name <> ?1
ORDER BY name",
)
.map_err(db)?;
statement
.query_map(params![MIGRATION_TABLE], |row| row.get::<_, String>(0))
.map_err(db)?
.collect::<std::result::Result<Vec<_>, _>>()
.map_err(db)
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
struct ColumnShape { struct ColumnShape {
cid: i64, cid: i64,
@@ -1600,6 +1622,31 @@ CREATE TABLE ticket_worker_assignments(workspace_id TEXT NOT NULL,ticket_id TEXT
assert!(!column_exists(&conn, "merge_requests", "merged_result_commit").unwrap()); assert!(!column_exists(&conn, "merge_requests", "merged_result_commit").unwrap());
} }
#[test]
fn unrelated_foreign_key_mismatch_does_not_block_merge_request_migration() {
let conn = exact_v8_connection();
conn.execute_batch(
"CREATE TABLE unrelated_parent(
left_id TEXT NOT NULL,
right_id TEXT NOT NULL,
PRIMARY KEY(left_id,right_id)
);
CREATE TABLE unrelated_child(
left_id TEXT REFERENCES unrelated_parent(left_id)
);",
)
.unwrap();
let error = conn
.query_row("PRAGMA foreign_key_check", [], |_| Ok(()))
.unwrap_err();
assert!(error.to_string().contains("foreign key mismatch"));
migrate(&conn).unwrap();
verify(&conn).unwrap();
assert_eq!(marker_version(&conn), 9);
assert!(column_exists(&conn, "merge_requests", "merged_result_commit").unwrap());
}
#[test] #[test]
fn versions_older_than_v8_are_rejected() { fn versions_older_than_v8_are_rejected() {
let conn = fresh_connection(); let conn = fresh_connection();