Skip to content

Commit 03e2637

Browse files
committed
fix: performance issue in update_deprecated_advisory
1 parent fa2570a commit 03e2637

File tree

3 files changed

+43
-5
lines changed

3 files changed

+43
-5
lines changed

migration/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ mod m0000640_create_product_status;
8484
mod m0000650_alter_advisory_tracking;
8585
mod m0000660_purl_id_indexes;
8686
mod m0000670_version_cmp;
87+
mod m0000680_fix_update_deprecated_advisory;
8788

8889
pub struct Migrator;
8990

@@ -175,6 +176,7 @@ impl MigratorTrait for Migrator {
175176
Box::new(m0000650_alter_advisory_tracking::Migration),
176177
Box::new(m0000660_purl_id_indexes::Migration),
177178
Box::new(m0000670_version_cmp::Migration),
179+
Box::new(m0000680_fix_update_deprecated_advisory::Migration),
178180
]
179181
}
180182
}

migration/src/m0000650_alter_advisory_tracking/update_deprecated_advisory.sql

+8-5
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ CREATE OR REPLACE FUNCTION update_deprecated_advisory(identifier_input TEXT DEFA
22
RETURNS VOID AS
33
$$
44
BEGIN
5+
WITH MostRecent AS (SELECT DISTINCT ON (identifier) id
6+
FROM advisory
7+
WHERE identifier = COALESCE(identifier_input, identifier)
8+
ORDER BY identifier, modified DESC)
59
UPDATE advisory
6-
SET deprecated = (id != (SELECT id
7-
FROM advisory a
8-
WHERE a.identifier = COALESCE(identifier_input, advisory.identifier)
9-
ORDER BY a.modified DESC
10-
LIMIT 1))
10+
SET deprecated = CASE
11+
WHEN id IN (SELECT id FROM MostRecent) THEN FALSE
12+
ELSE TRUE
13+
END
1114
WHERE identifier = COALESCE(identifier_input, identifier);
1215
END;
1316
$$ LANGUAGE plpgsql;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use sea_orm_migration::prelude::*;
2+
3+
#[derive(DeriveMigrationName)]
4+
pub struct Migration;
5+
6+
#[async_trait::async_trait]
7+
impl MigrationTrait for Migration {
8+
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
9+
// This one is a bit special. The original migration was bugged by a performance issue. So
10+
// we need to replace that function if it was already present and passed the migration. But
11+
// We also need to replace the function in case the migration was not yet run. Because
12+
// otherwise, the migration would not pass.
13+
//
14+
// The strategy is to replace the original function with the new content, and re-apply it
15+
// with this migration. If the original migration did not yet pass, it would now. In any
16+
// case, this migration ensures the new content of the function from now on.
17+
manager
18+
.get_connection()
19+
.execute_unprepared(include_str!(
20+
"m0000650_alter_advisory_tracking/update_deprecated_advisory.sql"
21+
))
22+
.await
23+
.map(|_| ())?;
24+
25+
Ok(())
26+
}
27+
28+
async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> {
29+
// As the original version of this function was flawed, we replaced the original content
30+
// and don't migrate back.
31+
Ok(())
32+
}
33+
}

0 commit comments

Comments
 (0)