1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge pull request #43333 from oliverguenther/revertible-expression-named-index

Allow named expression indexes to be revertible.
This commit is contained in:
Ryuta Kamizono 2022-01-03 19:58:49 +09:00 committed by GitHub
commit a3930799ea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
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. * Fix incorrect argument in PostgreSQL structure dump tasks.
Updating the `--no-comment` argument added in Rails 7 to the correct `--no-comments` argument. Updating the `--no-comment` argument added in Rails 7 to the correct `--no-comments` argument.

View file

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