Work around bug in migrations to non-null columns

When running migration 20170705075039 followed by 20170715131706, the
latter fails due to lingering null values in a newly non-null column—

    Mysql2::Error: Invalid use of NULL value: ALTER TABLE `tracks` CHANGE `state` `state` varchar(255) DEFAULT 'new' NOT NULL
    db/migrate/20170715131706_make_track_state_not_null_and_add_default_value.rb:17:in `change'

—despite having apparently converted any existing null values prior to
changing the column type. Investigation reveals that actually the
attempted conversion has had no effect, and that this can be resolved by
clearing ActiveRecord internal caches between migrations:

    connection.schema_cache.clear_data_source_cache! 'tracks'

The same problem also affects running 20170705075039 followed by
20170720134353, but in that case it leads to silent data corruption as
`change_column_null` automatically converts any lingering null values.

This commit 1) clears ActiveRecord internal caches at the beginning of
each affected migration, and 2) replaces `change_column_null` with
`change_column` to reflect that no automatic conversion is intended.
This commit is contained in:
Andrew Kvalheim 2020-05-11 21:55:36 -07:00 committed by Henne Vogelsang
parent 2051540693
commit fdd7806071
No known key found for this signature in database
GPG key ID: 9D6164C2955FADE0
2 changed files with 5 additions and 1 deletions

View file

@ -6,6 +6,8 @@ class MakeTrackStateNotNullAndAddDefaultValue < ActiveRecord::Migration
end
def change
TmpTrack.reset_column_information
TmpTrack.where(state: nil).each do |track|
track.state = 'confirmed'
track.save!

View file

@ -6,11 +6,13 @@ class MakeTrackCfpActiveNotNull < ActiveRecord::Migration
end
def change
TmpTrack.reset_column_information
TmpTrack.where(cfp_active: nil).each do |track|
track.cfp_active = true
track.save!
end
change_column_null :tracks, :cfp_active, false
change_column :tracks, :cfp_active, :boolean, null: false, default: false
end
end