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:
commit
a3930799ea
3 changed files with 67 additions and 4 deletions
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
Loading…
Reference in a new issue