Class: Sequel::Postgres::PGArray

Inherits:
Array show all
Includes:
SQL::AliasMethods
Defined in:
lib/sequel/extensions/pg_array.rb,
lib/sequel/extensions/pg_array_ops.rb

Overview

Represents a PostgreSQL array column value.

Defined Under Namespace

Modules: DatabaseMethods Classes: Creator, JSONCreator, Parser

Constant Summary collapse

ARRAY =
"ARRAY".freeze
DOUBLE_COLON =
'::'.freeze
EMPTY_ARRAY =
"'{}'".freeze
EMPTY_BRACKET =
'[]'.freeze
OPEN_BRACKET =
'['.freeze
CLOSE_BRACKET =
']'.freeze
COMMA =
','.freeze
BACKSLASH =
'\\'.freeze
EMPTY_STRING =
''.freeze
OPEN_BRACE =
'{'.freeze
CLOSE_BRACE =
'}'.freeze
NULL =
'NULL'.freeze
QUOTE =
'"'.freeze
ARRAY_TYPES =

Global hash of database array type name strings to symbols (e.g. ‘double precision’ => :float), used by the schema parsing for array types registered globally.

{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from SQL::AliasMethods

#as

Methods inherited from Array

#case, #pg_array, #pg_json, #pg_jsonb, #pg_row, #sql_expr, #sql_negate, #sql_or, #sql_string_join, #sql_value_list, #~

Constructor Details

#initialize(array, type = nil) ⇒ PGArray

Set the array to delegate to, and a database type.



491
492
493
494
# File 'lib/sequel/extensions/pg_array.rb', line 491

def initialize(array, type=nil)
  super(array)
  @array_type = type
end

Instance Attribute Details

#array_typeObject

The type of this array. May be nil if no type was given. If a type is provided, the array is automatically casted to this type when literalizing. This type is the underlying type, not the array type itself, so for an int4[] database type, it should be :int4 or ‘int4’



488
489
490
# File 'lib/sequel/extensions/pg_array.rb', line 488

def array_type
  @array_type
end

Class Method Details

.register(db_type, opts = OPTS, &block) ⇒ Object

Registers an array type that the extension should handle. Makes a Database instance that has been extended with DatabaseMethods recognize the array type given and set up the appropriate typecasting. Also sets up automatic typecasting for the native postgres adapter, so that on retrieval, the values are automatically converted to PGArray instances. The db_type argument should be the exact database type used (as returned by the PostgreSQL format_type database function). Accepts the following options:

:array_type

The type to automatically cast the array to when literalizing the array. Usually the same as db_type.

:converter

A callable object (e.g. Proc), that is called with each element of the array (usually a string), and should return the appropriate typecasted object.

:oid

The PostgreSQL OID for the array type. This is used by the Sequel postgres adapter to set up automatic type conversion on retrieval from the database.

:parser

Can be set to :json to use the faster JSON-based parser. Note that the JSON-based parser can only correctly handle integers values correctly. It doesn’t handle full precision for numeric types, and doesn’t handle NaN/Infinity values for floating point types.

:scalar_oid

Should be the PostgreSQL OID for the scalar version of this array type. If given, automatically sets the :converter option by looking for scalar conversion proc.

:scalar_typecast

Should be a symbol indicating the typecast method that should be called on each element of the array, when a plain array is passed into a database typecast method. For example, for an array of integers, this could be set to :integer, so that the typecast_value_integer method is called on all of the array elements. Defaults to :type_symbol option.

:type_procs

A hash mapping oids to conversion procs, used for looking up the :scalar_oid and value and setting the :oid value. Defaults to the global Sequel::Postgres::PG_TYPES.

:type_symbol

The base of the schema type symbol for this type. For example, if you provide :integer, Sequel will recognize this type as :integer_array during schema parsing. Defaults to the db_type argument.

:typecast_method_map

The map in which to place the database type string to type symbol mapping. Defaults to ARRAY_TYPES.

:typecast_methods_module

If given, a module object to add the typecasting method to. Defaults to DatabaseMethods.

If a block is given, it is treated as the :converter option.



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/sequel/extensions/pg_array.rb', line 147

def self.register(db_type, opts=OPTS, &block)
  db_type = db_type.to_s
  type = (opts[:type_symbol] || db_type).to_sym
  type_procs = opts[:type_procs] || PG_TYPES
  mod = opts[:typecast_methods_module] || DatabaseMethods
  typecast_method_map = opts[:typecast_method_map] || ARRAY_TYPES

  if converter = opts[:converter]
    raise Error, "can't provide both a block and :converter option to register" if block
  else
    converter = block
  end

  if soid = opts[:scalar_oid]
    raise Error, "can't provide both a converter and :scalar_oid option to register" if converter 
    converter = type_procs[soid]
  end

  array_type = (opts[:array_type] || db_type).to_s.dup.freeze
  creator = (opts[:parser] == :json ? JSONCreator : Creator).new(array_type, converter)

  typecast_method_map[db_type] = :"#{type}_array"

  define_array_typecast_method(mod, type, creator, opts.fetch(:scalar_typecast, type))

  if oid = opts[:oid]
    type_procs[oid] = creator
  end

  nil
end

Instance Method Details

#opObject

Wrap the PGArray instance in an ArrayOp, allowing you to easily use the PostgreSQL array functions and operators with literal arrays.



282
283
284
# File 'lib/sequel/extensions/pg_array_ops.rb', line 282

def op
  ArrayOp.new(self)
end

#sql_literal_append(ds, sql) ⇒ Object

Append the array SQL to the given sql string. If the receiver has a type, add a cast to the database array type.



499
500
501
502
503
504
505
506
507
508
509
510
# File 'lib/sequel/extensions/pg_array.rb', line 499

def sql_literal_append(ds, sql)
  at = array_type
  if empty? && at
    sql << EMPTY_ARRAY
  else
    sql << ARRAY
    _literal_append(sql, ds, to_a)
  end
  if at
    sql << DOUBLE_COLON << at.to_s << EMPTY_BRACKET
  end
end