module Sequel::Postgres::PGMultiRange::DatabaseMethods
Public Class Methods
Add the default multirange conversion procs to the database
# File lib/sequel/extensions/pg_multirange.rb, line 112 def self.extended(db) db.instance_exec do raise Error, "multiranges not supported on this database" unless server_version >= 140000 extension :pg_range @pg_multirange_schema_types ||= {} register_multirange_type('int4multirange', :range_oid=>3904, :oid=>4451) register_multirange_type('nummultirange', :range_oid=>3906, :oid=>4532) register_multirange_type('tsmultirange', :range_oid=>3908, :oid=>4533) register_multirange_type('tstzmultirange', :range_oid=>3910, :oid=>4534) register_multirange_type('datemultirange', :range_oid=>3912, :oid=>4535) register_multirange_type('int8multirange', :range_oid=>3926, :oid=>4536) if respond_to?(:register_array_type) register_array_type('int4multirange', :oid=>6150, :scalar_oid=>4451, :scalar_typecast=>:int4multirange) register_array_type('nummultirange', :oid=>6151, :scalar_oid=>4532, :scalar_typecast=>:nummultirange) register_array_type('tsmultirange', :oid=>6152, :scalar_oid=>4533, :scalar_typecast=>:tsmultirange) register_array_type('tstzmultirange', :oid=>6153, :scalar_oid=>4534, :scalar_typecast=>:tstzmultirange) register_array_type('datemultirange', :oid=>6155, :scalar_oid=>4535, :scalar_typecast=>:datemultirange) register_array_type('int8multirange', :oid=>6157, :scalar_oid=>4536, :scalar_typecast=>:int8multirange) end [:int4multirange, :nummultirange, :tsmultirange, :tstzmultirange, :datemultirange, :int8multirange].each do |v| @schema_type_classes[v] = PGMultiRange end procs = conversion_procs add_conversion_proc(4533, PGMultiRange::Creator.new("tsmultirange", procs[3908])) add_conversion_proc(4534, PGMultiRange::Creator.new("tstzmultirange", procs[3910])) if respond_to?(:register_array_type) && defined?(PGArray::Creator) add_conversion_proc(6152, PGArray::Creator.new("tsmultirange", procs[4533])) add_conversion_proc(6153, PGArray::Creator.new("tstzmultirange", procs[4534])) end end end
Public Instance Methods
Handle PGMultiRange values in bound variables
# File lib/sequel/extensions/pg_multirange.rb, line 151 def bound_variable_arg(arg, conn) case arg when PGMultiRange arg.unquoted_literal(schema_utility_dataset) else super end end
Freeze the pg multirange schema types to prevent adding new ones.
# File lib/sequel/extensions/pg_multirange.rb, line 161 def freeze @pg_multirange_schema_types.freeze super end
Register a database specific multirange type. This can be used to support different multirange types per Database. Options:
- :converter
-
A callable object (e.g. Proc), that is called with the PostgreSQL range string, and should return a PGRange instance.
- :oid
-
The PostgreSQL OID for the multirange type. This is used by Sequel to set up automatic type conversion on retrieval from the database.
- :range_oid
-
Should be the PostgreSQL OID for the multirange subtype (the range type). If given, automatically sets the :converter option by looking for scalar conversion proc.
If a block is given, it is treated as the :converter option.
# File lib/sequel/extensions/pg_multirange.rb, line 178 def register_multirange_type(db_type, opts=OPTS, &block) oid = opts[:oid] soid = opts[:range_oid] if has_converter = opts.has_key?(:converter) raise Error, "can't provide both a block and :converter option to register_multirange_type" if block converter = opts[:converter] else has_converter = true if block converter = block end unless (soid || has_converter) && oid range_oid, subtype_oid = from(:pg_range).join(:pg_type, :oid=>:rngmultitypid).where(:typname=>db_type.to_s).get([:rngmultitypid, :rngtypid]) soid ||= subtype_oid unless has_converter oid ||= range_oid end db_type = db_type.to_s.dup.freeze if soid raise Error, "can't provide both a converter and :range_oid option to register" if has_converter raise Error, "no conversion proc for :range_oid=>#{soid.inspect} in conversion_procs" unless converter = conversion_procs[soid] end raise Error, "cannot add a multirange type without a convertor (use :converter or :range_oid option or pass block)" unless converter creator = Creator.new(db_type, converter) add_conversion_proc(oid, creator) @pg_multirange_schema_types[db_type] = db_type.to_sym singleton_class.class_eval do meth = :"typecast_value_#{db_type}" scalar_typecast_method = :"typecast_value_#{opts.fetch(:scalar_typecast, db_type.sub('multirange', 'range'))}" define_method(meth){|v| typecast_value_pg_multirange(v, creator, scalar_typecast_method)} private meth end @schema_type_classes[db_type] = PGMultiRange nil end
Private Instance Methods
Recognize the registered database multirange types.
# File lib/sequel/extensions/pg_multirange.rb, line 223 def schema_multirange_type(db_type) @pg_multirange_schema_types[db_type] || super end
Set the :ruby_default value if the default value is recognized as a multirange.
# File lib/sequel/extensions/pg_multirange.rb, line 228 def schema_post_process(_) super.each do |a| h = a[1] db_type = h[:db_type] if @pg_multirange_schema_types[db_type] && h[:default] =~ /\A#{db_type}\(.*\)\z/ h[:ruby_default] = get(Sequel.lit(h[:default])) end end end
Given a value to typecast and the type of PGMultiRange subclass:
-
If given a PGMultiRange with a matching type, use it directly.
-
If given a PGMultiRange with a different type, return a PGMultiRange with the creator's type.
-
If given an Array, create a new PGMultiRange instance for it, typecasting each instance using the scalar_typecast_method.
# File lib/sequel/extensions/pg_multirange.rb, line 244 def typecast_value_pg_multirange(value, creator, scalar_typecast_method=nil) case value when PGMultiRange return value if value.db_type == creator.type when Array # nothing else raise Sequel::InvalidValue, "invalid value for multirange type: #{value.inspect}" end if scalar_typecast_method && respond_to?(scalar_typecast_method, true) value = value.map{|v| send(scalar_typecast_method, v)} end PGMultiRange.new(value, creator.type) end