-
Notifications
You must be signed in to change notification settings - Fork 386
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
a "fast" attempt to bring 4.2 compatibility to PG but seems it's not …
…the right way Postgres will be the trickiest to handle multiple AR support with 4.2 ... as always
- Loading branch information
Showing
3 changed files
with
144 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -930,5 +930,8 @@ def _string_to_timestamp(value) | |
end | ||
|
||
end | ||
module Jdbc | ||
autoload :TypeCast, 'arjdbc/jdbc/type_cast' | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters