diff options
author | Sean Griffin <sean@thoughtbot.com> | 2014-05-22 09:39:16 -0700 |
---|---|---|
committer | Sean Griffin <sean@thoughtbot.com> | 2014-05-22 09:43:30 -0700 |
commit | 4826a4ab348e59c3ac1f6c31fd73f93eabb91a3b (patch) | |
tree | 053d88e831c9b6c95fecc29a32bd5f21c7b3b488 /activerecord | |
parent | 110d3d0c0bceddd05cab86c0463f0aa71df815cb (diff) | |
download | rails-4826a4ab348e59c3ac1f6c31fd73f93eabb91a3b.tar.gz rails-4826a4ab348e59c3ac1f6c31fd73f93eabb91a3b.tar.bz2 rails-4826a4ab348e59c3ac1f6c31fd73f93eabb91a3b.zip |
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
Diffstat (limited to 'activerecord')
4 files changed, 63 insertions, 84 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb index e54c092bf6..2494e19f84 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb @@ -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 diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb index 27829ae1a3..28f7a4eafb 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb @@ -13,7 +13,8 @@ module ActiveRecord 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 @@ module ActiveRecord 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 @@ module ActiveRecord 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 diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index ed3e884455..29288d93a3 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -540,7 +540,7 @@ module ActiveRecord 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 @@ module ActiveRecord 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 diff --git a/activerecord/test/cases/adapters/postgresql/composite_test.rb b/activerecord/test/cases/adapters/postgresql/composite_test.rb index f01717d1a7..1f55cce352 100644 --- a/activerecord/test/cases/adapters/postgresql/composite_test.rb +++ b/activerecord/test/cases/adapters/postgresql/composite_test.rb @@ -102,15 +102,7 @@ class PostgresqlCompositeWithCustomOIDTest < ActiveRecord::TestCase 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 |