Skip to content

Invalid datetime(precision nil and zero) Column DB schema dump in Rails 7.0 #43934

@tmimura39

Description

@tmimura39

Steps to reproduce

prepare mysql db

# frozen_string_literal: true

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  gem "activerecord", "~> 7.0.0"
  gem "mysql2"
end

require "active_record"
require "minitest/autorun"
require "logger"

ActiveRecord::Base.establish_connection(adapter: "mysql2", username: "root", database: "test")
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :posts, force: true do |t|
    t.datetime :precision_nil, precision: nil
    t.datetime :precision_zero, precision: 0
    t.datetime :precision_six, precision: 6
    t.datetime :precision_none
    t.timestamps
  end
end

class BugTest < Minitest::Test
  def test_schema_dump
   expected_schema = <<~STR
     # This file is auto-generated from the current state of the database. Instead
     # of editing this file, please use the migrations feature of Active Record to
     # incrementally modify your database, and then regenerate this schema definition.
     #
     # This file is the source Rails uses to define your schema when running `bin/rails
     # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
     # be faster and is potentially less error prone than running all of your
     # migrations from scratch. Old migrations may fail to apply correctly if those
     # migrations use external dependencies or application code.
     #
     # It's strongly recommended that you check this file into your version control system.

     ActiveRecord::Schema.define(version: 0) do

       create_table "posts", charset: "utf8mb4", force: :cascade do |t|
         t.datetime "precision_nil", precision: nil
         t.datetime "precision_zero", precision: 0
         t.datetime "precision_six", precision: 6
         t.datetime "precision_none", precision: 6
         t.datetime "created_at", precision: 6, null: false
         t.datetime "updated_at", precision: 6, null: false
       end

     end
   STR

   filename = "schema.rb"
   File.open(filename, "w") do |file|
     ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
   end

   ActiveRecord::Base.connection.truncate_tables(*ActiveRecord::Base.connection.tables)
   load(filename)

   assert_equal expected_schema, File.read(filename)
  end
end
-- create_table(:posts, {:force=>true})
D, [2021-12-19T07:17:50.303686 #22447] DEBUG -- :    (7.3ms)  DROP TABLE IF EXISTS `posts`
D, [2021-12-19T07:17:50.319572 #22447] DEBUG -- :    (15.5ms)  CREATE TABLE `posts` (`id` bigint NOT NULL AUTO_INCREMENT PRIMARY KEY, `precision_nil` datetime, `precision_zero` datetime(0), `precision_six` datetime(6), `precision_none` datetime(6), `created_at` datetime(6) NOT NULL, `updated_at` datetime(6) NOT NULL)
   -> 0.0407s
D, [2021-12-19T07:17:50.429670 #22447] DEBUG -- :   ActiveRecord::InternalMetadata Load (0.3ms)  SELECT `ar_internal_metadata`.* FROM `ar_internal_metadata` WHERE `ar_internal_metadata`.`key` = 'environment' LIMIT 1
Run options: --seed 25344

# Running:

D, [2021-12-19T07:17:50.450122 #22447] DEBUG -- :   ActiveRecord::SchemaMigration Pluck (0.2ms)  SELECT `schema_migrations`.`version` FROM `schema_migrations` ORDER BY `schema_migrations`.`version` ASC
D, [2021-12-19T07:17:50.454876 #22447] DEBUG -- :    (0.1ms)  SELECT @@FOREIGN_KEY_CHECKS
D, [2021-12-19T07:17:50.455104 #22447] DEBUG -- :    (0.1ms)  SET FOREIGN_KEY_CHECKS = 0
D, [2021-12-19T07:17:50.466658 #22447] DEBUG -- :   Truncate Tables (11.2ms)  TRUNCATE TABLE `posts`
D, [2021-12-19T07:17:50.466915 #22447] DEBUG -- :    (0.1ms)  SET FOREIGN_KEY_CHECKS = 1
-- create_table("posts", {:charset=>"utf8mb4", :force=>:cascade})
D, [2021-12-19T07:17:50.474021 #22447] DEBUG -- :    (5.2ms)  DROP TABLE IF EXISTS `posts` CASCADE
D, [2021-12-19T07:17:50.486943 #22447] DEBUG -- :    (12.0ms)  CREATE TABLE `posts` (`id` bigint NOT NULL AUTO_INCREMENT PRIMARY KEY, `precision_nil` datetime(6), `precision_zero` datetime(6), `precision_six` datetime(6), `precision_none` datetime(6), `created_at` datetime(6) NOT NULL, `updated_at` datetime(6) NOT NULL) DEFAULT CHARSET=utf8mb4
   -> 0.0190s
D, [2021-12-19T07:17:50.489694 #22447] DEBUG -- :   ActiveRecord::SchemaMigration Pluck (0.2ms)  SELECT `schema_migrations`.`version` FROM `schema_migrations` ORDER BY `schema_migrations`.`version` ASC
D, [2021-12-19T07:17:50.491513 #22447] DEBUG -- :   ActiveRecord::InternalMetadata Load (0.3ms)  SELECT `ar_internal_metadata`.* FROM `ar_internal_metadata` WHERE `ar_internal_metadata`.`key` = 'environment' LIMIT 1
F

Finished in 0.053775s, 18.5962 runs/s, 18.5962 assertions/s.

  1) Failure:
BugTest#test_schema_dump [mysql_precision_dump.rb:69]:
--- expected
+++ actual
@@ -14,7 +14,7 @@

   create_table \"posts\", charset: \"utf8mb4\", force: :cascade do |t|
-    t.datetime \"precision_nil\", precision: nil
-    t.datetime \"precision_zero\", precision: 0
+    t.datetime \"precision_nil\"
+    t.datetime \"precision_zero\"
     t.datetime \"precision_six\", precision: 6
     t.datetime \"precision_none\", precision: 6
     t.datetime \"created_at\", precision: 6, null: false


1 runs, 1 assertions, 1 failures, 0 errors, 0 skips

This is a different event than the #43909, but I think the cause is similar.
Confirmed only with mysql.
Other adapers are unconfirmed.

Expected behavior

precision: nil and precision: 0 is dumped. ?

There should be no difference in schema before and after db:schema:dump db:schema:load.

Actual behavior

precision: nil and precision: 0 is not dumped.

The precision of the precision_nil and precision_zero has gone from 0 to 6.

System configuration

Rails version: v7.0.0

Ruby version: v3.0.3

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions