Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix migration compatibility for default precision value on datetime columns #42606

Merged
merged 3 commits into from Jun 26, 2021

Conversation

robertomiranda
Copy link
Contributor

@robertomiranda robertomiranda commented Jun 25, 2021

Background

I have made a mistake on #42297, the definitions for add_column and column were put under the wrong class

class V4_2 < V5_0
module TableDefinition
def references(*, **options)
options[:index] ||= false
super
end
alias :belongs_to :references
def timestamps(**options)
options[:null] = true if options[:null].nil?
super
end
def column(name, type, index: nil, **options)
options[:precision] ||= nil
super
end
end
def add_reference(table_name, ref_name, **options)
options[:index] ||= false
super
end
alias :add_belongs_to :add_reference
def add_timestamps(table_name, **options)
options[:null] = true if options[:null].nil?
super
end
def index_exists?(table_name, column_name, **options)
column_names = Array(column_name).map(&:to_s)
options[:name] =
if options[:name].present?
options[:name].to_s
else
connection.index_name(table_name, column: column_names)
end
super
end
def remove_index(table_name, column_name = nil, **options)
options[:name] = index_name_for_remove(table_name, column_name, options)
super
end
def add_column(table_name, column_name, type, **options)
if type == :datetime
options[:precision] ||= nil
end

As you can notice above they are in the V4_2 class when they should be in V6_1, in 9b9d9c7 I could verify this by changing the versions of the migrations from 4.2 to 6.1, please the errors here https://buildkite.com/rails/rails/builds/78711#d5c2b003-4552-4173-afc9-61e46d8b4fde

Solution

Move the definitions to v6_1 and tweak V5_0 to add support older than 5.0 365acb6

cc @guilleiguaran @zzak @ghiculescu

@robertomiranda robertomiranda changed the title Test default precision agains 6.1 Test default precision against 6.1 Jun 25, 2021
@robertomiranda robertomiranda changed the title Test default precision against 6.1 Fix migration compatibility for default precision value on datetime columns Jun 25, 2021
@robertomiranda robertomiranda marked this pull request as ready for review June 25, 2021 16:54
@guilleiguaran guilleiguaran merged commit de737ea into rails:main Jun 26, 2021
@robertomiranda robertomiranda deleted the r/test-compatibility branch June 26, 2021 06:00
@Tonkpils
Copy link
Contributor

👋 @robertomiranda @guilleiguaran this seems to have broken some migrations in our application when using create_table

class AddColumnWorks < ActiveRecord::Migration[4.2]
  def change
    add_column :my_table, :some_column, :datetime, default: -> { "NOW()" }, null: false
  end
end

works but

class AddColumnWorks < ActiveRecord::Migration[4.2]
  def change
    create_table :my_table do |t|
      t.datetime :some_column, default: -> { "NOW()" }, null: false
    end
  end
end

fails with Invalid default value for 'some_column'

@robertomiranda
Copy link
Contributor Author

robertomiranda commented Jun 28, 2021

@Tonkpils interesting, it would be good to add a test case, which RDMS are you using?

@Tonkpils
Copy link
Contributor

which RDMS are you using?

mysql

@ghiculescu
Copy link
Member

@Tonkpils is the issue specific to ActiveRecord::Migration[4.2] or does it happen on newer ones too?

@Tonkpils
Copy link
Contributor

Tonkpils commented Jun 28, 2021

is the issue specific to ActiveRecord::Migration[4.2] or does it happen on newer ones too?

The compatibility broke for ActiveRecord::Migration[4.2] up to 5.0. ActiveRecord::Migration[6.1] works.

@robertomiranda
Copy link
Contributor Author

robertomiranda commented Jun 28, 2021

Looks like they are broken from 4.2 to 6.0 I'm working on a fix here #42631

@Tonkpils
Copy link
Contributor

Looks like they are broken from 4.2 to 6.0 I'm working on a fix here #42606 (comment)

For added context and in case it helps @robertomiranda , looks like the query generated when on this PR looks like

t.datetime :mycolumn, default: -> { "NOW()" }
`mycolumn` datetime(6) DEFAULT NOW()

because the precision is added (not sure how), the NOW() default would require this same precision. I'm not sure if the same is true when using default: Time.now

@robertomiranda
Copy link
Contributor Author

because the precision is added (not sure how), the NOW() default would require this same precision. I'm not sure if the same is true when using default: Time.now

In theory the compatibility.rb should prevent the introduction of this behaviour to Rails version previous to 7.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants