aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2012-02-03 11:11:19 -0800
committerAaron Patterson <aaron.patterson@gmail.com>2012-02-07 14:13:46 -0800
commit3efbd7fadeb3545b3b5c3df77236f4868064eabb (patch)
treef8ceb457ff5377c49c1df47d083b7264050015d6 /activerecord
parent20440fd8700e1eb9725ffa0e85d458a81b519dd2 (diff)
downloadrails-3efbd7fadeb3545b3b5c3df77236f4868064eabb.tar.gz
rails-3efbd7fadeb3545b3b5c3df77236f4868064eabb.tar.bz2
rails-3efbd7fadeb3545b3b5c3df77236f4868064eabb.zip
taking column width in to account when fetching decimal fields
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid.rb41
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb3
2 files changed, 42 insertions, 2 deletions
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
}