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