2016-01-14 7 views
7

Ho problemi a ottenere risultati digitati dalla gemma pg.pg gem: 'Attenzione: nessun tipo di cast definito per il tipo "numerico"'

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 

Questo programma dà l'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} 

Quindi: booleani e carri e date (e interi) vengono convertiti, ma non numerici o il tipo di denaro.

Qualcuno può dirmi come "eseguire il cast del tipo in modo esplicito", assumendo che non si desideri codificare in modo rigido una soluzione per ogni tabella?

risposta

1

Ha lo stesso problema con un campo di testo. Risolto duplicando un codificatore e modificando il suo 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) 



come ci sono arrivato: che potrebbe interessare la persona accanto, se il problema è simile ma non identico.

Ho letto altre persone in linea che parlano di type_map_for_results, ma come non sapevano come definire un codificatore. Dato che si trattava di un campo di testo nel mio caso, ho deciso di provare a clonare uno esistente. Sapevo che avrei potuto trovare un testo pre-impostato in un'applicazione Rails, così ho aperto un rails console e cercato:

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

così ho messo insieme il codice nella soluzione. Ha fatto un tentativo, e ha funzionato.

Non era stato facile da trovare, così ho deciso di uscire dalla modalità lurker e condividerlo su SO.In tal modo: grazie @Andreyy per me portare in :)

[pry cd and ls]

+0

PS dopo tanti anni di in agguato, mi sono appena iscritto a SO e questo è il mio primo contributo. Guida apprezzata;) – Giuse

+0

C'è un errore di battitura nel codice ('new_coder' ->' name_coder') e mi ci sarebbero voluti due minuti anziché cinque per verificare la tua risposta se avessi mostrato il messaggio di errore. Ma niente di tutto questo è importante. Hai risolto ciò che nessun altro potrebbe, anche quando ho offerto una taglia. Spunta, spunta, spunta. Grazie molto! –

+0

Non ho alcun errore da mostrare, dal momento che utilizzo 'nome_coder' nella mia implementazione. Il mio campo è in realtà chiamato 'nome', quindi la mia scelta di' nome_codice', che sfortunatamente echi 'c.name' nel codice ... confuso ancora? Ecco perché ho provato a cambiare il nome: P Grazie per aver individuato l'ultimo di loro, ero praticamente esaurito per il giorno in cui ho scritto questa risposta. Felice di aiutare! :) – Giuse

0
  1. Google il messaggio di errore: "Attenzione: non cast di tipo definito per tipo"
  2. si può trovare è fonte github.
  3. Reding classe, direi linee 150-214 potrebbero essere consiredered esempi:
    • register_type 0, 'text', PG::TextEncoder::String
    • alias_type 0, 'varchar', 'text'
  4. Dal register_type e alias_type sono metodi della classe di PG::BasicTypeRegistry::CoderMap Vorrei giocare con solo loro e vedere se qualcosa cambia:
    • PG::BasicTypeRegistry::CoderMap.alias_type 0, 'money', 'text'
    • PG::BasicTypeRegistry::CoderMap.alias_type 0, 'numeric', 'text'

Leggendo i commenti nella classe sembra che la codifica/decodifica di quelli e alcuni altri campi non è implementata.

È possibile utilizzare una libreria ORM di livello superiore come AvtiveRecord che implementa più tipi (money).

+0

Naturalmente, ho già fatto queste cose. Penso che forse se Pg fosse in grado di supportare Money semplicemente passando 'denaro' come stringa a Codermap, lo farebbe già? Sono abbastanza sicuro di aver bisogno di creare un nuovo oggetto Coder che traduca i tipi numerici e di denaro in un BigDecimal. Ma nulla nella fonte che ho visto finora mi dice come configurare un nuovo oggetto Coder, o dove collegarlo ... –

+0

Cosa ne pensi di prendere uno dei coder/decoder pirs di fine esempio? https://goo.gl/3Dhe5c – Andreyy

+0

"Nulla nella fonte che ho visto finora mi dice come configurare un nuovo oggetto Coder" –

2

dirottamento questa discussione, come dopo qualche scavo ho finalmente trovato un modo per aggiungere un decodificatore/codificatore personalizzato, quindi pubblicare un esempio di seguito:

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) 
Problemi correlati