Skip to content

Commit 6b5ae0f

Browse files
authored
Maintain index options during change_column operations (#1345)
1 parent 766b219 commit 6b5ae0f

File tree

3 files changed

+113
-2
lines changed

3 files changed

+113
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@
1717
- [#1320](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1320) Fix SQL statement to calculate `updated_at` when upserting.
1818
- [#1327](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1327) Fix multiple `nil` identity columns for merge insert.
1919
- [#1338](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1338) Fix `insert_all`/`upsert_all` for table names containing numbers.
20+
- [#1345](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1345) Maintain index options during `change_column` operations.
2021

2122
Please check [8-0-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/8-0-stable/CHANGELOG.md) for previous changes.

lib/active_record/connection_adapters/sqlserver/schema_statements.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,12 +210,14 @@ def change_column(table_name, column_name, type, options = {})
210210
sql_commands << "ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{default_constraint_name(table_name, column_name)} DEFAULT #{default} FOR #{quote_column_name(column_name)}"
211211
end
212212

213+
sql_commands.each { |c| execute(c) }
214+
213215
# Add any removed indexes back
214216
indexes.each do |index|
215-
sql_commands << "CREATE INDEX #{quote_table_name(index.name)} ON #{quote_table_name(table_name)} (#{index.columns.map { |c| quote_column_name(c) }.join(", ")})"
217+
create_index_def = CreateIndexDefinition.new(index)
218+
execute schema_creation.accept(create_index_def)
216219
end
217220

218-
sql_commands.each { |c| execute(c) }
219221
clear_cache!
220222
end
221223

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# frozen_string_literal: true
2+
3+
require "cases/helper_sqlserver"
4+
5+
class ChangeColumnIndexTestSqlServer < ActiveRecord::TestCase
6+
class CreateClientsWithUniqueIndex < ActiveRecord::Migration[8.0]
7+
def up
8+
create_table :clients do |t|
9+
t.string :name, limit: 15
10+
end
11+
add_index :clients, :name, unique: true
12+
end
13+
14+
def down
15+
drop_table :clients
16+
end
17+
end
18+
19+
class CreateBlogPostsWithMultipleIndexesOnTheSameColumn < ActiveRecord::Migration[8.0]
20+
def up
21+
create_table :blog_posts do |t|
22+
t.string :title, limit: 15
23+
t.string :subtitle
24+
end
25+
add_index :blog_posts, :title, unique: true, where: "([blog_posts].[title] IS NOT NULL)", name: "custom_index_name"
26+
add_index :blog_posts, [:title, :subtitle], unique: true
27+
end
28+
29+
def down
30+
drop_table :blog_posts
31+
end
32+
end
33+
34+
class ChangeClientsNameLength < ActiveRecord::Migration[8.0]
35+
def up
36+
change_column :clients, :name, :string, limit: 30
37+
end
38+
end
39+
40+
class ChangeBlogPostsTitleLength < ActiveRecord::Migration[8.0]
41+
def up
42+
change_column :blog_posts, :title, :string, limit: 30
43+
end
44+
end
45+
46+
before do
47+
@old_verbose = ActiveRecord::Migration.verbose
48+
ActiveRecord::Migration.verbose = false
49+
50+
CreateClientsWithUniqueIndex.new.up
51+
CreateBlogPostsWithMultipleIndexesOnTheSameColumn.new.up
52+
end
53+
54+
after do
55+
CreateClientsWithUniqueIndex.new.down
56+
CreateBlogPostsWithMultipleIndexesOnTheSameColumn.new.down
57+
58+
ActiveRecord::Migration.verbose = @old_verbose
59+
end
60+
61+
def test_index_uniqueness_is_maintained_after_column_change
62+
indexes = ActiveRecord::Base.connection.indexes("clients")
63+
columns = ActiveRecord::Base.connection.columns("clients")
64+
assert_equal columns.find { |column| column.name == "name" }.limit, 15
65+
assert_equal indexes.size, 1
66+
assert_equal indexes.first.name, "index_clients_on_name"
67+
assert indexes.first.unique
68+
69+
ChangeClientsNameLength.new.up
70+
71+
indexes = ActiveRecord::Base.connection.indexes("clients")
72+
columns = ActiveRecord::Base.connection.columns("clients")
73+
assert_equal columns.find { |column| column.name == "name" }.limit, 30
74+
assert_equal indexes.size, 1
75+
assert_equal indexes.first.name, "index_clients_on_name"
76+
assert indexes.first.unique
77+
end
78+
79+
def test_multiple_index_options_are_maintained_after_column_change
80+
indexes = ActiveRecord::Base.connection.indexes("blog_posts")
81+
columns = ActiveRecord::Base.connection.columns("blog_posts")
82+
assert_equal columns.find { |column| column.name == "title" }.limit, 15
83+
assert_equal indexes.size, 2
84+
85+
index_1 = indexes.find { |index| index.columns == ["title"] }
86+
assert_equal index_1.name, "custom_index_name"
87+
assert_equal index_1.where, "([blog_posts].[title] IS NOT NULL)"
88+
assert index_1.unique
89+
90+
index_2 = indexes.find { |index| index.columns == ["title", "subtitle"] }
91+
assert index_2.unique
92+
93+
ChangeBlogPostsTitleLength.new.up
94+
95+
indexes = ActiveRecord::Base.connection.indexes("blog_posts")
96+
columns = ActiveRecord::Base.connection.columns("blog_posts")
97+
assert_equal columns.find { |column| column.name == "title" }.limit, 30
98+
assert_equal indexes.size, 2
99+
100+
index_1 = indexes.find { |index| index.columns == ["title"] }
101+
assert_equal index_1.name, "custom_index_name"
102+
assert_equal index_1.where, "([blog_posts].[title] IS NOT NULL)"
103+
assert index_1.unique
104+
105+
index_2 = indexes.find { |index| index.columns == ["title", "subtitle"] }
106+
assert index_2.unique
107+
end
108+
end

0 commit comments

Comments
 (0)