aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
}