diff --git a/migrations/2025-02-11-163554_fix-num-versions-trigger/down.sql b/migrations/2025-02-11-163554_fix-num-versions-trigger/down.sql new file mode 100644 index 00000000000..8193ba6193e --- /dev/null +++ b/migrations/2025-02-11-163554_fix-num-versions-trigger/down.sql @@ -0,0 +1 @@ +DROP FUNCTION IF EXISTS update_num_versions_from_versions CASCADE; diff --git a/migrations/2025-02-11-163554_fix-num-versions-trigger/up.sql b/migrations/2025-02-11-163554_fix-num-versions-trigger/up.sql new file mode 100644 index 00000000000..d6699259e9f --- /dev/null +++ b/migrations/2025-02-11-163554_fix-num-versions-trigger/up.sql @@ -0,0 +1,16 @@ +CREATE OR REPLACE FUNCTION update_num_versions_from_versions() RETURNS TRIGGER AS $$ +BEGIN + IF (TG_OP = 'INSERT') THEN + INSERT INTO default_versions (crate_id, version_id, num_versions) + VALUES (NEW.crate_id, NEW.id, 1) + ON CONFLICT (crate_id) DO UPDATE + SET num_versions = default_versions.num_versions + 1; + RETURN NEW; + ELSIF (TG_OP = 'DELETE') THEN + UPDATE default_versions + SET num_versions = num_versions - 1 + WHERE crate_id = OLD.crate_id; + RETURN OLD; + END IF; +END +$$ LANGUAGE plpgsql; diff --git a/src/tests/krate/publish/basics.rs b/src/tests/krate/publish/basics.rs index ca932cd9de8..bf674e0fc4c 100644 --- a/src/tests/krate/publish/basics.rs +++ b/src/tests/krate/publish/basics.rs @@ -2,7 +2,7 @@ use crate::schema::versions_published_by; use crate::tests::builders::{CrateBuilder, PublishBuilder}; use crate::tests::util::{RequestHelper, TestApp}; use diesel::QueryDsl; -use diesel_async::RunQueryDsl; +use diesel_async::{AsyncPgConnection, RunQueryDsl}; use googletest::prelude::*; use http::StatusCode; use insta::{assert_json_snapshot, assert_snapshot}; @@ -116,23 +116,12 @@ async fn new_krate_twice() { // The primary purpose is to verify that the `default_version` we provide is as expected. #[tokio::test(flavor = "multi_thread")] async fn new_krate_twice_alt() { - use crate::schema::default_versions; - let (app, _, _, token) = TestApp::full().with_token().await; - let mut conn = app.db_conn().await; let crate_to_publish = PublishBuilder::new("foo_twice", "2.0.0").description("2.0.0 description"); token.publish_crate(crate_to_publish).await.good(); - let num_versions = default_versions::table - .select(default_versions::num_versions) - .load::>(&mut conn) - .await - .unwrap(); - assert_eq!(num_versions.len(), 1); - assert_eq!(num_versions[0], Some(1)); - let crate_to_publish = PublishBuilder::new("foo_twice", "0.99.0"); let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::OK); @@ -141,14 +130,6 @@ async fn new_krate_twice_alt() { ".crate.updated_at" => "[datetime]", }); - let num_versions = default_versions::table - .select(default_versions::num_versions) - .load::>(&mut conn) - .await - .unwrap(); - assert_eq!(num_versions.len(), 1); - assert_eq!(num_versions[0], Some(2)); - let crates = app.crates_from_index_head("foo_twice"); assert_json_snapshot!(crates); @@ -180,3 +161,33 @@ async fn new_krate_duplicate_version() { assert_that!(app.stored_files().await, empty()); } + +#[tokio::test(flavor = "multi_thread")] +async fn new_krate_advance_num_versions() { + use crate::schema::default_versions; + + let (app, _, _, token) = TestApp::full().with_token().await; + let mut conn = app.db_conn().await; + + async fn assert_num_versions(conn: &mut AsyncPgConnection, expected: i32) { + let num_versions = default_versions::table + .select(default_versions::num_versions) + .load::>(conn) + .await + .unwrap(); + assert_eq!(num_versions.len(), 1); + assert_eq!(num_versions[0], Some(expected)); + } + + let crate_to_publish = PublishBuilder::new("foo", "2.0.0").description("2.0.0 description"); + token.publish_crate(crate_to_publish).await.good(); + assert_num_versions(&mut conn, 1).await; + + let crate_to_publish = PublishBuilder::new("foo", "2.0.1").description("2.0.1 description"); + token.publish_crate(crate_to_publish).await.good(); + assert_num_versions(&mut conn, 2).await; + + let crate_to_publish = PublishBuilder::new("foo", "2.0.2").description("2.0.2 description"); + token.publish_crate(crate_to_publish).await.good(); + assert_num_versions(&mut conn, 3).await; +}