From 3efbd7fadeb3545b3b5c3df77236f4868064eabb Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 3 Feb 2012 11:11:19 -0800 Subject: taking column width in to account when fetching decimal fields --- .../connection_adapters/postgresql/oid.rb | 41 +++++++++++++++++++++- .../connection_adapters/postgresql_adapter.rb | 3 +- 2 files changed, 42 insertions(+), 2 deletions(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb index bb2a5c0122..cf254eae8f 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb @@ -116,13 +116,52 @@ module ActiveRecord end end - TYPE_MAP = {} # :nodoc: + class Decimal + def type_cast(value) + return if value.nil? + + ConnectionAdapters::Column.value_to_decimal value + end + end + + class TypeMap + def initialize + @mapping = {} + end + + def []=(oid, type) + @mapping[oid] = type + end + + def [](oid) + @mapping[oid] + end + + def fetch(ftype, fmod) + # The type for the numeric depends on the width of the field, + # so we'll do something special here. + # + # When dealing with decimal columns: + # + # places after decimal = fmod - 4 & 0xffff + # places before decimal = (fmod - 4) >> 16 & 0xffff + if ftype == 1700 && (fmod - 4 & 0xffff).zero? + ftype = 23 + end + + @mapping.fetch(ftype) { |oid| yield oid, fmod } + end + end + + TYPE_MAP = TypeMap.new # :nodoc: TYPE_MAP[23] = OID::Integer.new # int4 TYPE_MAP[20] = TYPE_MAP[23] # int8 TYPE_MAP[21] = TYPE_MAP[23] # int2 TYPE_MAP[26] = TYPE_MAP[23] # oid + TYPE_MAP[1700] = OID::Decimal.new # decimal + TYPE_MAP[25] = OID::Identity.new # text TYPE_MAP[19] = TYPE_MAP[25] # name TYPE_MAP[1043] = TYPE_MAP[25] # varchar diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 170a3ada8a..a0010ac7b7 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -712,7 +712,8 @@ module ActiveRecord types = {} result.fields.each_with_index do |fname, i| ftype = result.ftype i - types[fname] = OID::TYPE_MAP.fetch(ftype) { |oid| + fmod = result.fmod i + types[fname] = OID::TYPE_MAP.fetch(ftype, fmod) { |oid, mod| warn "unknown OID: #{fname}(#{oid}) (#{sql})" OID::Identity.new } -- cgit v1.2.3