2016-01-14 69 views
7

我無法從pg gem中獲得輸入結果。pg gem:'Warning:沒有爲類型「numeric」定義類型轉換''

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 

這個節目給輸出:

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} 

所以:布爾和花車和日期(和整數)被轉換,但不NUMERICS還是把錢類型。

任何人都可以告訴我如何「明確地轉換類型」,假設我不想硬編碼每個表的解決方案?

回答

1

與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) 



我如何到達那裏:可能下一個感興趣的人,如果這個問題是相似但不完全相同。

我看其他人在網上談論type_map_for_results,但他們沒怎麼知道如何定義編碼器。由於這是我的案例中的文本字段,因此我決定嘗試克隆現有的文本字段。我知道我能找到一個Rails應用程序的文本預先設定的,所以我開了一個rails console和搜索:

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=` 

所以我放在一起的解決方案的代碼。試一試,它的工作。

它沒有一帆風順的被發現,所以我決定退出潛行者模式,並分享它的左右。因此:感謝@Andreyy把我的:)

[pry cd and ls]

+0

PS經過這麼多年的潛伏後,我剛加入SO,這是我的第一個貢獻。指導讚賞;) – Giuse

+0

你的代碼中存在一個錯字('new_coder' - >'name_coder'),如果你顯示錯誤信息,它會花費我兩分鐘而不是五分鐘。但沒有任何關係。你已經解決了別人無法做到的事情,即使我提供了賞金。勾選,勾選,勾選。非常感謝! –

+0

我沒有錯誤顯示,因爲我在我的實現中使用了'name_coder'。我的字段實際上被恰當地命名爲'name',因此我選擇了'name_coder',不幸的是在代碼中回聲'c.name' ......困惑了嗎?這就是爲什麼我(試圖)更改名稱的原因:P感謝您發現最後一個名字,我寫了這個答案的那天我幾乎被燒死了。樂意效勞! :) – Giuse

0
  1. 谷歌的錯誤消息:「警告:類型沒有定義類型轉換」
  2. 你可以找到它的源github
  3. 雷丁類,我猜線150至214可以被consiredered 例子:
    • register_type 0, 'text', PG::TextEncoder::String
    • alias_type 0, 'varchar', 'text'
  4. 由於register_type和alias_type是我將與玩的PG::BasicTypeRegistry::CoderMap類方法他們只是看看是否有什麼變化:
    • PG::BasicTypeRegistry::CoderMap.alias_type 0, 'money', 'text'
    • PG::BasicTypeRegistry::CoderMap.alias_type 0, 'numeric', 'text'

閱讀在類似乎這些和其他一些領域的編碼/解碼不落實的意見。

您可以考慮使用更高級別的ORM庫像AvtiveRecord它實現了多種類型(money)。

+0

當然,我已經做了這些事情。我想也許如果Pg能夠通過將「金錢」作爲一個字符串傳遞給Codermap來支持Money,它已經可以這樣做了?我很確定我需要創建一個新的Coder對象,將數字和貨幣類型轉換爲BigDecimal。但是到目前爲止,我所見過的源代碼中沒有任何內容告訴我如何配置新的編碼器對象,或者將其插入哪裏...... –

+0

以實例編碼器/解碼器之一爲例,怎麼樣? https://goo.gl/3Dhe5c – Andreyy

+0

「我迄今爲止看到的源代碼中沒有任何內容告訴我如何配置一個新的編碼器對象」 –

2

劫持這個線程,因爲一些挖後,我終於找到了一種方法來添加自定義解碼器/編碼器,所以下面張貼的例子:

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)