Skip to content

Commit

Permalink
a "fast" attempt to bring 4.2 compatibility to PG but seems it's not …
Browse files Browse the repository at this point in the history
…the right way

Postgres will be the trickiest to handle multiple AR support with 4.2 ... as always
  • Loading branch information
kares committed Nov 21, 2014
1 parent 9bc5b7a commit ff0a5b4
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 0 deletions.
3 changes: 3 additions & 0 deletions lib/arjdbc/jdbc/adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -930,5 +930,8 @@ def _string_to_timestamp(value)
end

end
module Jdbc
autoload :TypeCast, 'arjdbc/jdbc/type_cast'
end
end
end
140 changes: 140 additions & 0 deletions lib/arjdbc/jdbc/type_cast.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
module ActiveRecord::ConnectionAdapters
module Jdbc
# Type casting methods taken from AR 4.1's Column class.
# @private Simply to quickly "hack-in" 4.2 compatibility.
module TypeCast

TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON'].to_set
FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off', 'OFF'].to_set

#module Format
ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/
ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
#end

# Used to convert from BLOBs to Strings
def binary_to_string(value)
value
end

def value_to_date(value)
if value.is_a?(String)
return nil if value.empty?
fast_string_to_date(value) || fallback_string_to_date(value)
elsif value.respond_to?(:to_date)
value.to_date
else
value
end
end

def string_to_time(string)
return string unless string.is_a?(String)
return nil if string.empty?

fast_string_to_time(string) || fallback_string_to_time(string)
end

def string_to_dummy_time(string)
return string unless string.is_a?(String)
return nil if string.empty?

dummy_time_string = "2000-01-01 #{string}"

fast_string_to_time(dummy_time_string) || begin
time_hash = Date._parse(dummy_time_string)
return nil if time_hash[:hour].nil?
new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction))
end
end

# convert something to a boolean
def value_to_boolean(value)
if value.is_a?(String) && value.empty?
nil
else
TRUE_VALUES.include?(value)
end
end

# Used to convert values to integer.
# handle the case when an integer column is used to store boolean values
def value_to_integer(value)
case value
when TrueClass, FalseClass
value ? 1 : 0
else
value.to_i rescue nil
end
end

# convert something to a BigDecimal
def value_to_decimal(value)
# Using .class is faster than .is_a? and
# subclasses of BigDecimal will be handled
# in the else clause
if value.class == BigDecimal
value
elsif value.respond_to?(:to_d)
value.to_d
else
value.to_s.to_d
end
end

protected
# '0.123456' -> 123456
# '1.123456' -> 123456
def microseconds(time)
time[:sec_fraction] ? (time[:sec_fraction] * 1_000_000).to_i : 0
end

def new_date(year, mon, mday)
if year && year != 0
Date.new(year, mon, mday) rescue nil
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 =~ ISO_DATE
new_date $1.to_i, $2.to_i, $3.to_i
end
end

# Doesn't handle time zones.
def fast_string_to_time(string)
if string =~ ISO_DATETIME
microsec = ($7.to_r * 1_000_000).to_i
new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, microsec
end
end

def fallback_string_to_date(string)
new_date(*::Date._parse(string, false).values_at(:year, :mon, :mday))
end

def fallback_string_to_time(string)
time_hash = Date._parse(string)
time_hash[:sec_fraction] = microseconds(time_hash)

new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset))
end

end
end
end
1 change: 1 addition & 0 deletions lib/arjdbc/postgresql/column.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class << base
include ActiveRecord::ConnectionAdapters::PostgreSQL::ArrayParser
end if AR4_COMPAT

include ActiveRecord::ConnectionAdapters::Jdbc::TypeCast if AR42_COMPAT
include Cast

end
Expand Down

0 comments on commit ff0a5b4

Please sign in to comment.