From 44afcd2019d3c1c77c91f24a08e657331568c39f Mon Sep 17 00:00:00 2001
From: Stan Hu <stanhu@gmail.com>
Date: Mon, 27 Apr 2015 06:09:20 -0700
Subject: [PATCH] Fix DB error when trying to tag a repository

Upon tagging a repository, an error due to a missing migration occurred:

```
    PG::Error: ERROR:  column "taggings_count" does not exist
        LINE 1: UPDATE "tags" SET "taggings_count" = COALESCE("taggings_coun...
```

Ran `rake acts_as_taggable_on_engine:install:migrations`, removed the first
migration that created the `tags` and `taggings` table, and added the rest.

Closes #1512
Closes https://github.com/gitlabhq/gitlabhq/issues/6867
Closes https://github.com/gitlabhq/gitlabhq/issues/9194
---
 CHANGELOG                                     |  2 +-
 ...ique_indices.acts_as_taggable_on_engine.rb | 20 +++++++++++++++++++
 ...ache_to_tags.acts_as_taggable_on_engine.rb | 15 ++++++++++++++
 ...ggable_index.acts_as_taggable_on_engine.rb | 10 ++++++++++
 ...or_tag_names.acts_as_taggable_on_engine.rb | 10 ++++++++++
 db/schema.rb                                  |  7 +++++--
 features/project/project.feature              |  7 +++++++
 features/steps/project/project.rb             |  8 ++++++++
 8 files changed, 76 insertions(+), 3 deletions(-)
 create mode 100644 db/migrate/20150425164648_add_missing_unique_indices.acts_as_taggable_on_engine.rb
 create mode 100644 db/migrate/20150425164649_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb
 create mode 100644 db/migrate/20150425164650_add_missing_taggable_index.acts_as_taggable_on_engine.rb
 create mode 100644 db/migrate/20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb

diff --git a/CHANGELOG b/CHANGELOG
index 38dcb7dd227..840ef787be6 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -7,7 +7,7 @@ v 7.11.0 (unreleased)
   - Fix "Cannot move project" error message from popping up after a successful transfer (Stan Hu)
   - Redirect to sign in page after signing out.
   - Fix "Hello @username." references not working by no longer allowing usernames to end in period.
-  -
+  - Fix DB error when trying to tag a repository (Stan Hu)
   - Add "Reply quoting selected text" shortcut key (`r`)
   - Fix bug causing `@whatever` inside an issue's first code block to be picked up as a user mention.
   - Fix bug causing `@whatever` inside an inline code snippet (backtick-style) to be picked up as a user mention.
diff --git a/db/migrate/20150425164648_add_missing_unique_indices.acts_as_taggable_on_engine.rb b/db/migrate/20150425164648_add_missing_unique_indices.acts_as_taggable_on_engine.rb
new file mode 100644
index 00000000000..4ca676f6c72
--- /dev/null
+++ b/db/migrate/20150425164648_add_missing_unique_indices.acts_as_taggable_on_engine.rb
@@ -0,0 +1,20 @@
+# This migration comes from acts_as_taggable_on_engine (originally 2)
+class AddMissingUniqueIndices < ActiveRecord::Migration
+  def self.up
+    add_index :tags, :name, unique: true
+
+    remove_index :taggings, :tag_id
+    remove_index :taggings, [:taggable_id, :taggable_type, :context]
+    add_index :taggings,
+              [:tag_id, :taggable_id, :taggable_type, :context, :tagger_id, :tagger_type],
+              unique: true, name: 'taggings_idx'
+  end
+
+  def self.down
+    remove_index :tags, :name
+
+    remove_index :taggings, name: 'taggings_idx'
+    add_index :taggings, :tag_id
+    add_index :taggings, [:taggable_id, :taggable_type, :context]
+  end
+end
diff --git a/db/migrate/20150425164649_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb b/db/migrate/20150425164649_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb
new file mode 100644
index 00000000000..8edb5080781
--- /dev/null
+++ b/db/migrate/20150425164649_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb
@@ -0,0 +1,15 @@
+# This migration comes from acts_as_taggable_on_engine (originally 3)
+class AddTaggingsCounterCacheToTags < ActiveRecord::Migration
+  def self.up
+    add_column :tags, :taggings_count, :integer, default: 0
+
+    ActsAsTaggableOn::Tag.reset_column_information
+    ActsAsTaggableOn::Tag.find_each do |tag|
+      ActsAsTaggableOn::Tag.reset_counters(tag.id, :taggings)
+    end
+  end
+
+  def self.down
+    remove_column :tags, :taggings_count
+  end
+end
diff --git a/db/migrate/20150425164650_add_missing_taggable_index.acts_as_taggable_on_engine.rb b/db/migrate/20150425164650_add_missing_taggable_index.acts_as_taggable_on_engine.rb
new file mode 100644
index 00000000000..71f2d7f4330
--- /dev/null
+++ b/db/migrate/20150425164650_add_missing_taggable_index.acts_as_taggable_on_engine.rb
@@ -0,0 +1,10 @@
+# This migration comes from acts_as_taggable_on_engine (originally 4)
+class AddMissingTaggableIndex < ActiveRecord::Migration
+  def self.up
+    add_index :taggings, [:taggable_id, :taggable_type, :context]
+  end
+
+  def self.down
+    remove_index :taggings, [:taggable_id, :taggable_type, :context]
+  end
+end
diff --git a/db/migrate/20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb b/db/migrate/20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb
new file mode 100644
index 00000000000..bfb06bc7cda
--- /dev/null
+++ b/db/migrate/20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb
@@ -0,0 +1,10 @@
+# This migration comes from acts_as_taggable_on_engine (originally 5)
+# This migration is added to circumvent issue #623 and have special characters
+# work properly
+class ChangeCollationForTagNames < ActiveRecord::Migration
+  def up
+    if ActsAsTaggableOn::Utils.using_mysql?
+      execute("ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;")
+    end
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 8683c0446fe..adfc241deae 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -433,13 +433,16 @@ ActiveRecord::Schema.define(version: 20150425173433) do
     t.datetime "created_at"
   end
 
-  add_index "taggings", ["tag_id"], name: "index_taggings_on_tag_id", using: :btree
+  add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true, using: :btree
   add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree
 
   create_table "tags", force: true do |t|
-    t.string "name"
+    t.string  "name"
+    t.integer "taggings_count", default: 0
   end
 
+  add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree
+
   create_table "users", force: true do |t|
     t.string   "email",                         default: "",    null: false
     t.string   "encrypted_password",            default: "",    null: false
diff --git a/features/project/project.feature b/features/project/project.feature
index 3e1fd54bee8..ae28312a69a 100644
--- a/features/project/project.feature
+++ b/features/project/project.feature
@@ -55,3 +55,10 @@ Feature: Project
     Then I should see project "Forum" README
     And I visit project "Shop" page
     Then I should see project "Shop" README
+
+  Scenario: I tag a project
+    When I visit edit project "Shop" page
+    Then I should see project settings
+    And I add project tags
+    And I save project
+    Then I should see project tags
diff --git a/features/steps/project/project.rb b/features/steps/project/project.rb
index d39c8e7d2db..f14396bcfff 100644
--- a/features/steps/project/project.rb
+++ b/features/steps/project/project.rb
@@ -94,4 +94,12 @@ class Spinach::Features::Project < Spinach::FeatureSteps
     page.should have_link 'README.md'
     page.should have_content 'testme'
   end
+
+  step 'I add project tags' do
+    fill_in 'Tags', with: 'tag1, tag2'
+  end
+
+  step 'I should see project tags' do
+    expect(find_field('Tags').value).to eq 'tag1, tag2'
+  end
 end
-- 
GitLab