60 lines
1.6 KiB
Ruby
60 lines
1.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class AddOldestMergeRequestsIndexAgain < ActiveRecord::Migration[6.0]
|
|
include Gitlab::Database::SchemaHelpers
|
|
include Gitlab::Database::MigrationHelpers
|
|
|
|
disable_ddl_transaction!
|
|
|
|
DOWNTIME = false
|
|
|
|
INDEX = 'index_on_merge_requests_for_latest_diffs'
|
|
|
|
def up
|
|
execute "DROP INDEX CONCURRENTLY #{INDEX}" if invalid_index?
|
|
|
|
return if index_exists_by_name?('merge_requests', INDEX)
|
|
|
|
begin
|
|
disable_statement_timeout do
|
|
execute "CREATE INDEX CONCURRENTLY #{INDEX} ON merge_requests " \
|
|
'USING btree (target_project_id) INCLUDE (id, latest_merge_request_diff_id)'
|
|
end
|
|
rescue ActiveRecord::StatementInvalid => ex
|
|
# Due to https://github.com/lfittl/pg_query/issues/184, if the CREATE
|
|
# INDEX statement fails, we trigger a separate error due to the Gem not
|
|
# supporting the INCLUDE syntax.
|
|
#
|
|
# To work around this, we raise a custom error instead, as these won't
|
|
# have a query context injected.
|
|
raise "The index #{INDEX} couldn't be added: #{ex.message}"
|
|
end
|
|
|
|
create_comment(
|
|
'INDEX',
|
|
INDEX,
|
|
'Index used to efficiently obtain the oldest merge request for a commit SHA'
|
|
)
|
|
end
|
|
|
|
def down
|
|
return unless index_exists_by_name?('merge_requests', INDEX)
|
|
|
|
disable_statement_timeout do
|
|
execute "DROP INDEX CONCURRENTLY #{INDEX}"
|
|
end
|
|
end
|
|
|
|
def invalid_index?
|
|
result = execute(<<~SQL)
|
|
SELECT pg_class.relname
|
|
FROM pg_class, pg_index
|
|
WHERE pg_index.indisvalid = false
|
|
AND pg_index.indexrelid = pg_class.oid
|
|
AND pg_class.relname = '#{INDEX}';
|
|
SQL
|
|
|
|
result.values.any?
|
|
end
|
|
end
|