class PG::BasicTypeMapForQueries

Simple set of rules for type casting common Ruby types to PostgreSQL.

OIDs of supported type casts are not hard-coded in the sources, but are retrieved from the PostgreSQL's pg_type table in PG::BasicTypeMapForQueries.new .

Query params are type casted based on the class of the given value.

Higher level libraries will most likely not make use of this class, but use their own derivation of PG::TypeMapByClass or another set of rules to choose suitable encoders and decoders for the values to be sent.

Example:

conn = PG::Connection.new
# Assign a default ruleset for type casts of input and output values.
conn.type_map_for_queries = PG::BasicTypeMapForQueries.new(conn)
# Execute a query. The Integer param value is typecasted internally by PG::BinaryEncoder::Int8.
# The format of the parameter is set to 0 (text) and the OID of this parameter is set to 20 (int8).
res = conn.exec_params( "SELECT $1", [5] )

Constants

DEFAULT_ARRAY_TYPE_MAP
DEFAULT_TYPE_MAP

Attributes

encode_array_as[R]

Public Class Methods

new(connection_or_coder_maps, registry: nil, if_undefined: nil) click to toggle source

Create a new type map for query submission

Options:

  • registry: Custom type registry, nil for default global registry

  • if_undefined: Optional Proc object which is called, if no type for an parameter class is not defined in the registry. The Proc object is called with the name and format of the missing type. Its return value is not used.

# File lib/pg/basic_type_map_for_queries.rb, line 51
def initialize(connection_or_coder_maps, registry: nil, if_undefined: nil)
        @coder_maps = build_coder_maps(connection_or_coder_maps, registry: registry)
        @array_encoders_by_klass = array_encoders_by_klass
        @encode_array_as = :array
        @if_undefined = if_undefined || method(:raise_undefined_type).to_proc
        init_encoders
end

Public Instance Methods

encode_array_as=(pg_type) click to toggle source

Change the mechanism that is used to encode ruby array values

Possible values:

  • :array : Encode the ruby array as a PostgreSQL array. The array element type is inferred from the class of the first array element. This is the default.

  • :json : Encode the ruby array as a JSON document.

  • :record : Encode the ruby array as a composite type row.

  • "_type" : Encode the ruby array as a particular PostgreSQL type. All PostgreSQL array types are supported. If there's an encoder registered for the elements type, it will be used. Otherwise a string conversion (by value.to_s) is done.

# File lib/pg/basic_type_map_for_queries.rb, line 74
def encode_array_as=(pg_type)
        case pg_type
                when :array
                when :json
                when :record
                when /\A_/
                else
                        raise ArgumentError, "invalid pg_type #{pg_type.inspect}"
        end

        @encode_array_as = pg_type

        init_encoders
end

Private Instance Methods

array_encoders_by_klass() click to toggle source
# File lib/pg/basic_type_map_for_queries.rb, line 151
def array_encoders_by_klass
        DEFAULT_ARRAY_TYPE_MAP.inject({}) do |h, (klass, (format, name))|
                h[klass] = coder_by_name(format, :encoder, name)
                h
        end
end
coder_by_name(format, direction, name) click to toggle source
# File lib/pg/basic_type_map_for_queries.rb, line 99
def coder_by_name(format, direction, name)
        check_format_and_direction(format, direction)
        @coder_maps.map_for(format, direction).coder_by_name(name)
end
get_array_type(value) click to toggle source
# File lib/pg/basic_type_map_for_queries.rb, line 158
def get_array_type(value)
        elem = value
        while elem.kind_of?(Array)
                elem = elem.first
        end
        @array_encoders_by_klass[elem.class] ||
                        elem.class.ancestors.lazy.map{|ancestor| @array_encoders_by_klass[ancestor] }.find{|a| a } ||
                        @textarray_encoder
end
init_encoders() click to toggle source
# File lib/pg/basic_type_map_for_queries.rb, line 93
def init_encoders
        coders.each { |kl, c| self[kl] = nil } # Clear type map
        populate_encoder_list
        @textarray_encoder = coder_by_name(0, :encoder, '_text')
end
populate_encoder_list() click to toggle source
# File lib/pg/basic_type_map_for_queries.rb, line 108
def populate_encoder_list
        DEFAULT_TYPE_MAP.each do |klass, selector|
                if Array === selector
                        format, name, oid_name = selector
                        coder = coder_by_name(format, :encoder, name).dup
                        if coder
                                if oid_name
                                        oid_coder = coder_by_name(format, :encoder, oid_name)
                                        if oid_coder
                                                coder.oid = oid_coder.oid
                                        else
                                                undefined(oid_name, format)
                                        end
                                else
                                        coder.oid = 0
                                end
                                self[klass] = coder
                        else
                                undefined(name, format)
                        end
                else

                        case @encode_array_as
                                when :array
                                        self[klass] = selector
                                when :json
                                        self[klass] = PG::TextEncoder::JSON.new
                                when :record
                                        self[klass] = PG::TextEncoder::Record.new type_map: self
                                when /\A_/
                                        coder = coder_by_name(0, :encoder, @encode_array_as)
                                        if coder
                                                self[klass] = coder
                                        else
                                                undefined(@encode_array_as, format)
                                        end
                                else
                                        raise ArgumentError, "invalid pg_type #{@encode_array_as.inspect}"
                        end
                end
        end
end
raise_undefined_type(oid_name, format) click to toggle source
# File lib/pg/basic_type_map_for_queries.rb, line 59
        def raise_undefined_type(oid_name, format)
        raise UndefinedEncoder, "no encoder defined for type #{oid_name.inspect} format #{format}"
end
undefined(name, format) click to toggle source
# File lib/pg/basic_type_map_for_queries.rb, line 104
def undefined(name, format)
        @if_undefined.call(name, format)
end