aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/connection_adapters/postgresql
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters/postgresql')
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/cast.rb23
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid.rb11
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb10
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb8
4 files changed, 52 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb b/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb
index c04a799b8d..3772f7ddaa 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb
@@ -92,6 +92,29 @@ module ActiveRecord
parse_pg_array(string).map{|val| oid.type_cast val}
end
+ def string_to_intrange(string)
+ if string.nil?
+ nil
+ elsif "empty" == string
+ (nil..nil)
+ elsif String === string
+ matches = /^(\(|\[)([0-9]+),(\s?)([0-9]+)(\)|\])$/i.match(string)
+ lower_bound = ("(" == matches[1] ? (matches[2].to_i + 1) : matches[2].to_i)
+ upper_bound = (")" == matches[5] ? (matches[4].to_i - 1) : matches[4].to_i)
+ (lower_bound..upper_bound)
+ else
+ string
+ end
+ end
+
+ def intrange_to_string(object)
+ if Range === object
+ "[#{object.first},#{object.exclude_end? ? object.last : object.last.to_i + 1})"
+ else
+ object
+ end
+ end
+
private
HstorePair = begin
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
index 52344f61c0..18ea83ce42 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
@@ -168,6 +168,14 @@ module ActiveRecord
end
end
+ class IntRange < Type
+ def type_cast(value)
+ return if value.nil?
+
+ ConnectionAdapters::PostgreSQLColumn.string_to_intrange value
+ end
+ end
+
class TypeMap
def initialize
@mapping = {}
@@ -269,6 +277,9 @@ module ActiveRecord
register_type 'hstore', OID::Hstore.new
register_type 'json', OID::Json.new
+ register_type 'int4range', OID::IntRange.new
+ alias_type 'int8range', 'int4range'
+
register_type 'cidr', OID::Cidr.new
alias_type 'inet', 'cidr'
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
index 62a4d76928..c2fcef94da 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
@@ -31,6 +31,11 @@ module ActiveRecord
when 'json' then super(PostgreSQLColumn.json_to_string(value), column)
else super
end
+ when Range
+ case column.sql_type
+ when 'int4range', 'int8range' then super(PostgreSQLColumn.intrange_to_string(value), column)
+ else super
+ end
when IPAddr
case column.sql_type
when 'inet', 'cidr' then super(PostgreSQLColumn.cidr_to_string(value), column)
@@ -89,6 +94,11 @@ module ActiveRecord
when 'json' then PostgreSQLColumn.json_to_string(value)
else super(value, column)
end
+ when Range
+ case column.sql_type
+ when 'int4range', 'int8range' then PostgreSQLColumn.intrange_to_string(value)
+ else super(value, column)
+ end
when IPAddr
return super(value, column) unless ['inet','cidr'].include? column.sql_type
PostgreSQLColumn.cidr_to_string(value)
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
index 18bf14d1fb..e10b562fa4 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
@@ -417,6 +417,14 @@ module ActiveRecord
when 0..6; "timestamp(#{precision})"
else raise(ActiveRecordError, "No timestamp type has precision of #{precision}. The allowed range of precision is from 0 to 6")
end
+ when 'intrange'
+ return 'int4range' unless limit
+
+ case limit
+ when 1..4; 'int4range'
+ when 5..8; 'int8range'
+ else raise(ActiveRecordError, "No range type has byte size #{limit}. Use a numeric with precision 0 instead.")
+ end
else
super
end