pg gem:'警告:没有为类型“numeric”定义类型转换

时间:2020-12-18 23:25:38

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带我进来:)

[pry cd and ls]

[撬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  

  1. Google the error message: "Warning: no type cast defined for type"
  2. 谷歌的错误信息:“警告:没有为类型定义类型转换”

  3. You can find it's source github.
  4. 你可以找到它的源码github。

  5. Reding the class, I would guess lines from 150 to 214 could be consiredered examples:
    • register_type 0, 'text', PG::TextEncoder::String
    • register_type 0,'text',PG :: TextEncoder :: String

    • alias_type 0, 'varchar', 'text'
    • alias_type 0,'varchar','text'

  6. 重做这个类,我猜测从150到214的行可能是一个例子:register_type 0,'text',PG :: TextEncoder :: String alias_type 0,'varchar','text'

  7. 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,'money','text'

    • PG::BasicTypeRegistry::CoderMap.alias_type 0, 'numeric', 'text'
    • PG :: BasicTypeRegistry :: CoderMap.alias_type 0,'numeric','text'

  8. 由于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带我进来:)

[pry cd and ls]

[撬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  

  1. Google the error message: "Warning: no type cast defined for type"
  2. 谷歌的错误信息:“警告:没有为类型定义类型转换”

  3. You can find it's source github.
  4. 你可以找到它的源码github。

  5. Reding the class, I would guess lines from 150 to 214 could be consiredered examples:
    • register_type 0, 'text', PG::TextEncoder::String
    • register_type 0,'text',PG :: TextEncoder :: String

    • alias_type 0, 'varchar', 'text'
    • alias_type 0,'varchar','text'

  6. 重做这个类,我猜测从150到214的行可能是一个例子:register_type 0,'text',PG :: TextEncoder :: String alias_type 0,'varchar','text'

  7. 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,'money','text'

    • PG::BasicTypeRegistry::CoderMap.alias_type 0, 'numeric', 'text'
    • PG :: BasicTypeRegistry :: CoderMap.alias_type 0,'numeric','text'

  8. 由于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,它可以实现更多类型(金钱)。