pg_range.rb

lib/sequel/extensions/pg_range.rb
Last Update: 2017-01-19 10:04:33 -0800

The pg_range extension adds support for the PostgreSQL 9.2+ range types to Sequel. PostgreSQL range types are similar to ruby's Range class, representating an array of values. However, they are more flexible than ruby's ranges, allowing exclusive beginnings and endings (ruby's range only allows exclusive endings), and unbounded beginnings and endings (which ruby's range does not support).

This extension integrates with Sequel's native postgres and jdbc/postgresql adapters, so that when range type values are retrieved, they are parsed and returned as instances of Sequel::Postgres::PGRange. PGRange mostly acts like a Range, but it's not a Range as not all PostgreSQL range type values would be valid ruby ranges. If the range type value you are using is a valid ruby range, you can call PGRange#to_range to get a Range. However, if you call PGRange#to_range on a range type value uses features that ruby's Range does not support, an exception will be raised.

In addition to the parser, this extension comes with literalizers for both PGRange and Range that use the standard Sequel literalization callbacks, so they work on all adapters.

To turn an existing Range into a PGRange, use Sequel.pg_range:

Sequel.pg_range(range)

If you have loaded the core_extensions extension, or you have loaded the core_refinements extension and have activated refinements for the file, you can also use Range#pg_range:

range.pg_range

You may want to specify a specific range type:

Sequel.pg_range(range, :daterange)
range.pg_range(:daterange)

If you specify the range database type, Sequel will automatically cast the value to that type when literalizing.

If you would like to use range columns in your model objects, you probably want to modify the schema parsing/typecasting so that it recognizes and correctly handles the range type columns, which you can do by:

DB.extension :pg_range

See the schema modification guide for details on using range type columns in CREATE/ALTER TABLE statements.

This extension makes it easy to add support for other range types. In general, you just need to make sure that the subtype is handled and has the appropriate converter installed in Sequel::Postgres::PG_TYPES or the Database instance's conversion_procs usingthe appropriate type OID. For user defined types, you can do this via:

DB.conversion_procs[subtype_oid] = lambda{|string| }

Then you can call Sequel::Postgres::PGRange::DatabaseMethods#register_range_type to automatically set up a handler for the range type. So if you want to support the timerange type (assuming the time type is already supported):

DB.register_range_type('timerange')

You can also register range types on a global basis using Sequel::Postgres::PGRange.register. In this case, you'll have to specify the type oids:

Sequel::Postgres::PG_TYPES[1234] = lambda{|string| }
Sequel::Postgres::PGRange.register('foo', :oid=>4321, :subtype_oid=>1234)

Both Sequel::Postgres::PGRange::DatabaseMethods#register_range_type and Sequel::Postgres::PGRange.register support many options to customize the range type handling. See the Sequel::Postgres::PGRange.register method documentation.

This extension integrates with the pg_array extension. If you plan to use arrays of range types, load the pg_array extension before the pg_range extension:

DB.extension :pg_array, :pg_range

Related module: Sequel::Postgres::PGRange

Required files

  1. adapters/utils/pg_types