module Sequel::Postgres::PGArray::DatabaseMethods

Constants

APOS
BLOB_RANGE
DOUBLE_APOS
ESCAPE_RE
ESCAPE_REPLACEMENT

Public Class Methods

extended(db) click to toggle source

Create the local hash of database type strings to schema type symbols, used for array types local to this database.

# File lib/sequel/extensions/pg_array.rb, line 200
def self.extended(db)
  db.instance_eval do
    @pg_array_schema_types ||= {}
    procs = conversion_procs
    procs[1115] = Creator.new("timestamp without time zone", procs[1114])
    procs[1185] = Creator.new("timestamp with time zone", procs[1184])
    copy_conversion_procs([143, 791, 1000, 1001, 1003, 1005, 1006, 1007, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1021, 1022, 1028, 1182, 1183, 1231, 1270, 1561, 1563, 2951])
    [:string_array, :integer_array, :decimal_array, :float_array, :boolean_array, :blob_array, :date_array, :time_array, :datetime_array].each do |v|
      @schema_type_classes[v] = PGArray
    end
  end
end

Public Instance Methods

bound_variable_arg(arg, conn) click to toggle source

Handle arrays in bound variables

Calls superclass method
# File lib/sequel/extensions/pg_array.rb, line 214
def bound_variable_arg(arg, conn)
  case arg
  when PGArray
    bound_variable_array(arg.to_a)
  when Array
    bound_variable_array(arg)
  else
    super
  end
end
register_array_type(db_type, opts=OPTS, &block) click to toggle source

Register a database specific array type. This can be used to support different array types per Database. Use of this method does not affect global state, unlike Sequel::Postgres::PGArray.register. See Sequel::Postgres::PGArray.register for possible options.

# File lib/sequel/extensions/pg_array.rb, line 229
def register_array_type(db_type, opts=OPTS, &block)
  opts = {:type_procs=>conversion_procs, :typecast_method_map=>@pg_array_schema_types, :typecast_methods_module=>(class << self; self; end)}.merge(opts)
  unless (opts.has_key?(:scalar_oid) || block) && opts.has_key?(:oid)
    array_oid, scalar_oid = from(:pg_type).where(:typname=>db_type.to_s).get([:typarray, :oid])
    opts[:scalar_oid] = scalar_oid unless opts.has_key?(:scalar_oid) || block
    opts[:oid] = array_oid unless opts.has_key?(:oid)
  end
  PGArray.register(db_type, opts, &block)
  @schema_type_classes[:"#{opts[:type_symbol] || db_type}_array"] = PGArray
  conversion_procs_updated
end
schema_type_class(type) click to toggle source

Return PGArray if this type matches any supported array type.

Calls superclass method
# File lib/sequel/extensions/pg_array.rb, line 242
def schema_type_class(type)
  super || (ARRAY_TYPES.each_value{|v| return PGArray if type == v}; nil)
end

Private Instance Methods

bound_variable_array(a) click to toggle source

Format arrays used in bound variables.

# File lib/sequel/extensions/pg_array.rb, line 249
def bound_variable_array(a)
  case a
  when Array
    "{#{a.map{|i| bound_variable_array(i)}.join(COMMA)}}"
  when Sequel::SQL::Blob
    "\"#{literal(a)[BLOB_RANGE].gsub(DOUBLE_APOS, APOS).gsub(ESCAPE_RE, ESCAPE_REPLACEMENT)}\""
  when Sequel::LiteralString
    a
  when String
    "\"#{a.gsub(ESCAPE_RE, ESCAPE_REPLACEMENT)}\""
  else
    literal(a)
  end
end
convert_named_procs_to_procs(named_procs) click to toggle source

Automatically handle array types for the given named types.

Calls superclass method
# File lib/sequel/extensions/pg_array.rb, line 265
def convert_named_procs_to_procs(named_procs)
  h = super
  unless h.empty?
    from(:pg_type).where(:oid=>h.keys).select_map([:typname, :oid, :typarray]).each do |name, scalar_oid, array_oid|
      register_array_type(name, :type_procs=>h, :oid=>array_oid.to_i, :scalar_oid=>scalar_oid.to_i)
    end
  end
  h
end
get_conversion_procs() click to toggle source

Manually override the typecasting for timestamp array types so that they use the database's timezone instead of the global Sequel timezone.

Calls superclass method
# File lib/sequel/extensions/pg_array.rb, line 278
def get_conversion_procs
  procs = super

  procs[1115] = Creator.new("timestamp without time zone", procs[1114])
  procs[1185] = Creator.new("timestamp with time zone", procs[1184])

  procs
end
pg_array_schema_type(type) click to toggle source

Look into both the current database's array schema types and the global array schema types to get the type symbol for the given database type string.

# File lib/sequel/extensions/pg_array.rb, line 290
def pg_array_schema_type(type)
  @pg_array_schema_types[type] || ARRAY_TYPES[type]
end
schema_column_type(db_type) click to toggle source

Make the column type detection handle registered array types.

Calls superclass method
# File lib/sequel/extensions/pg_array.rb, line 295
def schema_column_type(db_type)
  if (db_type =~ /\A([^(]+)(?:\([^(]+\))?\[\]\z/io) && (type = pg_array_schema_type($1))
    type
  else
    super
  end
end
typecast_value_pg_array(value, creator, scalar_typecast_method=nil) click to toggle source

Given a value to typecast and the type of PGArray subclass:

  • If given a PGArray with a matching array_type, use it directly.

  • If given a PGArray with a different array_type, return a PGArray with the creator's type.

  • If given an Array, create a new PGArray instance for it. This does not typecast all members of the array in ruby for performance reasons, but it will cast the array the appropriate database type when the array is literalized.

# File lib/sequel/extensions/pg_array.rb, line 311
def typecast_value_pg_array(value, creator, scalar_typecast_method=nil)
  case value
  when PGArray
    if value.array_type != creator.type
      PGArray.new(value.to_a, creator.type)
    else
      value
    end
  when Array
    if scalar_typecast_method && respond_to?(scalar_typecast_method, true)
      value = Sequel.recursive_map(value, method(scalar_typecast_method))
    end
    PGArray.new(value, creator.type)
  else
    raise Sequel::InvalidValue, "invalid value for array type: #{value.inspect}"
  end
end