Skip to content

Commit 57a9e25

Browse files
skipkayhilrafaelfranca
authored andcommitted
Fix change_column not setting precision for sqlite
There were a few 6.1 migration compatibility fixes in [previous][1] [commits][2]. Most importantly, those commits reorganized some of the compatibility tests to ensure that the tests would run against every Migration version. To continue the effort of improving test coverage for Migration compatibility, this commit converts tests for create_table and change_column setting the correct precision on datetime columns. While the create_table tests all pass, the change_column test did not pass for 7.0 versioned Migrations on sqlite. This was due to the sqlite adapter not using new_column_definition to set the options on the new column (new_column_definition is where precision: 6 gets set if no precision is specified). This happens because columns can't be modified in place in sqlite and instead the whole table must be recreated and the data copied. Before this commit, change_column would use the options of the existing column as a base and merge in the exact options (and type) passed to change_column. This commit changes the change_column method to replace the existing column without using the existing options. This ensures that precision: 6 is set consistently across adapters when change_column is used to create a datetime column. [1]: c2f838e [2]: 9b07b2d
1 parent d3981d1 commit 57a9e25

File tree

4 files changed

+90
-42
lines changed

4 files changed

+90
-42
lines changed

activerecord/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
* Fix `change_column` not setting `precision: 6` on `datetime` columns when
2+
using 7.0+ Migrations and SQLite.
3+
4+
*Hartley McGuire*
5+
16
* Support composite identifiers in `to_key`
27

38
`to_key` avoids wrapping `#id` value into an `Array` if `#id` already an array

activerecord/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ module ConnectionAdapters
55
module SQLite3
66
# = Active Record SQLite3 Adapter \Table Definition
77
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
8+
def change_column(column_name, type, **options)
9+
name = column_name.to_s
10+
@columns_hash[name] = nil
11+
column(name, type, **options)
12+
end
13+
814
def references(*args, **options)
915
super(*args, type: :integer, **options)
1016
end

activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -328,10 +328,7 @@ def change_column_null(table_name, column_name, null, default = nil) # :nodoc:
328328

329329
def change_column(table_name, column_name, type, **options) # :nodoc:
330330
alter_table(table_name) do |definition|
331-
definition[column_name].instance_eval do
332-
self.type = aliased_types(type.to_s, type)
333-
self.options.merge!(options)
334-
end
331+
definition.change_column(column_name, type, **options)
335332
end
336333
end
337334

activerecord/test/cases/migration/compatibility_test.rb

Lines changed: 78 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -336,22 +336,6 @@ def migrate(x)
336336
connection.drop_table :more_testings rescue nil
337337
end
338338

339-
def test_datetime_doesnt_set_precision_on_create_table
340-
migration = Class.new(ActiveRecord::Migration[6.1]) {
341-
def migrate(x)
342-
create_table :more_testings do |t|
343-
t.datetime :published_at
344-
end
345-
end
346-
}.new
347-
348-
ActiveRecord::Migrator.new(:up, [migration], @schema_migration, @internal_metadata).migrate
349-
350-
assert connection.column_exists?(:more_testings, :published_at, **precision_implicit_default)
351-
ensure
352-
connection.drop_table :more_testings rescue nil
353-
end
354-
355339
def test_datetime_doesnt_set_precision_on_add_column_5_0
356340
migration = Class.new(ActiveRecord::Migration[5.0]) {
357341
def migrate(x)
@@ -376,28 +360,6 @@ def migrate(x)
376360
assert connection.column_exists?(:testings, :published_at, **precision_implicit_default)
377361
end
378362

379-
def test_datetime_doesnt_set_precision_on_change_column_6_1
380-
create_migration = Class.new(ActiveRecord::Migration[6.1]) {
381-
def migrate(x)
382-
create_table :more_testings do |t|
383-
t.date :published_at
384-
end
385-
end
386-
}.new(nil, 0)
387-
388-
change_migration = Class.new(ActiveRecord::Migration[6.1]) {
389-
def migrate(x)
390-
change_column :more_testings, :published_at, :datetime
391-
end
392-
}.new(nil, 1)
393-
394-
ActiveRecord::Migrator.new(:up, [create_migration, change_migration], @schema_migration, @internal_metadata).migrate
395-
396-
assert connection.column_exists?(:more_testings, :published_at, **precision_implicit_default)
397-
ensure
398-
connection.drop_table :more_testings rescue nil
399-
end
400-
401363
def test_change_table_allows_if_exists_option_on_7_0
402364
migration = Class.new(ActiveRecord::Migration[7.0]) {
403365
def migrate(x)
@@ -723,6 +685,44 @@ def migrate(x)
723685
connection.drop_table :more_testings rescue nil
724686
end
725687

688+
def test_datetime_doesnt_set_precision_on_create_table
689+
migration = Class.new(migration_class) {
690+
def migrate(x)
691+
create_table :more_testings do |t|
692+
t.datetime :published_at
693+
end
694+
end
695+
}.new
696+
697+
ActiveRecord::Migrator.new(:up, [migration], @schema_migration, @internal_metadata).migrate
698+
699+
assert connection.column_exists?(:more_testings, :published_at, **precision_implicit_default)
700+
ensure
701+
connection.drop_table :more_testings rescue nil
702+
end
703+
704+
def test_datetime_doesnt_set_precision_on_change_column
705+
create_migration = Class.new(migration_class) {
706+
def migrate(x)
707+
create_table :more_testings do |t|
708+
t.date :published_at
709+
end
710+
end
711+
}.new(nil, 0)
712+
713+
change_migration = Class.new(migration_class) {
714+
def migrate(x)
715+
change_column :more_testings, :published_at, :datetime
716+
end
717+
}.new(nil, 1)
718+
719+
ActiveRecord::Migrator.new(:up, [create_migration, change_migration], @schema_migration, @internal_metadata).migrate
720+
721+
assert connection.column_exists?(:more_testings, :published_at, **precision_implicit_default)
722+
ensure
723+
connection.drop_table :more_testings rescue nil
724+
end
725+
726726
private
727727
def precision_implicit_default
728728
if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)
@@ -757,6 +757,46 @@ def migrate(x)
757757
ensure
758758
connection.drop_table :more_testings rescue nil
759759
end
760+
761+
def test_datetime_sets_precision_6_on_create_table
762+
migration = Class.new(migration_class) {
763+
def migrate(x)
764+
create_table :more_testings do |t|
765+
t.datetime :published_at
766+
end
767+
end
768+
}.new
769+
770+
ActiveRecord::Migrator.new(:up, [migration], @schema_migration, @internal_metadata).migrate
771+
772+
assert connection.column_exists?(:more_testings, :published_at, precision: 6)
773+
ensure
774+
connection.drop_table :more_testings rescue nil
775+
end
776+
777+
def test_datetime_sets_precision_6_on_change_column
778+
create_migration = Class.new(migration_class) {
779+
def migrate(x)
780+
create_table :more_testings do |t|
781+
t.date :published_at
782+
end
783+
end
784+
}.new(nil, 0)
785+
786+
$global = true
787+
788+
change_migration = Class.new(migration_class) {
789+
def migrate(x)
790+
change_column :more_testings, :published_at, :datetime
791+
end
792+
}.new(nil, 1)
793+
794+
ActiveRecord::Migrator.new(:up, [create_migration, change_migration], @schema_migration, @internal_metadata).migrate
795+
796+
assert connection.column_exists?(:more_testings, :published_at, precision: 6)
797+
ensure
798+
connection.drop_table :more_testings rescue nil
799+
end
760800
end
761801

762802
class BaseCompatibilityTest < ActiveRecord::TestCase

0 commit comments

Comments
 (0)