Skip to content

Commit

Permalink
Drop invalid index in safe_add_index
Browse files Browse the repository at this point in the history
  • Loading branch information
dgsuarez committed Sep 7, 2023
1 parent fa43564 commit 2ecf093
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 3 deletions.
16 changes: 16 additions & 0 deletions lib/strong_migrations/adapters/postgresql_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,22 @@ def default_volatile?(default)
rows.empty? || rows.any? { |r| r["provolatile"] == "v" }
end

def invalid_index?(index_name)
query = <<~SQL
SELECT
pg_class.relname
FROM
pg_class
INNER JOIN
pg_index ON pg_index.indexrelid = pg_class.oid
WHERE
pg_index.indisvalid = false AND
pg_class.relname = #{connection.quote(index_name)}
SQL

select_all(query.squish).any?
end

private

def set_timeout(setting, timeout)
Expand Down
17 changes: 14 additions & 3 deletions lib/strong_migrations/safe_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ def safe_by_default_method?(method)
StrongMigrations.safe_by_default && [:add_index, :add_belongs_to, :add_reference, :remove_index, :add_foreign_key, :add_check_constraint, :change_column_null].include?(method)
end

# TODO check if invalid index with expected name exists and remove if needed
def safe_add_index(*args, **options)
def safe_add_index(table, columns, **options)
index_name = options.fetch(:name, connection.index_name(table, columns))
if postgresql? && adapter.invalid_index?(index_name)
safe_remove_index(table, columns, **options)
end

disable_transaction
@migration.add_index(*args, **options.merge(algorithm: :concurrently))

@migration.add_index(table, columns, **options.merge(algorithm: :concurrently))
end

def safe_remove_index(*args, **options)
Expand Down Expand Up @@ -124,5 +129,11 @@ def disable_transaction
def in_transaction?
@migration.connection.open_transactions > 0
end

private

def postgresql?
adapter.instance_of?(Adapters::PostgreSQLAdapter)
end
end
end
6 changes: 6 additions & 0 deletions test/migrations/add_index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ def change
end
end

class SafeAddIndexColumnsUnique < TestMigration
def change
add_index :users, :name, unique: true
end
end

class AddIndexName < TestMigration
def change
add_index :users, :name, name: "my_index"
Expand Down
17 changes: 17 additions & 0 deletions test/safe_by_default_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,21 @@ def test_change_column_null_default
ensure
User.delete_all
end

def test_add_index_with_invalid_present
skip unless postgresql?

User.create(name: 'same')
duplicate = User.create(name: 'same')

assert_raises(ActiveRecord::RecordNotUnique) do
migrate SafeAddIndexColumnsUnique
end

duplicate.delete

assert_safe SafeAddIndexColumnsUnique
ensure
User.delete_all
end
end

0 comments on commit 2ecf093

Please sign in to comment.