diff --git a/app/models/topic.rb b/app/models/topic.rb index 95cb1b94dfa..6f155fec2f9 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -1846,7 +1846,7 @@ end # idx_topics_user_id_deleted_at (user_id) WHERE (deleted_at IS NULL) # idxtopicslug (slug) WHERE ((deleted_at IS NULL) AND (slug IS NOT NULL)) # index_topics_on_bannered_until (bannered_until) WHERE (bannered_until IS NOT NULL) -# index_topics_on_bumped_at (bumped_at) +# index_topics_on_bumped_at_public (bumped_at) WHERE ((deleted_at IS NULL) AND ((archetype)::text <> 'private_message'::text)) # index_topics_on_created_at_and_visible (created_at,visible) WHERE ((deleted_at IS NULL) AND ((archetype)::text <> 'private_message'::text)) # index_topics_on_id_and_deleted_at (id,deleted_at) # index_topics_on_id_filtered_banner (id) UNIQUE WHERE (((archetype)::text = 'banner'::text) AND (deleted_at IS NULL)) diff --git a/db/post_migrate/20210922064213_alter_bumped_at_indexes_on_topics.rb b/db/post_migrate/20210922064213_alter_bumped_at_indexes_on_topics.rb new file mode 100644 index 00000000000..037b6c20fc4 --- /dev/null +++ b/db/post_migrate/20210922064213_alter_bumped_at_indexes_on_topics.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +class AlterBumpedAtIndexesOnTopics < ActiveRecord::Migration[6.1] + disable_ddl_transaction! + + def up + execute(<<~SQL) + CREATE INDEX CONCURRENTLY IF NOT EXISTS index_topics_on_bumped_at_public + ON topics (bumped_at) + WHERE ((deleted_at IS NULL) AND ((archetype)::text <> 'private_message'::text)); + SQL + + execute(<<~SQL) + DROP INDEX IF EXISTS index_topics_on_bumped_at; + SQL + + # The following index is known to have not been properly renamed. Drop it if + # exists just in case. + execute(<<~SQL) + DROP INDEX IF EXISTS index_forum_threads_on_bumped_at; + SQL + end + + def down + raise ActiveRecord::IrreversibleMigration + end +end diff --git a/lib/topic_query.rb b/lib/topic_query.rb index 25362ab862f..57ffb9a726d 100644 --- a/lib/topic_query.rb +++ b/lib/topic_query.rb @@ -625,11 +625,11 @@ class TopicQuery @options[:category_id] = category_id if category_id if options[:no_subcategories] - result = result.where('categories.id = ?', category_id) + result = result.where('topics.category_id = ?', category_id) else - result = result.where("categories.id IN (?)", Category.subcategory_ids(category_id)) + result = result.where("topics.category_id IN (?)", Category.subcategory_ids(category_id)) if !SiteSetting.show_category_definitions_in_topic_lists - result = result.where("categories.topic_id <> topics.id OR categories.id = ?", category_id) + result = result.where("categories.topic_id <> topics.id OR topics.category_id = ?", category_id) end end result = result.references(:categories) diff --git a/spec/components/topic_query_spec.rb b/spec/components/topic_query_spec.rb index cd6595733ea..a7e7f2ecc01 100644 --- a/spec/components/topic_query_spec.rb +++ b/spec/components/topic_query_spec.rb @@ -268,33 +268,100 @@ describe TopicQuery do let!(:subcategory) { Fabricate(:category_with_definition, parent_category_id: category.id) } let(:subsubcategory) { Fabricate(:category_with_definition, parent_category_id: subcategory.id) } + # Not used in assertions but fabricated to ensure we're not leaking topics + # across categories + let!(:_category) { Fabricate(:category_with_definition) } + let!(:_subcategory) { Fabricate(:category_with_definition, parent_category_id: _category.id) } + it "works with subcategories" do - expect(TopicQuery.new(moderator, category: category.id).list_latest.topics.size).to eq(1) - expect(TopicQuery.new(moderator, category: subcategory.id).list_latest.topics.size).to eq(1) - expect(TopicQuery.new(moderator, category: category.id, no_subcategories: true).list_latest.topics.size).to eq(1) + expect( + TopicQuery + .new(moderator, category: category.id) + .list_latest.topics + ).to contain_exactly(category.topic) + + expect( + TopicQuery + .new(moderator, category: subcategory.id) + .list_latest.topics + ).to contain_exactly(subcategory.topic) + + expect( + TopicQuery + .new(moderator, category: category.id, no_subcategories: true) + .list_latest.topics + ).to contain_exactly(category.topic) end it "shows a subcategory definition topic in its parent list with the right site setting" do SiteSetting.show_category_definitions_in_topic_lists = true - expect(TopicQuery.new(moderator, category: category.id).list_latest.topics.size).to eq(2) + + expect( + TopicQuery + .new(moderator, category: category.id) + .list_latest.topics + ).to contain_exactly(category.topic, subcategory.topic) end it "works with subsubcategories" do SiteSetting.max_category_nesting = 3 - Fabricate(:topic, category: category) - Fabricate(:topic, category: subcategory) - Fabricate(:topic, category: subsubcategory) + category_topic = Fabricate(:topic, category: category) + subcategory_topic = Fabricate(:topic, category: subcategory) + subsubcategory_topic = Fabricate(:topic, category: subsubcategory) SiteSetting.max_category_nesting = 2 - expect(TopicQuery.new(moderator, category: category.id).list_latest.topics.size).to eq(3) - expect(TopicQuery.new(moderator, category: subcategory.id).list_latest.topics.size).to eq(3) - expect(TopicQuery.new(moderator, category: subsubcategory.id).list_latest.topics.size).to eq(2) + + expect( + TopicQuery + .new(moderator, category: category.id) + .list_latest.topics + ).to contain_exactly(category.topic, category_topic, subcategory_topic) + + expect( + TopicQuery + .new(moderator, category: subcategory.id) + .list_latest.topics + ).to contain_exactly( + subcategory.topic, + subcategory_topic, + subsubcategory_topic + ) + + expect( + TopicQuery + .new(moderator, category: subsubcategory.id) + .list_latest.topics + ).to contain_exactly(subsubcategory.topic, subsubcategory_topic) SiteSetting.max_category_nesting = 3 - expect(TopicQuery.new(moderator, category: category.id).list_latest.topics.size).to eq(4) - expect(TopicQuery.new(moderator, category: subcategory.id).list_latest.topics.size).to eq(3) - expect(TopicQuery.new(moderator, category: subsubcategory.id).list_latest.topics.size).to eq(2) + + expect( + TopicQuery + .new(moderator, category: category.id) + .list_latest.topics + ).to contain_exactly( + category.topic, + category_topic, + subcategory_topic, + subsubcategory_topic + ) + + expect( + TopicQuery + .new(moderator, category: subcategory.id) + .list_latest.topics + ).to contain_exactly( + subcategory.topic, + subcategory_topic, + subsubcategory_topic + ) + + expect( + TopicQuery + .new(moderator, category: subsubcategory.id) + .list_latest.topics + ).to contain_exactly(subsubcategory.topic, subsubcategory_topic) end end end