Permalink
Browse files

Use the generic type map for all PG type registrations

We're going to want all of the benefits of the type map object for
registrations, including block registration and real aliasing. Moves
type name registrations to the adapter, and aliases the OIDs to the
named types
  • Loading branch information...
sgrif committed May 22, 2014
1 parent 110d3d0 commit 4826a4ab348e59c3ac1f6c31fd73f93eabb91a3b
@@ -27,73 +27,6 @@ module ActiveRecord
module ConnectionAdapters
module PostgreSQL
module OID # :nodoc:
- # When the PG adapter connects, the pg_type table is queried. The
- # key of this hash maps to the `typname` column from the table.
- # type_map is then dynamically built with oids as the key and type
- # objects as values.
- NAMES = Hash.new { |h,k| # :nodoc:
- h[k] = Type::Value.new
- }
-
- # Register an OID type named +name+ with a typecasting object in
- # +type+. +name+ should correspond to the `typname` column in
- # the `pg_type` table.
- def self.register_type(name, type)
- NAMES[name] = type
- end
-
- # Alias the +old+ type to the +new+ type.
- def self.alias_type(new, old)
- NAMES[new] = NAMES[old]
- end
-
- # Is +name+ a registered type?
- def self.registered_type?(name)
- NAMES.key? name
- end
-
- register_type 'int2', OID::Integer.new
- 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', Type::Text.new
- register_type 'varchar', Type::String.new
- alias_type 'char', 'varchar'
- alias_type 'name', 'varchar'
- alias_type 'bpchar', 'varchar'
- register_type 'bool', Type::Boolean.new
- register_type 'bit', OID::Bit.new
- alias_type 'varbit', 'bit'
- register_type 'timestamp', OID::DateTime.new
- alias_type 'timestamptz', 'timestamp'
- register_type 'date', OID::Date.new
- register_type 'time', OID::Time.new
-
- register_type 'money', OID::Money.new
- register_type 'bytea', OID::Bytea.new
- register_type 'point', OID::Point.new
- register_type 'hstore', OID::Hstore.new
- register_type 'json', OID::Json.new
- register_type 'cidr', OID::Cidr.new
- register_type 'inet', OID::Inet.new
- register_type 'uuid', OID::Uuid.new
- register_type 'xml', SpecializedString.new(:xml)
- register_type 'tsvector', SpecializedString.new(:tsvector)
- register_type 'macaddr', SpecializedString.new(:macaddr)
- 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
@@ -13,7 +13,8 @@ def initialize(store)
end
def run(records)
- mapped, nodes = records.partition { |row| OID.registered_type? row['typname'] }
+ nodes = records.reject { |row| @store.key? row['oid'].to_i }
+ mapped, nodes = nodes.partition { |row| @store.key? row['typname'] }
ranges, nodes = nodes.partition { |row| row['typtype'] == 'r' }
enums, nodes = nodes.partition { |row| row['typtype'] == 'e' }
domains, nodes = nodes.partition { |row| row['typtype'] == 'd' }
@@ -30,7 +31,7 @@ def run(records)
private
def register_mapped_type(row)
- register row['oid'], OID::NAMES[row['typname']]
+ alias_type row['oid'], row['typname']
end
def register_enum_type(row)
@@ -64,12 +65,18 @@ def register_composite_type(row)
end
def register(oid, oid_type)
- oid = oid.to_i
+ oid = assert_valid_registration(oid, oid_type)
+ @store.register_type(oid, oid_type)
+ end
- raise ArgumentError, "can't register nil type for OID #{oid}" if oid_type.nil?
- return if @store.key?(oid)
+ def alias_type(oid, target)
+ oid = assert_valid_registration(oid, target)
+ @store.alias_type(oid, target)
+ end
- @store.register_type(oid, oid_type)
+ def assert_valid_registration(oid, oid_type)
+ raise ArgumentError, "can't register nil type for OID #{oid}" if oid_type.nil?
+ oid.to_i
end
end
end
@@ -540,7 +540,7 @@ def translate_exception(exception, message)
def get_oid_type(oid, fmod, column_name)
if !type_map.key?(oid)
- initialize_type_map(type_map, [oid])
+ load_additional_types(type_map, [oid])
end
type_map.fetch(normalize_oid_type(oid, fmod)) {
@@ -566,7 +566,54 @@ def normalize_oid_type(ftype, fmod)
end
end
- def initialize_type_map(type_map, oids = nil)
+ def initialize_type_map(m)
+ m.register_type 'int2', OID::Integer.new
+ m.alias_type 'int4', 'int2'
+ m.alias_type 'int8', 'int2'
+ m.alias_type 'oid', 'int2'
+ m.register_type 'numeric', OID::Decimal.new
+ m.register_type 'float4', OID::Float.new
+ m.alias_type 'float8', 'float4'
+ m.register_type 'text', Type::Text.new
+ m.register_type 'varchar', Type::String.new
+ m.alias_type 'char', 'varchar'
+ m.alias_type 'name', 'varchar'
+ m.alias_type 'bpchar', 'varchar'
+ m.register_type 'bool', Type::Boolean.new
+ m.register_type 'bit', OID::Bit.new
+ m.alias_type 'varbit', 'bit'
+ m.register_type 'timestamp', OID::DateTime.new
+ m.alias_type 'timestamptz', 'timestamp'
+ m.register_type 'date', OID::Date.new
+ m.register_type 'time', OID::Time.new
+
+ m.register_type 'money', OID::Money.new
+ m.register_type 'bytea', OID::Bytea.new
+ m.register_type 'point', OID::Point.new
+ m.register_type 'hstore', OID::Hstore.new
+ m.register_type 'json', OID::Json.new
+ m.register_type 'cidr', OID::Cidr.new
+ m.register_type 'inet', OID::Inet.new
+ m.register_type 'uuid', OID::Uuid.new
+ m.register_type 'xml', OID::SpecializedString.new(:xml)
+ m.register_type 'tsvector', OID::SpecializedString.new(:tsvector)
+ m.register_type 'macaddr', OID::SpecializedString.new(:macaddr)
+ m.register_type 'citext', OID::SpecializedString.new(:citext)
+ m.register_type 'ltree', OID::SpecializedString.new(:ltree)
+
+ # FIXME: why are we keeping these types as strings?
+ m.alias_type 'interval', 'varchar'
+ m.alias_type 'path', 'varchar'
+ m.alias_type 'line', 'varchar'
+ m.alias_type 'polygon', 'varchar'
+ m.alias_type 'circle', 'varchar'
+ m.alias_type 'lseg', 'varchar'
+ m.alias_type 'box', 'varchar'
+
+ load_additional_types(m)
+ end
+
+ def load_additional_types(type_map, oids = nil)
if supports_ranges?
query = <<-SQL
SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
@@ -102,15 +102,7 @@ def type_cast_for_write(value)
def setup
super
- @registration = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID
- @registration.register_type "full_address", FullAddressType.new
- end
-
- def teardown
- super
-
- # there is currently no clean way to unregister a OID::Type
- @registration::NAMES.delete("full_address")
+ @connection.type_map.register_type "full_address", FullAddressType.new
end
def test_column

0 comments on commit 4826a4a

Please sign in to comment.