FIX: delete synonym tags if other synonyms are already exist. (#21885)

When a topic already has multiple synonym tags of a target tag, if we try to update the "`tag_id`" column to target tag id then it will raise a unique violation error since there are multiple synonyms present in the topic. So before doing that action, we must delete the problematic tags so the topic has only one synonym tag to update.

This is not an issue when the topic has a target tag already along with synonyms.
This commit is contained in:
Vinoth Kannan 2023-06-02 19:47:29 +05:30 committed by GitHub
parent d40649c648
commit 6409794e0f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 0 deletions

View File

@ -773,6 +773,16 @@ module DiscourseTagging
successful = existing.select { |t| !t.errors.present? }
synonyms_ids = successful.map(&:id)
TopicTag.where(topic_id: target_tag.topics.with_deleted, tag_id: synonyms_ids).delete_all
TopicTag.joins(DB.sql_fragment(<<~SQL, synonyms_ids: synonyms_ids)).delete_all
INNER JOIN (
SELECT MIN(id) AS id, topic_id
FROM topic_tags
WHERE tag_id IN (:synonyms_ids)
GROUP BY topic_id
) AS tt ON tt.id < topic_tags.id
AND tt.topic_id = topic_tags.topic_id
AND topic_tags.tag_id IN (:synonyms_ids)
SQL
TopicTag.where(tag_id: synonyms_ids).update_all(tag_id: target_tag.id)
Scheduler::Defer.later "Update tag topic counts" do
Tag.ensure_consistency!

View File

@ -1552,6 +1552,19 @@ RSpec.describe DiscourseTagging do
expect(tag2.reload.target_tag).to eq(tag1)
end
it "replaces topic synonym tags with target tag" do
tag4, tag5 = 2.times.collect { Fabricate(:tag) }
topic = Fabricate(:topic, tags: [tag2, tag3, tag4])
expect {
expect(DiscourseTagging.add_or_create_synonyms_by_name(tag1, [tag2.name, tag3.name])).to eq(
true,
)
}.to_not change { Tag.count }
expect_same_tag_names(tag1.reload.synonyms, [tag2, tag3])
expect_same_tag_names(topic.reload.tags, [tag1, tag4])
expect(tag5.reload).to be_present
end
it "can create new tags" do
expect {
expect(DiscourseTagging.add_or_create_synonyms_by_name(tag1, ["synonym1"])).to eq(true)