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
56
57
58
59
60
61
62
63
64
65
66
|
class RemoveRedundantPipelineStages < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up(attempts: 100)
remove_redundant_pipeline_stages!
remove_outdated_index!
add_unique_index!
rescue ActiveRecord::RecordNotUnique
retry if (attempts -= 1) > 0
raise StandardError, <<~EOS
Failed to add an unique index to ci_stages, despite retrying the
migration 100 times.
See https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/16580.
EOS
end
def down
remove_concurrent_index :ci_stages, [:pipeline_id, :name], unique: true
add_concurrent_index :ci_stages, [:pipeline_id, :name]
end
private
def remove_outdated_index!
return unless index_exists?(:ci_stages, [:pipeline_id, :name])
remove_concurrent_index :ci_stages, [:pipeline_id, :name]
end
def add_unique_index!
add_concurrent_index :ci_stages, [:pipeline_id, :name], unique: true
end
def remove_redundant_pipeline_stages!
disable_statement_timeout do
redundant_stages_ids = <<~SQL
SELECT id FROM ci_stages WHERE (pipeline_id, name) IN (
SELECT pipeline_id, name FROM ci_stages
GROUP BY pipeline_id, name HAVING COUNT(*) > 1
)
SQL
execute <<~SQL
UPDATE ci_builds SET stage_id = NULL WHERE stage_id IN (#{redundant_stages_ids})
SQL
if Gitlab::Database.postgresql?
execute <<~SQL
DELETE FROM ci_stages WHERE id IN (#{redundant_stages_ids})
SQL
else # We can't modify a table we are selecting from on MySQL
execute <<~SQL
DELETE a FROM ci_stages AS a, ci_stages AS b
WHERE a.pipeline_id = b.pipeline_id AND a.name = b.name
AND a.id <> b.id
SQL
end
end
end
end
|