diff options
author | Aaron Patterson <aaron.patterson@gmail.com> | 2012-05-16 16:29:43 -0700 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2012-05-16 16:29:43 -0700 |
commit | 835df6f3ed9b1575fd6a1fb62516d8ebeffbf114 (patch) | |
tree | 4d14825b67a32157efa18d4d8cbe27c342eb4df6 /activerecord/lib | |
parent | 66cbde016c5c457f25c45a71ef8839608ef77299 (diff) | |
parent | 0e1c6513a442737ab9ff757efec24a10cd2f947a (diff) | |
download | rails-835df6f3ed9b1575fd6a1fb62516d8ebeffbf114.tar.gz rails-835df6f3ed9b1575fd6a1fb62516d8ebeffbf114.tar.bz2 rails-835df6f3ed9b1575fd6a1fb62516d8ebeffbf114.zip |
Merge pull request #6192 from danmcclain/add_inet_and_cidr_types_to_postgresql_adapter
Add support for macaddr, inet, and cidr types to PostgreSQL adapter
Diffstat (limited to 'activerecord/lib')
3 files changed, 65 insertions, 7 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index 1933ce2b46..01bd3ae26c 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -124,6 +124,7 @@ module ActiveRecord when :binary then "#{klass}.binary_to_string(#{var_name})" when :boolean then "#{klass}.value_to_boolean(#{var_name})" when :hstore then "#{klass}.string_to_hstore(#{var_name})" + when :inet, :cidr then "#{klass}.string_to_cidr(#{var_name})" else var_name 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 c82afc232c..df3d5e4657 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb @@ -137,6 +137,14 @@ module ActiveRecord end end + class Cidr < Type + def type_cast(value) + return if value.nil? + + ConnectionAdapters::PostgreSQLColumn.string_to_cidr value + end + end + class TypeMap def initialize @mapping = {} @@ -212,11 +220,9 @@ module ActiveRecord # FIXME: why are we keeping these types as strings? alias_type 'tsvector', 'text' alias_type 'interval', 'text' - alias_type 'cidr', 'text' - alias_type 'inet', 'text' - alias_type 'macaddr', 'text' alias_type 'bit', 'text' alias_type 'varbit', 'text' + alias_type 'macaddr', 'text' # FIXME: I don't think this is correct. We should probably be returning a parsed date, # but the tests pass with a string returned. @@ -237,6 +243,9 @@ module ActiveRecord register_type 'polygon', OID::Identity.new register_type 'circle', OID::Identity.new register_type 'hstore', OID::Hstore.new + + register_type 'cidr', OID::Cidr.new + alias_type 'inet', 'cidr' 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 4d5459939b..6714970103 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -8,6 +8,8 @@ require 'arel/visitors/bind_visitor' gem 'pg', '~> 0.11' require 'pg' +require 'ipaddr' + module ActiveRecord module ConnectionHandling # Establishes a connection to the database that's used by all Active Record objects @@ -79,6 +81,25 @@ module ActiveRecord end end + def string_to_cidr(string) + if string.nil? + nil + elsif String === string + IPAddr.new(string) + else + string + end + + end + + def cidr_to_string(object) + if IPAddr === object + "#{object.to_s}/#{object.instance_variable_get(:@mask_addr).to_s(2).count('1')}" + else + object + end + end + private HstorePair = begin quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/ @@ -197,6 +218,13 @@ module ActiveRecord :decimal when 'hstore' :hstore + # Network address types + when 'inet' + :inet + when 'cidr' + :cidr + when 'macaddr' + :macaddr # Character types when /^(?:character varying|bpchar)(?:\(\d+\))?$/ :string @@ -211,9 +239,6 @@ module ActiveRecord # Geometric types when /^(?:point|line|lseg|box|"?path"?|polygon|circle)$/ :string - # Network address types - when /^(?:cidr|inet|macaddr)$/ - :string # Bit strings when /^bit(?: varying)?(?:\(\d+\))?$/ :string @@ -282,6 +307,18 @@ module ActiveRecord def hstore(name, options = {}) column(name, 'hstore', options) end + + def inet(name, options = {}) + column(name, 'inet', options) + end + + def cidr(name, options = {}) + column(name, 'cidr', options) + end + + def macaddr(name, options = {}) + column(name, 'macaddr', options) + end end ADAPTER_NAME = 'PostgreSQL' @@ -301,7 +338,10 @@ module ActiveRecord :boolean => { :name => "boolean" }, :xml => { :name => "xml" }, :tsvector => { :name => "tsvector" }, - :hstore => { :name => "hstore" } + :hstore => { :name => "hstore" }, + :inet => { :name => "inet" }, + :cidr => { :name => "cidr" }, + :macaddr => { :name => "macaddr" } } # Returns 'PostgreSQL' as adapter name for identification purposes. @@ -510,6 +550,11 @@ module ActiveRecord when 'hstore' then super(PostgreSQLColumn.hstore_to_string(value), column) else super end + when IPAddr + case column.sql_type + when 'inet', 'cidr' then super(PostgreSQLColumn.cidr_to_string(value), column) + else super + end when Float if value.infinite? && column.type == :datetime "'#{value.to_s.downcase}'" @@ -549,6 +594,9 @@ module ActiveRecord when Hash return super unless 'hstore' == column.sql_type PostgreSQLColumn.hstore_to_string(value) + when IPAddr + return super unless ['inet','cidr'].includes? column.sql_type + PostgreSQLColumn.cidr_to_string(value) else super end |