module Sequel::Postgres::PGArray::DatabaseMethods
Constants
- APOS
- BLOB_RANGE
- DOUBLE_APOS
- ESCAPE_RE
- ESCAPE_REPLACEMENT
Public Class Methods
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
Handle arrays in bound variables
# 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 the pg array schema types to prevent adding new ones.
# File lib/sequel/extensions/pg_array.rb, line 225 def freeze @pg_array_schema_types.freeze super end
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
Return PGArray if this type matches any supported array type.
# 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
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
Convert ruby arrays to PostgreSQL arrays when used as default values.
# 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
Automatically handle array types for the given named types.
# 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
Manually override the typecasting for timestamp array types so that they use the database's timezone instead of the global Sequel timezone.
# 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
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
Make the column type detection handle registered array types.
# 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
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