From df8444e8132fab79c7c60d74513d176c98a35053 Mon Sep 17 00:00:00 2001 From: David Taylor Date: Mon, 30 Dec 2019 11:20:44 +0000 Subject: [PATCH] FIX: Update topic/post counter correctly when category has zero topics (#8600) Previously, categories without any topics were being excluded from the UPDATE query. This means the counter gets stuck, and the category cannot be deleted. This change ensures that the counters get correctly set to zero. --- app/models/category.rb | 13 +++++++++---- spec/models/category_spec.rb | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/app/models/category.rb b/app/models/category.rb index e19556c2697..455e50cbe8b 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -188,11 +188,16 @@ class Category < ActiveRecord::Base DB.exec <<~SQL UPDATE categories c - SET topic_count = x.topic_count, - post_count = x.post_count - FROM (#{topics_with_post_count}) x + SET topic_count = COALESCE(x.topic_count, 0), + post_count = COALESCE(x.post_count, 0) + FROM ( + SELECT ccc.id as category_id, stats.topic_count, stats.post_count + FROM categories ccc + LEFT JOIN (#{topics_with_post_count}) stats + ON stats.category_id = ccc.id + ) x WHERE x.category_id = c.id - AND (c.topic_count <> x.topic_count OR c.post_count <> x.post_count) + AND (c.topic_count <> COALESCE(x.topic_count, 0) OR c.post_count <> COALESCE(x.post_count, 0)) SQL # Yes, there are a lot of queries happening below. diff --git a/spec/models/category_spec.rb b/spec/models/category_spec.rb index f268c2c7356..fa9cf430104 100644 --- a/spec/models/category_spec.rb +++ b/spec/models/category_spec.rb @@ -642,6 +642,22 @@ describe Category do expect(@uncategorized.posts_week).to eq(1) end end + + context 'when there are no topics left' do + let!(:topic) { create_post(user: @category.user, category: @category.id).reload.topic } + + it 'can update the topic count to zero' do + @category.reload + expect(@category.topic_count).to eq(1) + expect(@category.topics.count).to eq(2) + topic.delete # Delete so the post trash/destroy hook doesn't fire + + Category.update_stats + @category.reload + expect(@category.topics.count).to eq(1) + expect(@category.topic_count).to eq(0) + end + end end describe "#url" do