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 199
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 213
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
freeze() click to toggle source

Freeze the pg array schema types to prevent adding new ones.

Calls superclass method
# File lib/sequel/extensions/pg_array.rb, line 225
def freeze
  @pg_array_schema_types.freeze
  super
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 234
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 247
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 254
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
column_definition_default_sql(sql, column) click to toggle source

Convert ruby arrays to PostgreSQL arrays when used as default values.

Calls superclass method
# File lib/sequel/extensions/pg_array.rb, line 309
def column_definition_default_sql(sql, column)
  if (d = column[:default]) && d.is_a?(Array) && !Sequel.condition_specifier?(d)
    sql << " DEFAULT (#{literal(Sequel.pg_array(d))}::#{type_literal(column)})"
  else
    super
  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 270
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 283
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 295
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 300
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 325
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