From ac371655974aff8c7d09ab374fa2d3e9f1fa6f15 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Tue, 20 May 2014 07:51:33 -0700 Subject: Delegate type_cast to injected type object in mysql --- .../active_record/connection_adapters/column.rb | 17 +---- .../connection_adapters/mysql_adapter.rb | 78 +++++++++++----------- .../lib/active_record/connection_adapters/type.rb | 2 + .../connection_adapters/type/date_time.rb | 2 + .../active_record/connection_adapters/type/time.rb | 2 + .../connection_adapters/type/time_value.rb | 24 +++++++ 6 files changed, 72 insertions(+), 53 deletions(-) create mode 100644 activerecord/lib/active_record/connection_adapters/type/time_value.rb diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index 25a9cdafcf..11b2e728e1 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -132,6 +132,8 @@ module ActiveRecord end class << self + include Type::TimeValue + # Used to convert from BLOBs to Strings def binary_to_string(value) value @@ -215,21 +217,6 @@ module ActiveRecord end end - def new_time(year, mon, mday, hour, min, sec, microsec, offset = nil) - # Treat 0000-00-00 00:00:00 as nil. - return nil if year.nil? || (year == 0 && mon == 0 && mday == 0) - - if offset - time = Time.utc(year, mon, mday, hour, min, sec, microsec) rescue nil - return nil unless time - - time -= offset - Base.default_timezone == :utc ? time : time.getlocal - else - Time.public_send(Base.default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil - end - end - def fast_string_to_date(string) if string =~ Format::ISO_DATE new_date $1.to_i, $2.to_i, $3.to_i diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index bf09bfe217..fc27e1dd66 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -68,26 +68,12 @@ module ActiveRecord class MysqlAdapter < AbstractMysqlAdapter class Column < AbstractMysqlAdapter::Column #:nodoc: - def self.string_to_time(value) - return super unless Mysql::Time === value - new_time( - value.year, - value.month, - value.day, - value.hour, - value.minute, - value.second, - value.second_part) - end - - def self.string_to_dummy_time(v) - return super unless Mysql::Time === v - new_time(2000, 01, 01, v.hour, v.minute, v.second, v.second_part) - end - - def self.string_to_date(v) - return super unless Mysql::Time === v - new_date(v.year, v.month, v.day) + def type_cast(value) + if encoded? + super + else + cast_type.type_cast(value) + end end def adapter @@ -329,27 +315,37 @@ module ActiveRecord end end - class DateTime < Type - def type; :datetime; end - - def type_cast(value) - return if value.nil? - - # FIXME: probably we can improve this since we know it is mysql - # specific - ConnectionAdapters::Column.string_to_time value + class DateTime < ConnectionAdapters::Type::DateTime + def cast_value(value) + if Mysql::Time === value + new_time( + value.year, + value.month, + value.day, + value.hour, + value.minute, + value.second, + value.second_part) + else + super + end end end - class Time < Type - def type; :time; end - - def type_cast(value) - return if value.nil? - - # FIXME: probably we can improve this since we know it is mysql - # specific - ConnectionAdapters::Column.string_to_dummy_time value + class Time < ConnectionAdapters::Type::Time + def cast_value(value) + if Mysql::Time === value + new_time( + 2000, + 01, + 01, + value.hour, + value.minute, + value.second, + value.second_part) + else + super + end end end @@ -418,6 +414,12 @@ module ActiveRecord end end + def initialize_type_map(m) # :nodoc: + super + m.register_type %r(datetime)i, Fields::DateTime.new + m.register_type %r(time)i, Fields::Time.new + end + def exec_without_stmt(sql, name = 'SQL') # :nodoc: # Some queries, like SHOW CREATE TABLE don't work through the prepared # statement API. For those queries, we need to use this method. :'( diff --git a/activerecord/lib/active_record/connection_adapters/type.rb b/activerecord/lib/active_record/connection_adapters/type.rb index 0268e0d569..fbc4cd7e32 100644 --- a/activerecord/lib/active_record/connection_adapters/type.rb +++ b/activerecord/lib/active_record/connection_adapters/type.rb @@ -1,4 +1,6 @@ +require 'active_record/connection_adapters/type/time_value' require 'active_record/connection_adapters/type/value' + require 'active_record/connection_adapters/type/binary' require 'active_record/connection_adapters/type/boolean' require 'active_record/connection_adapters/type/date' diff --git a/activerecord/lib/active_record/connection_adapters/type/date_time.rb b/activerecord/lib/active_record/connection_adapters/type/date_time.rb index e1cc9cee4a..757553cd68 100644 --- a/activerecord/lib/active_record/connection_adapters/type/date_time.rb +++ b/activerecord/lib/active_record/connection_adapters/type/date_time.rb @@ -2,6 +2,8 @@ module ActiveRecord module ConnectionAdapters module Type class DateTime < Value # :nodoc: + include TimeValue + def type :datetime end diff --git a/activerecord/lib/active_record/connection_adapters/type/time.rb b/activerecord/lib/active_record/connection_adapters/type/time.rb index c5c9c44676..b621e8f39c 100644 --- a/activerecord/lib/active_record/connection_adapters/type/time.rb +++ b/activerecord/lib/active_record/connection_adapters/type/time.rb @@ -2,6 +2,8 @@ module ActiveRecord module ConnectionAdapters module Type class Time < Value # :nodoc: + include TimeValue + def type :time end diff --git a/activerecord/lib/active_record/connection_adapters/type/time_value.rb b/activerecord/lib/active_record/connection_adapters/type/time_value.rb new file mode 100644 index 0000000000..d9564d7f48 --- /dev/null +++ b/activerecord/lib/active_record/connection_adapters/type/time_value.rb @@ -0,0 +1,24 @@ +module ActiveRecord + module ConnectionAdapters + module Type + module TimeValue # :nodoc: + private + + def new_time(year, mon, mday, hour, min, sec, microsec, offset = nil) + # Treat 0000-00-00 00:00:00 as nil. + return if year.nil? || (year == 0 && mon == 0 && mday == 0) + + if offset + time = ::Time.utc(year, mon, mday, hour, min, sec, microsec) rescue nil + return unless time + + time -= offset + Base.default_timezone == :utc ? time : time.getlocal + else + ::Time.public_send(Base.default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil + end + end + end + end + end +end -- cgit v1.2.3