Skip to content

Ridgepole always changes datetime with precision: 6 (Rails 7+, MySQL) #406

@dmytro-savochkin

Description

@dmytro-savochkin

Description

I encountered a problem while migrating our app which uses ridgepole from Rails 6 to Rails 7.
I also found how to avoid this problem on user side so I am gonna post it here in case someone like me encounters it later.
I think this problem can be considered as a bug of ridgepole but since there is a way to avoid it it probably can be considered as pretty minor?

Suppose I have the following configuration in Rails 6 application:

# Gemfile
ruby "3.0.2"
gem "activerecord", "6.1.7"
gem "mysql2", "0.5.4"
gem "ridgepole", "1.2.0"

# schema
create_table :records do |t|
  t.datetime :created_at_6, precision: 6
  t.datetime :created_at_3, precision: 3
  t.datetime :created_at_0
end

If I execute it with ridgepole it creates the following MySQL table:

-- Server version	8.0.23
CREATE TABLE `records` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `created_at_6` datetime(6) DEFAULT NULL,
  `created_at_3` datetime(3) DEFAULT NULL,
  `created_at_0` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
)

Now I want to migrate my application to Rails 7 so I change the configuration to the following (I specified precision: nil for created_at_0 according to this):

# Gemfile
ruby "3.0.2"
gem "activerecord", "7.0.4.2"
gem "mysql2", "0.5.4"
gem "ridgepole", "1.2.0"

# schema
create_table :records do |t|
  t.datetime :created_at_6, precision: 6
  t.datetime :created_at_3, precision: 3
  t.datetime :created_at_0, precision: nil
end

Now I run bundle exec ridgepole -a --verbose and this is what I get in return:

Apply `db/schemas/records.schema`
# Parse DSL
# Load tables
#   records
# Compare definitions
#   records
 {:definition=>
   {"created_at_0"=>{:options=>{:precision=>nil}, :type=>:datetime},
    "created_at_3"=>{:options=>{:precision=>3}, :type=>:datetime},
-   "created_at_6"=>{:options=>{}, :type=>:datetime}},
- :options=>{:charset=>"utf8", :collation=>"utf8_unicode_ci"}}
+   "created_at_6"=>{:options=>{:precision=>6}, :type=>:datetime}},
+ :options=>{}}

...

# Update schema
-- change_column("records", "created_at_6", :datetime, {:precision=>6, :null=>true, :default=>nil, :unsigned=>false, :comment=>nil})
   -> 0.0096s

And it tries to update column created_at_6 every time I run this command to precision: 6 even though it's already precision: 6.

If I do an export here is what I get:

create_table "records", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t|
  t.datetime "created_at_6"
  t.datetime "created_at_3", precision: 3
  t.datetime "created_at_0", precision: nil
end

This happens because now Rails dumper removes precision: 6 from the result it gets from the database because it considers it unnecessary (it's precision: 6 by default since Rails 7). So the only way to get rid of this unnecessary change for me is to change the schema according to the above removing precision: 6.

So, this can be avoided but I think at the very least this requires a comment in the Readme. Or, maybe ideally, a fix? After all, I wanted to keep precision: 6 specified in the schema explicitly for better readability so that the readers of the schema would not need to remember the differences in behaviour between Rails 6 and Rails 7. But I understand it might be too much effort to fix.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions