module PG::BasicTypeRegistry
This module defines the mapping between OID and encoder/decoder classes for PG::BasicTypeMapForResults
, PG::BasicTypeMapForQueries
and PG::BasicTypeMapBasedOnResult
.
Additional types can be added like so:
require 'pg' require 'ipaddr' class InetDecoder < PG::SimpleDecoder def decode(string, tuple=nil, field=nil) IPAddr.new(string) end end class InetEncoder < PG::SimpleEncoder def encode(ip_addr) ip_addr.to_s end end # 0 if for text format, can also be 1 for binary PG::BasicTypeRegistry.register_type(0, 'inet', InetEncoder, InetDecoder)
Constants
- CODERS_BY_NAME
The key of this hash maps to the `typname` column from the table. encoder_map is then dynamically built with oids as the key and Type objects as values.
- ValidDirections
- ValidFormats
Public Class Methods
Alias the old
type to the new
type.
# File lib/pg/basic_type_mapping.rb, line 180 def self.alias_type(format, new, old) [:encoder, :decoder].each do |ende| enc = CODERS_BY_NAME[format][ende][old] if enc CODERS_BY_NAME[format][ende][new] = enc else CODERS_BY_NAME[format][ende].delete(new) end end end
Register an encoder or decoder instance for casting a PostgreSQL type.
Coder#name
must correspond to the typname
column in the pg_type
table. Coder#format
can be 0 for text format and 1 for binary.
# File lib/pg/basic_type_mapping.rb, line 163 def self.register_coder(coder) h = CODERS_BY_NAME[coder.format] ||= { encoder: {}, decoder: {} } name = coder.name || raise(ArgumentError, "name of #{coder.inspect} must be defined") h[:encoder][name] = coder if coder.respond_to?(:encode) h[:decoder][name] = coder if coder.respond_to?(:decode) end
Register the given encoder_class
and/or decoder_class
for casting a PostgreSQL type.
name
must correspond to the typname
column in the pg_type
table. format
can be 0 for text format and 1 for binary.
# File lib/pg/basic_type_mapping.rb, line 174 def self.register_type(format, name, encoder_class, decoder_class) register_coder(encoder_class.new(name: name, format: format)) if encoder_class register_coder(decoder_class.new(name: name, format: format)) if decoder_class end
Protected Instance Methods
# File lib/pg/basic_type_mapping.rb, line 146 def check_format_and_direction(format, direction) raise(ArgumentError, "Invalid format value %p" % format) unless ValidFormats[format] raise(ArgumentError, "Invalid direction %p" % direction) unless ValidDirections[direction] end
Private Instance Methods
# File lib/pg/basic_type_mapping.rb, line 117 def build_coder_maps(connection) if supports_ranges?(connection) result = connection.exec <<-SQL SELECT t.oid, t.typname::text, t.typelem, t.typdelim, t.typinput::text, r.rngsubtype FROM pg_type as t LEFT JOIN pg_range as r ON oid = rngtypid SQL else result = connection.exec <<-SQL SELECT t.oid, t.typname::text, t.typelem, t.typdelim, t.typinput::text FROM pg_type as t SQL end [ [0, :encoder, PG::TextEncoder::Array], [0, :decoder, PG::TextDecoder::Array], [1, :encoder, nil], [1, :decoder, nil], ].inject([]) do |h, (format, direction, arraycoder)| h[format] ||= {} h[format][direction] = CoderMap.new result, CODERS_BY_NAME[format][direction], format, arraycoder h end end
# File lib/pg/basic_type_mapping.rb, line 113 def supports_ranges?(connection) connection.server_version >= 90200 end