Commit eb21f932 authored by Nick Thomas's avatar Nick Thomas

Only use DROP INDEX CONCURRENTLY on postgreql 9.2+

parent 6ece9792
...@@ -52,7 +52,7 @@ stages: ...@@ -52,7 +52,7 @@ stages:
.use-pg: &use-pg .use-pg: &use-pg
services: services:
- postgres:9.2 - postgres:9.1
- redis:alpine - redis:alpine
.use-mysql: &use-mysql .use-mysql: &use-mysql
......
...@@ -21,9 +21,8 @@ class IndexRoutesPathForLike < ActiveRecord::Migration ...@@ -21,9 +21,8 @@ class IndexRoutesPathForLike < ActiveRecord::Migration
def down def down
return unless Gitlab::Database.postgresql? return unless Gitlab::Database.postgresql?
return unless index_exists?(:routes, :path, name: INDEX_NAME)
if index_exists?(:routes, :path, name: INDEX_NAME) remove_concurrent_index_by_name(:routes, INDEX_NAME)
execute("DROP INDEX CONCURRENTLY #{INDEX_NAME};")
end
end end
end end
...@@ -11,13 +11,7 @@ class RemoveIndexForUsersCurrentSignInAt < ActiveRecord::Migration ...@@ -11,13 +11,7 @@ class RemoveIndexForUsersCurrentSignInAt < ActiveRecord::Migration
disable_ddl_transaction! disable_ddl_transaction!
def up def up
if index_exists? :users, :current_sign_in_at remove_concurrent_index :users, :current_sign_in_at
if Gitlab::Database.postgresql?
execute 'DROP INDEX CONCURRENTLY index_users_on_current_sign_in_at;'
else
remove_concurrent_index :users, :current_sign_in_at
end
end
end end
def down def down
......
...@@ -21,9 +21,8 @@ class IndexRedirectRoutesPathForLike < ActiveRecord::Migration ...@@ -21,9 +21,8 @@ class IndexRedirectRoutesPathForLike < ActiveRecord::Migration
def down def down
return unless Gitlab::Database.postgresql? return unless Gitlab::Database.postgresql?
return unless index_exists?(:redirect_routes, :path, name: INDEX_NAME)
if index_exists?(:redirect_routes, :path, name: INDEX_NAME) remove_concurrent_index_by_name(:redirect_routes, INDEX_NAME)
execute("DROP INDEX CONCURRENTLY #{INDEX_NAME};")
end
end end
end end
...@@ -42,7 +42,7 @@ module Gitlab ...@@ -42,7 +42,7 @@ module Gitlab
'in the body of your migration class' 'in the body of your migration class'
end end
if Database.postgresql? if supports_drop_index_concurrently?
options = options.merge({ algorithm: :concurrently }) options = options.merge({ algorithm: :concurrently })
disable_statement_timeout disable_statement_timeout
end end
...@@ -50,6 +50,39 @@ module Gitlab ...@@ -50,6 +50,39 @@ module Gitlab
remove_index(table_name, options.merge({ column: column_name })) remove_index(table_name, options.merge({ column: column_name }))
end end
# Removes an existing index, concurrently when supported
#
# On PostgreSQL this method removes an index concurrently.
#
# Example:
#
# remove_concurrent_index :users, "index_X_by_Y"
#
# See Rails' `remove_index` for more info on the available arguments.
def remove_concurrent_index_by_name(table_name, index_name, options = {})
if transaction_open?
raise 'remove_concurrent_index_by_name can not be run inside a transaction, ' \
'you can disable transactions by calling disable_ddl_transaction! ' \
'in the body of your migration class'
end
if supports_drop_index_concurrently?
options = options.merge({ algorithm: :concurrently })
disable_statement_timeout
end
remove_index(table_name, options.merge({ name: index_name }))
end
# Only available on Postgresql >= 9.2
def supports_drop_index_concurrently?
return false unless Database.postgresql?
version = select_one("SELECT current_setting('server_version_num') AS v")['v'].to_i
version >= 90200
end
# Adds a foreign key with only minimal locking on the tables involved. # Adds a foreign key with only minimal locking on the tables involved.
# #
# This method only requires minimal locking when using PostgreSQL. When # This method only requires minimal locking when using PostgreSQL. When
......
...@@ -66,16 +66,23 @@ describe Gitlab::Database::MigrationHelpers, lib: true do ...@@ -66,16 +66,23 @@ describe Gitlab::Database::MigrationHelpers, lib: true do
context 'using PostgreSQL' do context 'using PostgreSQL' do
before do before do
allow(Gitlab::Database).to receive(:postgresql?).and_return(true) allow(model).to receive(:supports_drop_index_concurrently?).and_return(true)
allow(model).to receive(:disable_statement_timeout) allow(model).to receive(:disable_statement_timeout)
end end
it 'removes the index concurrently' do it 'removes the index concurrently by column name' do
expect(model).to receive(:remove_index). expect(model).to receive(:remove_index).
with(:users, { algorithm: :concurrently, column: :foo }) with(:users, { algorithm: :concurrently, column: :foo })
model.remove_concurrent_index(:users, :foo) model.remove_concurrent_index(:users, :foo)
end end
it 'removes the index concurrently by index name' do
expect(model).to receive(:remove_index).
with(:users, { algorithm: :concurrently, name: "index_x_by_y" })
model.remove_concurrent_index_by_name(:users, "index_x_by_y")
end
end end
context 'using MySQL' do context 'using MySQL' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment