Skip to content

Commit 859681e

Browse files
committed
Separate primary key column options from table options
Otherwise we cannot handle the same name options for both column and table (e.g. `:comment`, `:charset`, `:collation`).
1 parent 3c6be5e commit 859681e

File tree

6 files changed

+23
-13
lines changed

6 files changed

+23
-13
lines changed

activerecord/lib/active_record/connection_adapters/abstract/schema_dumper.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ def column_spec(column)
1313
end
1414

1515
def column_spec_for_primary_key(column)
16-
return {} if default_primary_key?(column)
17-
spec = { id: schema_type(column).inspect }
18-
spec.merge!(prepare_column_options(column).except!(:null, :comment))
16+
spec = {}
17+
spec[:id] = schema_type(column).inspect unless default_primary_key?(column)
18+
spec.merge!(prepare_column_options(column).except!(:null))
1919
spec[:default] ||= "nil" if explicit_primary_key_default?(column)
2020
spec
2121
end

activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,11 @@ def create_table(table_name, id: :primary_key, primary_key: nil, force: nil, **o
300300
if id && !td.as
301301
pk = primary_key || Base.get_primary_key(table_name.to_s.singularize)
302302

303+
if id.is_a?(Hash)
304+
options.merge!(id.except(:type))
305+
id = id.fetch(:type, :primary_key)
306+
end
307+
303308
if pk.is_a?(Array)
304309
td.primary_keys pk
305310
else

activerecord/lib/active_record/schema_dumper.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,10 @@ def table(table, stream)
125125
tbl.print ", primary_key: #{pk.inspect}" unless pk == "id"
126126
pkcol = columns.detect { |c| c.name == pk }
127127
pkcolspec = column_spec_for_primary_key(pkcol)
128-
if pkcolspec.present?
128+
unless pkcolspec.empty?
129+
if pkcolspec != pkcolspec.slice(:id, :default)
130+
pkcolspec = { id: { type: pkcolspec.delete(:id), **pkcolspec }.compact }
131+
end
129132
tbl.print ", #{format_colspec(pkcolspec)}"
130133
end
131134
when Array
@@ -240,7 +243,9 @@ def foreign_keys(table, stream)
240243
end
241244

242245
def format_colspec(colspec)
243-
colspec.map { |key, value| "#{key}: #{value}" }.join(", ")
246+
colspec.map do |key, value|
247+
"#{key}: #{ value.is_a?(Hash) ? "{ #{format_colspec(value)} }" : value }"
248+
end.join(", ")
244249
end
245250

246251
def format_options(options)

activerecord/test/cases/adapters/mysql2/charset_collation_test.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class Mysql2CharsetCollationTest < ActiveRecord::Mysql2TestCase
99

1010
setup do
1111
@connection = ActiveRecord::Base.connection
12-
@connection.create_table :charset_collations, force: true do |t|
12+
@connection.create_table :charset_collations, id: { type: :string, collation: "utf8mb4_bin" }, force: true do |t|
1313
t.string :string_ascii_bin, charset: "ascii", collation: "ascii_bin"
1414
t.text :text_ucs2_unicode_ci, charset: "ucs2", collation: "ucs2_unicode_ci"
1515
end
@@ -50,6 +50,7 @@ class Mysql2CharsetCollationTest < ActiveRecord::Mysql2TestCase
5050

5151
test "schema dump includes collation" do
5252
output = dump_table_schema("charset_collations")
53+
assert_match %r/create_table "charset_collations", id: { type: :string, collation: "utf8mb4_bin" }/, output
5354
assert_match %r{t\.string\s+"string_ascii_bin",\s+collation: "ascii_bin"$}, output
5455
assert_match %r{t\.text\s+"text_ucs2_unicode_ci",\s+collation: "ucs2_unicode_ci"$}, output
5556
end

activerecord/test/cases/comment_test.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class PkCommented < ActiveRecord::Base
3939
end
4040

4141
@connection.create_table("pk_commenteds", comment: "Table comment", id: false, force: true) do |t|
42-
t.integer :id, comment: "Primary key comment", primary_key: true
42+
t.primary_key :id, comment: "Primary key comment"
4343
end
4444

4545
Commented.reset_column_information
@@ -197,8 +197,7 @@ def test_comment_on_primary_key
197197

198198
def test_schema_dump_with_primary_key_comment
199199
output = dump_table_schema "pk_commenteds"
200-
assert_match %r[create_table "pk_commenteds",.*\s+comment: "Table comment"], output
201-
assert_no_match %r[create_table "pk_commenteds",.*\s+comment: "Primary key comment"], output
200+
assert_match %r[create_table "pk_commenteds", id: { comment: "Primary key comment" }.*, comment: "Table comment"], output
202201
end
203202
end
204203
end

activerecord/test/cases/primary_keys_test.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -312,15 +312,15 @@ def test_any_type_primary_key
312312

313313
test "schema dump primary key includes type and options" do
314314
schema = dump_table_schema "barcodes"
315-
assert_match %r{create_table "barcodes", primary_key: "code", id: :string, limit: 42}, schema
315+
assert_match %r/create_table "barcodes", primary_key: "code", id: { type: :string, limit: 42 }/, schema
316316
assert_no_match %r{t\.index \["code"\]}, schema
317317
end
318318

319319
if current_adapter?(:Mysql2Adapter) && supports_datetime_with_precision?
320320
test "schema typed primary key column" do
321321
@connection.create_table(:scheduled_logs, id: :timestamp, precision: 6, force: true)
322322
schema = dump_table_schema("scheduled_logs")
323-
assert_match %r/create_table "scheduled_logs", id: :timestamp, precision: 6/, schema
323+
assert_match %r/create_table "scheduled_logs", id: { type: :timestamp, precision: 6.* }/, schema
324324
end
325325
end
326326
end
@@ -462,7 +462,7 @@ class Widget < ActiveRecord::Base
462462
assert_predicate column, :unsigned?
463463

464464
schema = dump_table_schema "widgets"
465-
assert_match %r{create_table "widgets", id: :integer, unsigned: true, }, schema
465+
assert_match %r/create_table "widgets", id: { type: :integer, unsigned: true }/, schema
466466
end
467467

468468
test "bigint primary key with unsigned" do
@@ -474,7 +474,7 @@ class Widget < ActiveRecord::Base
474474
assert_predicate column, :unsigned?
475475

476476
schema = dump_table_schema "widgets"
477-
assert_match %r{create_table "widgets", id: :bigint, unsigned: true, }, schema
477+
assert_match %r/create_table "widgets", id: { type: :bigint, unsigned: true }/, schema
478478
end
479479
end
480480
end

0 commit comments

Comments
 (0)