aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
authorRafael Mendonça França <rafaelmfranca@gmail.com>2014-04-01 09:56:06 -0500
committerRafael Mendonça França <rafaelmfranca@gmail.com>2014-04-01 09:56:06 -0500
commitfc0b98da0b83329474922a920a6070d370091228 (patch)
tree95e2accfedbc0109c921713ca2f19a5eee9d2be8 /activerecord/lib
parentf54dd28a34ad4204cb8af49fee2e20cb347bba16 (diff)
parent4d344bb4fdc0a57aff60c755dda0c5e3c6e08cdb (diff)
downloadrails-fc0b98da0b83329474922a920a6070d370091228.tar.gz
rails-fc0b98da0b83329474922a920a6070d370091228.tar.bz2
rails-fc0b98da0b83329474922a920a6070d370091228.zip
Merge pull request #14513 from senny/pg/responsible_oid
PostgreSQL determine `Column#type` through corresponding OID. #7814
Diffstat (limited to 'activerecord/lib')
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/column.rb65
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid.rb127
2 files changed, 91 insertions, 101 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb
index 823189934d..2cbcd5fd50 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb
@@ -151,70 +151,7 @@ module ActiveRecord
# Maps PostgreSQL-specific data types to logical Rails types.
def simplified_type(field_type)
- case field_type
- # Numeric and monetary types
- when /^(?:real|double precision)$/
- :float
- # Monetary types
- when 'money'
- :decimal
- when 'hstore'
- :hstore
- when 'ltree'
- :ltree
- # Network address types
- when 'inet'
- :inet
- when 'cidr'
- :cidr
- when 'macaddr'
- :macaddr
- # Character types
- when /^(?:character varying|bpchar)(?:\(\d+\))?$/
- :string
- when /^citext(?:\(\d+\))?$/
- :citext
- # Binary data types
- when 'bytea'
- :binary
- # Date/time types
- when /^timestamp with(?:out)? time zone$/
- :datetime
- when /^interval(?:|\(\d+\))$/
- :string
- # Geometric types
- when /^(?:point|line|lseg|box|"?path"?|polygon|circle)$/
- :string
- # Bit strings
- when /^bit(?: varying)?(?:\(\d+\))?$/
- :string
- # XML type
- when 'xml'
- :xml
- # tsvector type
- when 'tsvector'
- :tsvector
- # Arrays
- when /^\D+\[\]$/
- :string
- # Object identifier types
- when 'oid'
- :integer
- # UUID type
- when 'uuid'
- :uuid
- # JSON type
- when 'json'
- :json
- # Small and big integer types
- when /^(?:small|big)int$/
- :integer
- when /(num|date|tstz|ts|int4|int8)range$/
- field_type.to_sym
- # Pass through all types that are not specific to PostgreSQL.
- else
- super
- end
+ @oid_type.simplified_type(field_type) || super
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
index 5d32aaed50..57bdc3bb19 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
@@ -6,6 +6,7 @@ module ActiveRecord
module OID
class Type
def type; end
+ def simplified_type(sql_type); type end
def infinity(options = {})
::Float::INFINITY * (options[:negative] ? -1 : 1)
@@ -18,7 +19,9 @@ module ActiveRecord
end
end
- class Text < Type
+ class String < Type
+ def type; :string end
+
def type_cast(value)
return if value.nil?
@@ -26,9 +29,23 @@ module ActiveRecord
end
end
+ class SpecializedString < OID::String
+ def type; @type end
+
+ def initialize(type)
+ @type = type
+ end
+ end
+
+ class Text < OID::String
+ def type; :text end
+ end
+
class Bit < Type
+ def type; :string end
+
def type_cast(value)
- if String === value
+ if ::String === value
ConnectionAdapters::PostgreSQLColumn.string_to_bit value
else
value
@@ -37,6 +54,8 @@ module ActiveRecord
end
class Bytea < Type
+ def type; :binary end
+
def type_cast(value)
return if value.nil?
PGconn.unescape_bytea value
@@ -44,9 +63,11 @@ module ActiveRecord
end
class Money < Type
+ def type; :decimal end
+
def type_cast(value)
return if value.nil?
- return value unless String === value
+ return value unless ::String === value
# Because money output is formatted according to the locale, there are two
# cases to consider (note the decimal separators):
@@ -88,8 +109,10 @@ module ActiveRecord
end
class Point < Type
+ def type; :string end
+
def type_cast(value)
- if String === value
+ if ::String === value
ConnectionAdapters::PostgreSQLColumn.string_to_point value
else
value
@@ -98,13 +121,15 @@ module ActiveRecord
end
class Array < Type
+ def type; @subtype.type end
+
attr_reader :subtype
def initialize(subtype)
@subtype = subtype
end
def type_cast(value)
- if String === value
+ if ::String === value
ConnectionAdapters::PostgreSQLColumn.string_to_array value, @subtype
else
value
@@ -114,6 +139,8 @@ module ActiveRecord
class Range < Type
attr_reader :subtype
+ def simplified_type(sql_type); sql_type.to_sym end
+
def initialize(subtype)
@subtype = subtype
end
@@ -160,6 +187,8 @@ This is not reliable and will be removed in the future.
end
class Integer < Type
+ def type; :integer end
+
def type_cast(value)
return if value.nil?
@@ -168,6 +197,8 @@ This is not reliable and will be removed in the future.
end
class Boolean < Type
+ def type; :boolean end
+
def type_cast(value)
return if value.nil?
@@ -177,6 +208,14 @@ This is not reliable and will be removed in the future.
class Timestamp < Type
def type; :timestamp; end
+ def simplified_type(sql_type)
+ case sql_type
+ when /^timestamp with(?:out)? time zone$/
+ :datetime
+ else
+ :timestamp
+ end
+ end
def type_cast(value)
return if value.nil?
@@ -188,7 +227,7 @@ This is not reliable and will be removed in the future.
end
class Date < Type
- def type; :datetime; end
+ def type; :date; end
def type_cast(value)
return if value.nil?
@@ -200,6 +239,8 @@ This is not reliable and will be removed in the future.
end
class Time < Type
+ def type; :time end
+
def type_cast(value)
return if value.nil?
@@ -210,6 +251,8 @@ This is not reliable and will be removed in the future.
end
class Float < Type
+ def type; :float end
+
def type_cast(value)
return if value.nil?
@@ -218,6 +261,8 @@ This is not reliable and will be removed in the future.
end
class Decimal < Type
+ def type; :decimal end
+
def type_cast(value)
return if value.nil?
@@ -230,12 +275,16 @@ This is not reliable and will be removed in the future.
end
class Enum < Type
+ def type; :enum end
+
def type_cast(value)
value.to_s
end
end
class Hstore < Type
+ def type; :hstore end
+
def type_cast_for_write(value)
ConnectionAdapters::PostgreSQLColumn.hstore_to_string value
end
@@ -252,14 +301,20 @@ This is not reliable and will be removed in the future.
end
class Cidr < Type
+ def type; :cidr end
def type_cast(value)
return if value.nil?
ConnectionAdapters::PostgreSQLColumn.string_to_cidr value
end
end
+ class Inet < Cidr
+ def type; :inet end
+ end
class Json < Type
+ def type; :json end
+
def type_cast_for_write(value)
ConnectionAdapters::PostgreSQLColumn.json_to_string value
end
@@ -321,7 +376,7 @@ This is not reliable and will be removed in the future.
}
# Register an OID type named +name+ with a typecasting object in
- # +type+. +name+ should correspond to the `typname` column in
+ # +type+. +name+ should correspond to the `typname` column in
# the `pg_type` table.
def self.register_type(name, type)
NAMES[name] = type
@@ -338,48 +393,46 @@ This is not reliable and will be removed in the future.
end
register_type 'int2', OID::Integer.new
- alias_type 'int4', 'int2'
- alias_type 'int8', 'int2'
- alias_type 'oid', 'int2'
-
+ alias_type 'int4', 'int2'
+ alias_type 'int8', 'int2'
+ alias_type 'oid', 'int2'
register_type 'numeric', OID::Decimal.new
+ register_type 'float4', OID::Float.new
+ alias_type 'float8', 'float4'
register_type 'text', OID::Text.new
- alias_type 'varchar', 'text'
- alias_type 'char', 'text'
- alias_type 'bpchar', 'text'
- alias_type 'xml', 'text'
-
- # FIXME: why are we keeping these types as strings?
- alias_type 'tsvector', 'text'
- alias_type 'interval', 'text'
- alias_type 'macaddr', 'text'
- alias_type 'uuid', 'text'
-
- register_type 'money', OID::Money.new
- register_type 'bytea', OID::Bytea.new
+ register_type 'varchar', OID::String.new
+ alias_type 'char', 'varchar'
+ alias_type 'bpchar', 'varchar'
register_type 'bool', OID::Boolean.new
register_type 'bit', OID::Bit.new
- register_type 'varbit', OID::Bit.new
-
- register_type 'float4', OID::Float.new
- alias_type 'float8', 'float4'
-
+ alias_type 'varbit', 'bit'
register_type 'timestamp', OID::Timestamp.new
- register_type 'timestamptz', OID::Timestamp.new
+ alias_type 'timestamptz', 'timestamp'
register_type 'date', OID::Date.new
register_type 'time', OID::Time.new
- register_type 'path', OID::Text.new
+ register_type 'money', OID::Money.new
+ register_type 'bytea', OID::Bytea.new
register_type 'point', OID::Point.new
- register_type 'polygon', OID::Text.new
- register_type 'circle', OID::Text.new
register_type 'hstore', OID::Hstore.new
register_type 'json', OID::Json.new
- register_type 'citext', OID::Text.new
- register_type 'ltree', OID::Text.new
-
register_type 'cidr', OID::Cidr.new
- alias_type 'inet', 'cidr'
+ register_type 'inet', OID::Inet.new
+ register_type 'xml', SpecializedString.new(:xml)
+ register_type 'tsvector', SpecializedString.new(:tsvector)
+ register_type 'macaddr', SpecializedString.new(:macaddr)
+ register_type 'uuid', SpecializedString.new(:uuid)
+ register_type 'citext', SpecializedString.new(:citext)
+ register_type 'ltree', SpecializedString.new(:ltree)
+
+ # FIXME: why are we keeping these types as strings?
+ alias_type 'interval', 'varchar'
+ alias_type 'path', 'varchar'
+ alias_type 'line', 'varchar'
+ alias_type 'polygon', 'varchar'
+ alias_type 'circle', 'varchar'
+ alias_type 'lseg', 'varchar'
+ alias_type 'box', 'varchar'
end
end
end