Skip to content

Commit

Permalink
Delegate type_cast to injected type object in mysql
Browse files Browse the repository at this point in the history
  • Loading branch information
sgrif committed May 20, 2014
1 parent d17b056 commit ac37165
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 53 deletions.
17 changes: 2 additions & 15 deletions activerecord/lib/active_record/connection_adapters/column.rb
Expand Up @@ -132,6 +132,8 @@ def extract_default(default)
end

class << self
include Type::TimeValue

# Used to convert from BLOBs to Strings
def binary_to_string(value)
value
Expand Down Expand Up @@ -215,21 +217,6 @@ def new_date(year, mon, mday)
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
Expand Down
78 changes: 40 additions & 38 deletions activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
Expand Up @@ -68,26 +68,12 @@ module ConnectionAdapters
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
Expand Down Expand Up @@ -329,27 +315,37 @@ def type_cast(value)
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

Expand Down Expand Up @@ -418,6 +414,12 @@ def self.find_type(field)
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. :'(
Expand Down
2 changes: 2 additions & 0 deletions 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'
Expand Down
Expand Up @@ -2,6 +2,8 @@ module ActiveRecord
module ConnectionAdapters
module Type
class DateTime < Value # :nodoc:
include TimeValue

def type
:datetime
end
Expand Down
Expand Up @@ -2,6 +2,8 @@ module ActiveRecord
module ConnectionAdapters
module Type
class Time < Value # :nodoc:
include TimeValue

def type
:time
end
Expand Down
@@ -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

0 comments on commit ac37165

Please sign in to comment.