]> Untitled Git - lemmy.git/commitdiff
Do not decrement comment score twice when removing then deleting. (#3196)
authorJP Moresmau <jp@moresmau.fr>
Mon, 3 Jul 2023 18:13:53 +0000 (20:13 +0200)
committerGitHub <noreply@github.com>
Mon, 3 Jul 2023 18:13:53 +0000 (14:13 -0400)
Fixes #3004

Co-authored-by: Dessalines <dessalines@users.noreply.github.com>
crates/db_schema/src/aggregates/person_aggregates.rs
migrations/2023-06-19-120700_no_double_deletion/down.sql [new file with mode: 0644]
migrations/2023-06-19-120700_no_double_deletion/up.sql [new file with mode: 0644]

index 6f804590845016db79490b97d44e6c8932ecb309..295f1bfbb94f78947aea0883c86ef711b70d7156 100644 (file)
@@ -22,7 +22,7 @@ mod tests {
   use crate::{
     aggregates::person_aggregates::PersonAggregates,
     source::{
-      comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm},
+      comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm, CommentUpdateForm},
       community::{Community, CommunityInsertForm},
       instance::Instance,
       person::{Person, PersonInsertForm},
@@ -138,6 +138,27 @@ mod tests {
       .unwrap();
     assert_eq!(0, after_post_like_remove.post_score);
 
+    Comment::update(
+      pool,
+      inserted_comment.id,
+      &CommentUpdateForm::builder().removed(Some(true)).build(),
+    )
+    .await
+    .unwrap();
+    Comment::update(
+      pool,
+      inserted_child_comment.id,
+      &CommentUpdateForm::builder().removed(Some(true)).build(),
+    )
+    .await
+    .unwrap();
+
+    let after_parent_comment_removed = PersonAggregates::read(pool, inserted_person.id)
+      .await
+      .unwrap();
+    assert_eq!(0, after_parent_comment_removed.comment_count);
+    assert_eq!(0, after_parent_comment_removed.comment_score);
+
     // Remove a parent comment (the scores should also be removed)
     Comment::delete(pool, inserted_comment.id).await.unwrap();
     Comment::delete(pool, inserted_child_comment.id)
diff --git a/migrations/2023-06-19-120700_no_double_deletion/down.sql b/migrations/2023-06-19-120700_no_double_deletion/down.sql
new file mode 100644 (file)
index 0000000..9472780
--- /dev/null
@@ -0,0 +1,19 @@
+-- This file should undo anything in `up.sql`
+create or replace function was_removed_or_deleted(TG_OP text, OLD record, NEW record)
+RETURNS boolean
+LANGUAGE plpgsql
+as $$
+    begin
+        IF (TG_OP = 'INSERT') THEN
+            return false;
+        end if;
+
+        IF (TG_OP = 'DELETE') THEN
+            return true;
+        end if;
+
+    return TG_OP = 'UPDATE' AND (
+            (OLD.deleted = 'f' AND NEW.deleted = 't') OR
+            (OLD.removed = 'f' AND NEW.removed = 't')
+            );
+END $$;
diff --git a/migrations/2023-06-19-120700_no_double_deletion/up.sql b/migrations/2023-06-19-120700_no_double_deletion/up.sql
new file mode 100644 (file)
index 0000000..bd6d1e5
--- /dev/null
@@ -0,0 +1,67 @@
+-- Deleting after removing should not decrement the count twice.
+create or replace function was_removed_or_deleted(TG_OP text, OLD record, NEW record)
+RETURNS boolean
+LANGUAGE plpgsql
+as $$
+    begin
+        IF (TG_OP = 'INSERT') THEN
+            return false;
+        end if;
+
+        IF (TG_OP = 'DELETE' AND OLD.deleted = 'f' AND OLD.removed = 'f') THEN
+            return true;
+        end if;
+
+    return TG_OP = 'UPDATE' AND (
+            (OLD.deleted = 'f' AND NEW.deleted = 't') OR
+            (OLD.removed = 'f' AND NEW.removed = 't')
+            );
+END $$;
+
+-- Recalculate proper comment count.
+UPDATE person_aggregates
+    SET comment_count = cnt.count
+    FROM (
+    SELECT creator_id, count(*) AS count FROM comment
+    WHERE deleted='f' AND removed='f'
+    GROUP BY creator_id
+        ) cnt
+    WHERE person_aggregates.person_id = cnt.creator_id;
+
+-- Recalculate proper comment score.
+UPDATE person_aggregates ua
+    SET comment_score = cd.score
+    FROM (
+        SELECT u.id AS creator_id,
+            coalesce(0, sum(cl.score)) as score
+        -- User join because comments could be empty
+        FROM person u
+            LEFT JOIN comment c ON u.id = c.creator_id AND c.deleted = 'f' AND c.removed = 'f'
+            LEFT JOIN comment_like cl ON c.id = cl.comment_id
+        GROUP BY u.id
+    ) cd
+    WHERE ua.person_id = cd.creator_id;
+
+-- Recalculate proper post count.
+UPDATE person_aggregates
+    SET post_count = cnt.count
+    FROM (
+    SELECT creator_id, count(*) AS count FROM post
+    WHERE deleted='f' AND removed='f'
+    GROUP BY creator_id
+        ) cnt
+    WHERE person_aggregates.person_id = cnt.creator_id;
+
+-- Recalculate proper post score.
+ UPDATE person_aggregates ua
+    SET post_score = pd.score
+    FROM (
+        SELECT u.id AS creator_id,
+            coalesce(0, sum(pl.score)) AS score
+            -- User join because posts could be empty
+        FROM person u
+            LEFT JOIN post p ON u.id = p.creator_id AND p.deleted = 'f' AND p.removed = 'f'
+            LEFT JOIN post_like pl ON p.id = pl.post_id
+        GROUP BY u.id
+    ) pd
+    WHERE ua.person_id = pd.creator_id;