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
Public Class Methods
Create a new type map for query submission
Options:
-
registry
: Custom type registry, nil for default global registry -
if_undefined
: OptionalProc
object which is called, if no type for an parameter class is not defined in the registry. TheProc
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
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 elementstype
, it will be used. Otherwise a string conversion (byvalue.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
# 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
# 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
# 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
# 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
# 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
# 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
# File lib/pg/basic_type_map_for_queries.rb, line 104 def undefined(name, format) @if_undefined.call(name, format) end