mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Set precision 6 by default for datetime
💇♀️ Set precision 6 by detauls for datime columns when using sqlite3_adapter Set precision 6 by detauls for datime columns when using postgresql_adapter Update activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb Co-authored-by: Zachary Scott <zzakscott@gmail.com> Update tests precision Add datetime precision by using the migration compatibility layer Add default precision when adding new column for a table Fix compatibility tests Add changelog entry Update postgres test cases Custom type does not support precision Typo ⌨️ Fix specific mysql2 schema 💇♀️
This commit is contained in:
parent
9053b8f77f
commit
c2a6f618d2
11 changed files with 100 additions and 17 deletions
|
@ -1,3 +1,9 @@
|
|||
* Set precision 6 by default for `datetime` columns
|
||||
|
||||
By default, datetime columns will have microseconds precision instead of seconds precision.
|
||||
|
||||
*Roberto Miranda*
|
||||
|
||||
* Allow preloading of associations with instance dependent scopes
|
||||
|
||||
*John Hawthorn*, *John Crepezzi*, *Adam Hess*, *Eileen M. Uchitelle*, *Dinah Shi*
|
||||
|
|
|
@ -411,6 +411,12 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
if @conn.supports_datetime_with_precision?
|
||||
if type == :datetime && !options.key?(:precision)
|
||||
options[:precision] = 6
|
||||
end
|
||||
end
|
||||
|
||||
@columns_hash[name] = new_column_definition(name, type, **options)
|
||||
|
||||
if index
|
||||
|
|
|
@ -613,6 +613,12 @@ module ActiveRecord
|
|||
def add_column(table_name, column_name, type, **options)
|
||||
return if options[:if_not_exists] == true && column_exists?(table_name, column_name)
|
||||
|
||||
if supports_datetime_with_precision?
|
||||
if type == :datetime && !options.key?(:precision)
|
||||
options[:precision] = 6
|
||||
end
|
||||
end
|
||||
|
||||
at = create_alter_table table_name
|
||||
at.add_column(column_name, type, **options)
|
||||
execute schema_creation.accept at
|
||||
|
|
|
@ -295,6 +295,11 @@ module ActiveRecord
|
|||
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)
|
||||
|
@ -324,6 +329,14 @@ module ActiveRecord
|
|||
super
|
||||
end
|
||||
|
||||
def add_column(table_name, column_name, type, **options)
|
||||
if type == :datetime
|
||||
options[:precision] ||= nil
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
private
|
||||
def compatible_table_definition(t)
|
||||
class << t
|
||||
|
|
|
@ -125,7 +125,7 @@ class PostgresqlTimestampMigrationTest < ActiveRecord::PostgreSQLTestCase
|
|||
|
||||
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:datetimes_as_enum] = { name: "custom_time_format" }
|
||||
with_postgresql_datetime_type(:datetimes_as_enum) do
|
||||
ActiveRecord::Migration.new.add_column :postgresql_timestamp_with_zones, :times, :datetime
|
||||
ActiveRecord::Migration.new.add_column :postgresql_timestamp_with_zones, :times, :datetime, precision: nil
|
||||
|
||||
assert_equal({ "data_type" => "USER-DEFINED", "udt_name" => "custom_time_format" },
|
||||
PostgresqlTimestampWithZone.connection.execute("select data_type, udt_name from information_schema.columns where column_name = 'times'").to_a.first)
|
||||
|
|
|
@ -48,8 +48,8 @@ if supports_datetime_with_precision?
|
|||
unless current_adapter?(:Mysql2Adapter)
|
||||
def test_no_datetime_precision_isnt_truncated_on_assignment
|
||||
@connection.create_table(:foos, force: true)
|
||||
@connection.add_column :foos, :created_at, :datetime
|
||||
@connection.add_column :foos, :updated_at, :datetime, precision: 6
|
||||
@connection.add_column :foos, :created_at, :datetime, precision: nil
|
||||
@connection.add_column :foos, :updated_at, :datetime
|
||||
|
||||
time = ::Time.now.change(nsec: 123)
|
||||
foo = Foo.new(created_at: time, updated_at: time)
|
||||
|
|
|
@ -91,13 +91,13 @@ if current_adapter?(:PostgreSQLAdapter)
|
|||
output = dump_table_schema("defaults")
|
||||
if ActiveRecord::Base.connection.database_version >= 100000
|
||||
assert_match %r/t\.date\s+"modified_date",\s+default: -> { "CURRENT_DATE" }/, output
|
||||
assert_match %r/t\.datetime\s+"modified_time",\s+default: -> { "CURRENT_TIMESTAMP" }/, output
|
||||
assert_match %r/t\.datetime\s+"modified_time",\s+precision: 6,\s+default: -> { "CURRENT_TIMESTAMP" }/, output
|
||||
else
|
||||
assert_match %r/t\.date\s+"modified_date",\s+default: -> { "\('now'::text\)::date" }/, output
|
||||
assert_match %r/t\.datetime\s+"modified_time",\s+default: -> { "now\(\)" }/, output
|
||||
assert_match %r/t\.datetime\s+"modified_time",\s+precision: 6,\s+default: -> { "now\(\)" }/, output
|
||||
end
|
||||
assert_match %r/t\.date\s+"modified_date_function",\s+default: -> { "now\(\)" }/, output
|
||||
assert_match %r/t\.datetime\s+"modified_time_function",\s+default: -> { "now\(\)" }/, output
|
||||
assert_match %r/t\.datetime\s+"modified_time_function",\s+precision: 6,\s+default: -> { "now\(\)" }/, output
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -300,11 +300,11 @@ module ActiveRecord
|
|||
assert_equal :datetime, column.type
|
||||
|
||||
if current_adapter?(:PostgreSQLAdapter)
|
||||
assert_equal "timestamp without time zone", column.sql_type
|
||||
assert_equal "timestamp(6) without time zone", column.sql_type
|
||||
elsif current_adapter?(:Mysql2Adapter)
|
||||
assert_equal "datetime", column.sql_type
|
||||
assert_equal "datetime(6)", column.sql_type
|
||||
else
|
||||
assert_equal connection.type_to_sql("datetime"), column.sql_type
|
||||
assert_equal connection.type_to_sql("datetime(6)"), column.sql_type
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -318,7 +318,7 @@ module ActiveRecord
|
|||
column = connection.columns(:testings).find { |c| c.name == "foo" }
|
||||
|
||||
assert_equal :datetime, column.type
|
||||
assert_equal "timestamp with time zone", column.sql_type
|
||||
assert_equal "timestamp(6) with time zone", column.sql_type
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -341,7 +341,7 @@ module ActiveRecord
|
|||
elsif current_adapter?(:OracleAdapter)
|
||||
assert_equal "TIMESTAMP(6)", column.sql_type
|
||||
else
|
||||
assert_equal connection.type_to_sql("datetime"), column.sql_type
|
||||
assert_equal connection.type_to_sql("datetime(6)"), column.sql_type
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -335,6 +335,58 @@ module ActiveRecord
|
|||
assert connection.index_exists?(:testings, [:gizmo_type, :gizmo_id], name: :index_testings_on_gizmo_type_and_gizmo_id)
|
||||
end
|
||||
|
||||
def test_datetime_doesnt_set_precision_on_create_table
|
||||
migration = Class.new(ActiveRecord::Migration[4.2]) {
|
||||
def migrate(x)
|
||||
create_table :more_testings do |t|
|
||||
t.datetime :published_at
|
||||
end
|
||||
end
|
||||
}.new
|
||||
|
||||
ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate
|
||||
|
||||
assert connection.column_exists?(:more_testings, :published_at, **precision_implicit_default)
|
||||
ensure
|
||||
connection.drop_table :more_testings rescue nil
|
||||
end
|
||||
|
||||
def test_datetime_doesnt_set_precision_on_change_table
|
||||
create_migration = Class.new(ActiveRecord::Migration[4.2]) {
|
||||
def migrate(x)
|
||||
create_table :more_testings do |t|
|
||||
t.datetime :published_at
|
||||
end
|
||||
end
|
||||
}.new
|
||||
|
||||
change_migration = Class.new(ActiveRecord::Migration[4.2]) {
|
||||
def migrate(x)
|
||||
change_table :more_testings do |t|
|
||||
t.datetime :published_at, default: Time.now
|
||||
end
|
||||
end
|
||||
}.new
|
||||
|
||||
ActiveRecord::Migrator.new(:up, [create_migration, change_migration], @schema_migration).migrate
|
||||
|
||||
assert connection.column_exists?(:more_testings, :published_at, **precision_implicit_default)
|
||||
ensure
|
||||
connection.drop_table :more_testings rescue nil
|
||||
end
|
||||
|
||||
def test_datetime_doesnt_set_precision_on_add_column
|
||||
migration = Class.new(ActiveRecord::Migration[4.2]) {
|
||||
def migrate(x)
|
||||
add_column :testings, :published_at, :datetime, default: Time.now
|
||||
end
|
||||
}.new
|
||||
|
||||
ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate
|
||||
|
||||
assert connection.column_exists?(:testings, :published_at, **precision_implicit_default)
|
||||
end
|
||||
|
||||
private
|
||||
def precision_implicit_default
|
||||
if current_adapter?(:Mysql2Adapter)
|
||||
|
|
|
@ -837,7 +837,7 @@ class SchemaDumperDefaultsTest < ActiveRecord::TestCase
|
|||
|
||||
assert_match %r{t\.string\s+"string_with_default",.*?default: "Hello!"}, output
|
||||
assert_match %r{t\.date\s+"date_with_default",\s+default: "2014-06-05"}, output
|
||||
assert_match %r{t\.datetime\s+"datetime_with_default",\s+default: "2014-06-05 07:17:04"}, output
|
||||
assert_match %r{t\.datetime\s+"datetime_with_default",\s+precision: 6,\s+default: "2014-06-05 07:17:04"}, output
|
||||
assert_match %r{t\.time\s+"time_with_default",\s+default: "2000-01-01 07:17:04"}, output
|
||||
assert_match %r{t\.decimal\s+"decimal_with_default",\s+precision: 20,\s+scale: 10,\s+default: "1234567890.0123456789"}, output
|
||||
end
|
||||
|
@ -847,8 +847,8 @@ class SchemaDumperDefaultsTest < ActiveRecord::TestCase
|
|||
output = dump_table_schema("infinity_defaults")
|
||||
assert_match %r{t\.float\s+"float_with_inf_default",\s+default: ::Float::INFINITY}, output
|
||||
assert_match %r{t\.float\s+"float_with_nan_default",\s+default: ::Float::NAN}, output
|
||||
assert_match %r{t\.datetime\s+"beginning_of_time",\s+default: -::Float::INFINITY}, output
|
||||
assert_match %r{t\.datetime\s+"end_of_time",\s+default: ::Float::INFINITY}, output
|
||||
assert_match %r{t\.datetime\s+"beginning_of_time",\s+precision: 6,\s+default: -::Float::INFINITY}, output
|
||||
assert_match %r{t\.datetime\s+"end_of_time",\s+precision: 6,\s+default: ::Float::INFINITY}, output
|
||||
assert_match %r{t\.date\s+"date_with_neg_inf_default",\s+default: -::Float::INFINITY}, output
|
||||
assert_match %r{t\.date\s+"date_with_pos_inf_default",\s+default: ::Float::INFINITY}, output
|
||||
end
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
ActiveRecord::Schema.define do
|
||||
if supports_datetime_with_precision?
|
||||
create_table :datetime_defaults, force: true do |t|
|
||||
t.datetime :modified_datetime, default: -> { "CURRENT_TIMESTAMP" }
|
||||
t.datetime :precise_datetime, precision: 6, default: -> { "CURRENT_TIMESTAMP(6)" }
|
||||
t.datetime :modified_datetime, precision: nil, default: -> { "CURRENT_TIMESTAMP" }
|
||||
t.datetime :precise_datetime, default: -> { "CURRENT_TIMESTAMP(6)" }
|
||||
end
|
||||
|
||||
create_table :timestamp_defaults, force: true do |t|
|
||||
t.timestamp :nullable_timestamp
|
||||
t.timestamp :modified_timestamp, default: -> { "CURRENT_TIMESTAMP" }
|
||||
t.timestamp :modified_timestamp, precision: nil, default: -> { "CURRENT_TIMESTAMP" }
|
||||
t.timestamp :precise_timestamp, precision: 6, default: -> { "CURRENT_TIMESTAMP(6)" }
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue