I'm having trouble getting typed results out of the pg gem.
我无法从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?
任何人都可以告诉我如何“明确地转换类型”,假设我不想为每个表硬编码解决方案?
4 个解决方案
#1
1
Got the same problem with a text-ish field. Solved by duplicating a coder and editing its OID.
在text-ish字段中遇到了同样的问题。通过复制编码器并编辑其OID来解决。
text_coder = client.type_map_for_results.coders.find { |c| c.name == 'text' }
new_coder = text_coder.dup.tap { |c| c.oid = 19 } # oid from the warning
conn.type_map_for_results.add_coder(new_coder)
How I got there: it might interest the next guy, if the problem is similar but not identical.
我是如何到达那里的:如果问题相似但不完全相同,它可能会引起下一个人的兴趣。
I read other people online talking about type_map_for_results
, but how they didn't know how to define a coder. Since it was a text field in my case, I decided to try cloning an existing one. I knew I could find a textual pre-set in a Rails app, so I opened a rails console
and searched:
我在线阅读其他人谈论type_map_for_results,但是他们怎么不知道如何定义编码器。由于在我的案例中它是一个文本字段,我决定尝试克隆现有的字段。我知道我可以在Rails应用程序中找到一个文本预设,所以我打开了一个rails控制台并搜索:
adapter = ActiveRecord::Base.connection
connection = adapter.instance_variable_get("@connection")
mapping = connection.type_map_for_results
cd mapping # my console of choice is `pry`
ls # spotted a likely getter named `coders`
cd coders # again
ls # spotted getter `name` and setter `oid=`
So I put together the code in the solution. Gave it a try, and it worked.
所以我把代码放在解决方案中。试一试,它有效。
It had not been straightforward to find, so I decided to exit lurker mode and share it on SO. Thereby: thanks @Andreyy for bringing me in :)
它找不到直截了当,所以我决定退出潜伏模式并在SO上分享。因此:感谢@Andreyy带我进来:)
[撬cd和ls]
#2
2
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)
#3
1
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
#4
-1
- Google the error message: "Warning: no type cast defined for type"
- You can find it's source github.
- Reding the class, I would guess lines from 150 to 214 could be consiredered examples:
register_type 0, 'text', PG::TextEncoder::String
alias_type 0, 'varchar', 'text'
register_type 0,'text',PG :: TextEncoder :: String
alias_type 0,'varchar','text'
- Since register_type and alias_type are class methods of
PG::BasicTypeRegistry::CoderMap
I would play with them just and see if anything changes:PG::BasicTypeRegistry::CoderMap.alias_type 0, 'money', 'text'
PG::BasicTypeRegistry::CoderMap.alias_type 0, 'numeric', 'text'
PG :: BasicTypeRegistry :: CoderMap.alias_type 0,'money','text'
PG :: BasicTypeRegistry :: CoderMap.alias_type 0,'numeric','text'
谷歌的错误信息:“警告:没有为类型定义类型转换”
你可以找到它的源码github。
重做这个类,我猜测从150到214的行可能是一个例子:register_type 0,'text',PG :: TextEncoder :: String alias_type 0,'varchar','text'
由于register_type和alias_type是PG :: BasicTypeRegistry :: CoderMap的类方法,我将只使用它们并查看是否有任何更改:PG :: BasicTypeRegistry :: CoderMap.alias_type 0,'money','text'PG :: BasicTypeRegistry: :CoderMap.alias_type 0,'numeric','text'
Reading the comments in the class it seems that the coding/decoding of those and some other fields is not implemented.
读取类中的注释似乎没有实现那些和其他一些字段的编码/解码。
You might consider using a higher level ORM library like AvtiveRecord which implements more types (money).
您可以考虑使用更高级别的ORM库,例如AvtiveRecord,它可以实现更多类型(金钱)。
#1
1
Got the same problem with a text-ish field. Solved by duplicating a coder and editing its OID.
在text-ish字段中遇到了同样的问题。通过复制编码器并编辑其OID来解决。
text_coder = client.type_map_for_results.coders.find { |c| c.name == 'text' }
new_coder = text_coder.dup.tap { |c| c.oid = 19 } # oid from the warning
conn.type_map_for_results.add_coder(new_coder)
How I got there: it might interest the next guy, if the problem is similar but not identical.
我是如何到达那里的:如果问题相似但不完全相同,它可能会引起下一个人的兴趣。
I read other people online talking about type_map_for_results
, but how they didn't know how to define a coder. Since it was a text field in my case, I decided to try cloning an existing one. I knew I could find a textual pre-set in a Rails app, so I opened a rails console
and searched:
我在线阅读其他人谈论type_map_for_results,但是他们怎么不知道如何定义编码器。由于在我的案例中它是一个文本字段,我决定尝试克隆现有的字段。我知道我可以在Rails应用程序中找到一个文本预设,所以我打开了一个rails控制台并搜索:
adapter = ActiveRecord::Base.connection
connection = adapter.instance_variable_get("@connection")
mapping = connection.type_map_for_results
cd mapping # my console of choice is `pry`
ls # spotted a likely getter named `coders`
cd coders # again
ls # spotted getter `name` and setter `oid=`
So I put together the code in the solution. Gave it a try, and it worked.
所以我把代码放在解决方案中。试一试,它有效。
It had not been straightforward to find, so I decided to exit lurker mode and share it on SO. Thereby: thanks @Andreyy for bringing me in :)
它找不到直截了当,所以我决定退出潜伏模式并在SO上分享。因此:感谢@Andreyy带我进来:)
[撬cd和ls]
#2
2
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)
#3
1
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
#4
-1
- Google the error message: "Warning: no type cast defined for type"
- You can find it's source github.
- Reding the class, I would guess lines from 150 to 214 could be consiredered examples:
register_type 0, 'text', PG::TextEncoder::String
alias_type 0, 'varchar', 'text'
register_type 0,'text',PG :: TextEncoder :: String
alias_type 0,'varchar','text'
- Since register_type and alias_type are class methods of
PG::BasicTypeRegistry::CoderMap
I would play with them just and see if anything changes:PG::BasicTypeRegistry::CoderMap.alias_type 0, 'money', 'text'
PG::BasicTypeRegistry::CoderMap.alias_type 0, 'numeric', 'text'
PG :: BasicTypeRegistry :: CoderMap.alias_type 0,'money','text'
PG :: BasicTypeRegistry :: CoderMap.alias_type 0,'numeric','text'
谷歌的错误信息:“警告:没有为类型定义类型转换”
你可以找到它的源码github。
重做这个类,我猜测从150到214的行可能是一个例子:register_type 0,'text',PG :: TextEncoder :: String alias_type 0,'varchar','text'
由于register_type和alias_type是PG :: BasicTypeRegistry :: CoderMap的类方法,我将只使用它们并查看是否有任何更改:PG :: BasicTypeRegistry :: CoderMap.alias_type 0,'money','text'PG :: BasicTypeRegistry: :CoderMap.alias_type 0,'numeric','text'
Reading the comments in the class it seems that the coding/decoding of those and some other fields is not implemented.
读取类中的注释似乎没有实现那些和其他一些字段的编码/解码。
You might consider using a higher level ORM library like AvtiveRecord which implements more types (money).
您可以考虑使用更高级别的ORM库,例如AvtiveRecord,它可以实现更多类型(金钱)。