Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pg gem: 'Warning: no type cast defined for type "numeric" '

I'm having trouble getting typed results out of the pg gem.

require 'pg'                                                            
require_relative 'spec/fixtures/database'                               

client = PG.connect( DB[:pg] )                                            
client.type_map_for_queries = PG::BasicTypeMapForQueries.new(client)    
client.type_map_for_results = PG::BasicTypeMapForResults.new(client)    

client.exec( %|select * from testme;| ) do |query|                        
  query.each {|r| puts r.inspect }                                      
end

This program gives the output:

Warning: no type cast defined for type "money" with oid 790. Please cast this type explicitly to TEXT to be safe for future changes.
Warning: no type cast defined for type "numeric" with oid 1700. Please cast this type explicitly to TEXT to be safe for future changes.
{"string"=>"thing", "logical"=>true, "cash"=>"£1.23", "reel"=>"2.34", "day"=>#<Date: 2015-12-31 ((2457388j,0s,0n),+0s,2299161j)>, "float"=>3.45}

So: booleans and floats and dates (and integers) get converted, but not numerics or the money type.

Can anyone tell me how to "cast the type explicitly", assuming that I don't want to hard-code a solution for each table?

like image 780
Andy Jones Avatar asked Jan 14 '16 16:01

Andy Jones


2 Answers

Hijacking this thread, as after some digging I finally found a way to add a custom decoder/encoder, so posting an example below:

require 'ipaddr'
require 'pg'

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)
like image 74
Jack Avatar answered Oct 03 '22 18:10

Jack


Here's a catch all for those seeking to cast strings by default:

client = PG.connect( DB[:pg] )           

map = PG::BasicTypeMapForResults.new(conn)
map.default_type_map = PG::TypeMapAllStrings.new

client.type_map_for_results = map
like image 36
denweny Avatar answered Oct 03 '22 20:10

denweny