summaryrefslogtreecommitdiff
path: root/db/post_migrate/20190404143330_add_unique_constraint_to_approvals_user_id_and_merge_request_id.rb
blob: 447f91ebc7ee007d97693c87fe16ba81c15d30db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# frozen_string_literal: true

class AddUniqueConstraintToApprovalsUserIdAndMergeRequestId < ActiveRecord::Migration[5.0]
  include Gitlab::Database::MigrationHelpers

  DOWNTIME = false

  disable_ddl_transaction!

  def up
    remove_duplicates
    add_concurrent_index :approvals, [:user_id, :merge_request_id], unique: true
  end

  def down
    remove_concurrent_index :approvals, [:user_id, :merge_request_id]
  end

  private

  def remove_duplicates
    add_concurrent_index :approvals, [:user_id, :merge_request_id, :id]

    if Gitlab::Database.mysql?
      execute <<-SQL
        DELETE FROM a
        USING approvals AS a
        INNER JOIN (
          SELECT user_id, merge_request_id, MIN(id) as min_id
          FROM approvals
          GROUP BY user_id, merge_request_id
          HAVING COUNT(id) > 1
        ) as approvals_with_duplicates
        ON approvals_with_duplicates.user_id = a.user_id
        AND approvals_with_duplicates.merge_request_id = a.merge_request_id
        WHERE approvals_with_duplicates.min_id <> a.id;
      SQL
    else
      execute <<-SQL
        DELETE FROM approvals
        USING (
          SELECT user_id, merge_request_id, MIN(id) as min_id
          FROM approvals
          GROUP BY user_id, merge_request_id
          HAVING COUNT(id) > 1
        ) as approvals_with_duplicates
        WHERE approvals_with_duplicates.user_id = approvals.user_id
        AND approvals_with_duplicates.merge_request_id = approvals.merge_request_id
        AND approvals_with_duplicates.min_id <> approvals.id;
      SQL
    end

    remove_concurrent_index :approvals, [:user_id, :merge_request_id, :id]
  end
end