提交 4157f5d1 编写于 作者: R Ryuta Kamizono

Format the datetime string according to the precision of the datetime field.

Incompatible to rounding behavior between MySQL 5.6 and earlier.

In 5.5, when you insert `2014-08-17 12:30:00.999999` the fractional part
is ignored. In 5.6, it's rounded to `2014-08-17 12:30:01`:

http://bugs.mysql.com/bug.php?id=68760
上级 ae419af6
* Format the datetime string according to the precision of the datetime field.
Incompatible to rounding behavior between MySQL 5.6 and earlier.
In 5.5, when you insert `2014-08-17 12:30:00.999999` the fractional part
is ignored. In 5.6, it's rounded to `2014-08-17 12:30:01`:
http://bugs.mysql.com/bug.php?id=68760
*Ryuta Kamizono*
* Allow precision option for MySQL datetimes.
*Ryuta Kamizono*
......
......@@ -688,7 +688,7 @@ def initialize_type_map(m) # :nodoc:
m.register_type(%r(datetime)i) do |sql_type|
precision = extract_precision(sql_type)
Type::DateTime.new(precision: precision)
MysqlDateTime.new(precision: precision)
end
m.register_type(%r(enum)i) do |sql_type|
......@@ -884,6 +884,22 @@ def create_table_definition(name, temporary, options, as = nil) # :nodoc:
TableDefinition.new(native_database_types, name, temporary, options, as)
end
class MysqlDateTime < Type::DateTime # :nodoc:
def type_cast_for_database(value)
if value.acts_like?(:time) && value.respond_to?(:usec)
result = super.to_s(:db)
case precision
when 1..6
"#{result}.#{sprintf("%0#{precision}d", value.usec / 10**(6 - precision))}"
else
result
end
else
super
end
end
end
class MysqlString < Type::String # :nodoc:
def type_cast_for_database(value)
case value
......
......@@ -2,6 +2,9 @@
if mysql_56?
class DateTimeTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
class Foo < ActiveRecord::Base; end
def test_default_datetime_precision
ActiveRecord::Base.connection.create_table(:foos, force: true)
......@@ -50,6 +53,20 @@ def test_mysql_agrees_with_activerecord_about_precision
assert_equal 4, mysql_datetime_precision('foos', 'updated_at')
end
def test_formatting_datetime_according_to_precision
ActiveRecord::Base.connection.create_table(:foos, force: true) do |t|
t.datetime :created_at, precision: 0
t.datetime :updated_at, precision: 4
end
date = ::Time.utc(2014, 8, 17, 12, 30, 0, 999999)
Foo.create!(created_at: date, updated_at: date)
assert foo = Foo.find_by(created_at: date)
assert_equal date.to_s, foo.created_at.to_s
assert_equal date.to_s, foo.updated_at.to_s
assert_equal 000000, foo.created_at.usec
assert_equal 999900, foo.updated_at.usec
end
private
def mysql_datetime_precision(table_name, column_name)
......
......@@ -2,6 +2,9 @@
if mysql_56?
class DateTimeTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
class Foo < ActiveRecord::Base; end
def test_default_datetime_precision
ActiveRecord::Base.connection.create_table(:foos, force: true)
......@@ -50,6 +53,20 @@ def test_mysql_agrees_with_activerecord_about_precision
assert_equal 4, mysql_datetime_precision('foos', 'updated_at')
end
def test_formatting_datetime_according_to_precision
ActiveRecord::Base.connection.create_table(:foos, force: true) do |t|
t.datetime :created_at, precision: 0
t.datetime :updated_at, precision: 4
end
date = ::Time.utc(2014, 8, 17, 12, 30, 0, 999999)
Foo.create!(created_at: date, updated_at: date)
assert foo = Foo.find_by(created_at: date)
assert_equal date.to_s, foo.created_at.to_s
assert_equal date.to_s, foo.updated_at.to_s
assert_equal 000000, foo.created_at.usec
assert_equal 999900, foo.updated_at.usec
end
private
def mysql_datetime_precision(table_name, column_name)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册