Allow named expression indexes to be revertible.

Fixes #43331
This commit is contained in:
Oliver Günther 2022-01-01 21:25:28 +01:00
parent 3a2e361457
commit 5c200f8448
No known key found for this signature in database
GPG Key ID: 88872239EB414F99
3 changed files with 67 additions and 4 deletions

View File

@ -1,3 +1,15 @@
* Allow named expression indexes to be revertible.
Previously, the following code would raise an error in a reversible migration executed while rolling back, due to the index name not being used in the index removal.
```ruby
add_index(:settings, "(data->'property')", using: :gin, name: :index_settings_data_property)
```
Fixes #43331.
*Oliver Günther*
* Fix incorrect argument in PostgreSQL structure dump tasks.
Updating the `--no-comment` argument added in Rails 7 to the correct `--no-comments` argument.

View File

@ -1438,7 +1438,7 @@ module ActiveRecord
checks = []
if !options.key?(:name) && column_name.is_a?(String) && /\W/.match?(column_name)
if !options.key?(:name) && expression_column_name?(column_name)
options[:name] = index_name(table_name, column_name)
column_names = []
else
@ -1447,7 +1447,7 @@ module ActiveRecord
checks << lambda { |i| i.name == options[:name].to_s } if options.key?(:name)
if column_names.present?
if column_names.present? && !(options.key?(:name) && expression_column_name?(column_names))
checks << lambda { |i| index_name(table_name, i.columns) == index_name(table_name, column_names) }
end
@ -1515,7 +1515,7 @@ module ActiveRecord
end
def index_column_names(column_names)
if column_names.is_a?(String) && /\W/.match?(column_names)
if expression_column_name?(column_names)
column_names
else
Array(column_names)
@ -1523,13 +1523,18 @@ module ActiveRecord
end
def index_name_options(column_names)
if column_names.is_a?(String) && /\W/.match?(column_names)
if expression_column_name?(column_names)
column_names = column_names.scan(/\w+/).join("_")
end
{ column: column_names }
end
# Try to identify whether the given column name is an expression
def expression_column_name?(column_name)
column_name.is_a?(String) && /\W/.match?(column_name)
end
def strip_table_name_prefix_and_suffix(table_name)
prefix = Base.table_name_prefix
suffix = Base.table_name_suffix

View File

@ -0,0 +1,46 @@
# frozen_string_literal: true
require "cases/helper"
class PostgresqlInvertibleMigrationTest < ActiveRecord::PostgreSQLTestCase
class SilentMigration < ActiveRecord::Migration::Current
def write(*); end
end
class ExpressionIndexMigration < SilentMigration
def change
create_table("settings") do |t|
t.column :data, :jsonb
end
add_index :settings,
"(data->'foo')",
using: :gin,
name: "index_settings_data_foo"
end
end
self.use_transactional_tests = false
setup do
@connection = ActiveRecord::Base.connection
end
teardown do
@connection.drop_table "settings", if_exists: true
end
def test_migrate_revert_add_index_with_expression
ExpressionIndexMigration.new.migrate(:up)
assert @connection.table_exists?(:settings)
assert @connection.index_exists?(:settings, nil, name: "index_settings_data_foo"),
"index on index_settings_data_foo should exist"
ExpressionIndexMigration.new.migrate(:down)
assert_not @connection.table_exists?(:settings)
assert_not @connection.index_exists?(:settings, nil, name: "index_settings_data_foo"),
"index index_settings_data_foo should not exist"
end
end