Allow precision option for MySQL datetimes.
This commit is contained in:
parent
b63382ec06
commit
ae419af666
@ -1,3 +1,7 @@
|
||||
* Allow precision option for MySQL datetimes.
|
||||
|
||||
*Ryuta Kamizono*
|
||||
|
||||
* Fix `reaping_frequency` option when the value is a string.
|
||||
|
||||
This usually happens when it is configured using `DATABASE_URL`.
|
||||
|
@ -591,6 +591,13 @@ def type_to_sql(type, limit = nil, precision = nil, scale = nil)
|
||||
when 0x1000000..0xffffffff; 'longtext'
|
||||
else raise(ActiveRecordError, "No text type has character length #{limit}")
|
||||
end
|
||||
when 'datetime'
|
||||
return super unless precision
|
||||
|
||||
case precision
|
||||
when 0..6; "datetime(#{precision})"
|
||||
else raise(ActiveRecordError, "No datetime type has precision of #{precision}. The allowed range of precision is from 0 to 6")
|
||||
end
|
||||
else
|
||||
super
|
||||
end
|
||||
@ -679,6 +686,11 @@ def initialize_type_map(m) # :nodoc:
|
||||
m.alias_type %r(year)i, 'integer'
|
||||
m.alias_type %r(bit)i, 'binary'
|
||||
|
||||
m.register_type(%r(datetime)i) do |sql_type|
|
||||
precision = extract_precision(sql_type)
|
||||
Type::DateTime.new(precision: precision)
|
||||
end
|
||||
|
||||
m.register_type(%r(enum)i) do |sql_type|
|
||||
limit = sql_type[/^enum\((.+)\)/i, 1]
|
||||
.split(',').map{|enum| enum.strip.length - 2}.max
|
||||
|
70
activerecord/test/cases/adapters/mysql/datetime_test.rb
Normal file
70
activerecord/test/cases/adapters/mysql/datetime_test.rb
Normal file
@ -0,0 +1,70 @@
|
||||
require 'cases/helper'
|
||||
|
||||
if mysql_56?
|
||||
class DateTimeTest < ActiveRecord::TestCase
|
||||
|
||||
def test_default_datetime_precision
|
||||
ActiveRecord::Base.connection.create_table(:foos, force: true)
|
||||
ActiveRecord::Base.connection.add_column :foos, :created_at, :datetime
|
||||
ActiveRecord::Base.connection.add_column :foos, :updated_at, :datetime
|
||||
assert_nil activerecord_column_option('foos', 'created_at', 'precision')
|
||||
end
|
||||
|
||||
def test_datetime_data_type_with_precision
|
||||
ActiveRecord::Base.connection.create_table(:foos, force: true)
|
||||
ActiveRecord::Base.connection.add_column :foos, :created_at, :datetime, precision: 1
|
||||
ActiveRecord::Base.connection.add_column :foos, :updated_at, :datetime, precision: 5
|
||||
assert_equal 1, activerecord_column_option('foos', 'created_at', 'precision')
|
||||
assert_equal 5, activerecord_column_option('foos', 'updated_at', 'precision')
|
||||
end
|
||||
|
||||
def test_timestamps_helper_with_custom_precision
|
||||
ActiveRecord::Base.connection.create_table(:foos, force: true) do |t|
|
||||
t.timestamps null: true, precision: 4
|
||||
end
|
||||
assert_equal 4, activerecord_column_option('foos', 'created_at', 'precision')
|
||||
assert_equal 4, activerecord_column_option('foos', 'updated_at', 'precision')
|
||||
end
|
||||
|
||||
def test_passing_precision_to_datetime_does_not_set_limit
|
||||
ActiveRecord::Base.connection.create_table(:foos, force: true) do |t|
|
||||
t.timestamps null: true, precision: 4
|
||||
end
|
||||
assert_nil activerecord_column_option('foos', 'created_at', 'limit')
|
||||
assert_nil activerecord_column_option('foos', 'updated_at', 'limit')
|
||||
end
|
||||
|
||||
def test_invalid_datetime_precision_raises_error
|
||||
assert_raises ActiveRecord::ActiveRecordError do
|
||||
ActiveRecord::Base.connection.create_table(:foos, force: true) do |t|
|
||||
t.timestamps null: true, precision: 7
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_mysql_agrees_with_activerecord_about_precision
|
||||
ActiveRecord::Base.connection.create_table(:foos, force: true) do |t|
|
||||
t.timestamps null: true, precision: 4
|
||||
end
|
||||
assert_equal 4, mysql_datetime_precision('foos', 'created_at')
|
||||
assert_equal 4, mysql_datetime_precision('foos', 'updated_at')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def mysql_datetime_precision(table_name, column_name)
|
||||
results = ActiveRecord::Base.connection.exec_query("SELECT column_name, datetime_precision FROM information_schema.columns WHERE table_name ='#{table_name}'")
|
||||
result = results.find do |result_hash|
|
||||
result_hash["column_name"] == column_name
|
||||
end
|
||||
result && result["datetime_precision"]
|
||||
end
|
||||
|
||||
def activerecord_column_option(tablename, column_name, option)
|
||||
result = ActiveRecord::Base.connection.columns(tablename).find do |column|
|
||||
column.name == column_name
|
||||
end
|
||||
result && result.send(option)
|
||||
end
|
||||
end
|
||||
end
|
70
activerecord/test/cases/adapters/mysql2/datetime_test.rb
Normal file
70
activerecord/test/cases/adapters/mysql2/datetime_test.rb
Normal file
@ -0,0 +1,70 @@
|
||||
require 'cases/helper'
|
||||
|
||||
if mysql_56?
|
||||
class DateTimeTest < ActiveRecord::TestCase
|
||||
|
||||
def test_default_datetime_precision
|
||||
ActiveRecord::Base.connection.create_table(:foos, force: true)
|
||||
ActiveRecord::Base.connection.add_column :foos, :created_at, :datetime
|
||||
ActiveRecord::Base.connection.add_column :foos, :updated_at, :datetime
|
||||
assert_nil activerecord_column_option('foos', 'created_at', 'precision')
|
||||
end
|
||||
|
||||
def test_datetime_data_type_with_precision
|
||||
ActiveRecord::Base.connection.create_table(:foos, force: true)
|
||||
ActiveRecord::Base.connection.add_column :foos, :created_at, :datetime, precision: 1
|
||||
ActiveRecord::Base.connection.add_column :foos, :updated_at, :datetime, precision: 5
|
||||
assert_equal 1, activerecord_column_option('foos', 'created_at', 'precision')
|
||||
assert_equal 5, activerecord_column_option('foos', 'updated_at', 'precision')
|
||||
end
|
||||
|
||||
def test_timestamps_helper_with_custom_precision
|
||||
ActiveRecord::Base.connection.create_table(:foos, force: true) do |t|
|
||||
t.timestamps null: true, precision: 4
|
||||
end
|
||||
assert_equal 4, activerecord_column_option('foos', 'created_at', 'precision')
|
||||
assert_equal 4, activerecord_column_option('foos', 'updated_at', 'precision')
|
||||
end
|
||||
|
||||
def test_passing_precision_to_datetime_does_not_set_limit
|
||||
ActiveRecord::Base.connection.create_table(:foos, force: true) do |t|
|
||||
t.timestamps null: true, precision: 4
|
||||
end
|
||||
assert_nil activerecord_column_option('foos', 'created_at', 'limit')
|
||||
assert_nil activerecord_column_option('foos', 'updated_at', 'limit')
|
||||
end
|
||||
|
||||
def test_invalid_datetime_precision_raises_error
|
||||
assert_raises ActiveRecord::ActiveRecordError do
|
||||
ActiveRecord::Base.connection.create_table(:foos, force: true) do |t|
|
||||
t.timestamps null: true, precision: 7
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_mysql_agrees_with_activerecord_about_precision
|
||||
ActiveRecord::Base.connection.create_table(:foos, force: true) do |t|
|
||||
t.timestamps null: true, precision: 4
|
||||
end
|
||||
assert_equal 4, mysql_datetime_precision('foos', 'created_at')
|
||||
assert_equal 4, mysql_datetime_precision('foos', 'updated_at')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def mysql_datetime_precision(table_name, column_name)
|
||||
results = ActiveRecord::Base.connection.exec_query("SELECT column_name, datetime_precision FROM information_schema.columns WHERE table_name ='#{table_name}'")
|
||||
result = results.find do |result_hash|
|
||||
result_hash["column_name"] == column_name
|
||||
end
|
||||
result && result["datetime_precision"]
|
||||
end
|
||||
|
||||
def activerecord_column_option(tablename, column_name, option)
|
||||
result = ActiveRecord::Base.connection.columns(tablename).find do |column|
|
||||
column.name == column_name
|
||||
end
|
||||
result && result.send(option)
|
||||
end
|
||||
end
|
||||
end
|
@ -232,6 +232,13 @@ def test_schema_dumps_index_type
|
||||
end
|
||||
end
|
||||
|
||||
if mysql_56?
|
||||
def test_schema_dump_includes_datetime_precision
|
||||
output = standard_dump
|
||||
assert_match %r{t.datetime\s+"written_on",\s+precision: 6$}, output
|
||||
end
|
||||
end
|
||||
|
||||
def test_schema_dump_includes_decimal_options
|
||||
output = dump_all_table_schema([/^[^n]/])
|
||||
assert_match %r{precision: 3,[[:space:]]+scale: 2,[[:space:]]+default: 2.78}, output
|
||||
|
@ -726,7 +726,7 @@ def except(adapter_names_to_exclude)
|
||||
t.string :author_name
|
||||
t.string :author_email_address
|
||||
if mysql_56?
|
||||
t.datetime :written_on, limit: 6
|
||||
t.datetime :written_on, precision: 6
|
||||
else
|
||||
t.datetime :written_on
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user