[Python] psycopg2 e bytea

Stefano Dal Pra s.dalpra a gmail.com
Mer 16 Feb 2011 17:19:18 CET


2011/2/16 Daniele Varrazzo <piro a develer.com>

> On Wed, 16 Feb 2011 16:13:16 +0100, Stefano Dal Pra <s.dalpra a gmail.com>
> wrote:
> > Ciao Daniele, credo che un problema analogo valga anche per i boolean in
> > postgres.
> >
> > Sto migrando un db mysql in uno equivalente postgres.
> > faccio sostanzialmente cose tipo:
> >
> > mysqlcurs.execute("select * from Tab")
> > T = mysqlcurs.fetchall() #ci stanno, ci stanno... :-)
> > ...
> > fms = ','.join("%s" for x in range(len(T[0])))
> > for tup in T:
> >     pg.curs.execute("insert into %s values (%s)"%(tablename,fms),tup)
> >
> >
> > mysqldump mappa false/true in 0/1, per cui
> > psycopg2.execute("insert into T (boolvalue) values (%s)",1)
> > da errore (TypeError se ricordo bene?).
>
> No, questo TypeError viene dal fatto che in questo esempio hai usato "1" e
> non una sequenza per passare gli argomenti.
>

Scusami, purtroppo ho scritto "a memoria" invece di fare un sano cut&paste.
Quello che faccio equivale in realta' al test che hai messo tu:
cur.execute("insert into  testbool values (%s), (%s), (%s);",
(1,0,None))

insomma passo una tupla come si deve.

Quel che mi chiedo io e':
se dopo un connect psycopg2



> Strano che postgres non converta valori numerici 1/0 in booleani, ma
> confermo che è così:
>
>    In [10]: cur.execute("create table testbool (x bool);")
>
>    In [11]: cur.execute("insert into  testbool values (%s), (%s), (%s);",
> (1,0,None))
>
> ---------------------------------------------------------------------------
>    ProgrammingError                          Traceback (most recent call
> last)
>
>    /home/piro/src/psycopg2/<ipython console> in <module>()
>
>    ProgrammingError: column "x" is of type boolean but expression is of
> type integer
>    LINE 1: insert into  testbool values (1), (0), (NULL);
>                                          ^
>    HINT:  You will need to rewrite or cast the expression.
>
> È strano perchè quando viene forzato a fare un cast esplicito non ha
> problemi:
>
>    In [12]: cur.execute("insert into  testbool values (%s::bool),
> (%s::bool), (%s::bool);", (1,0,None))
>
>    In [13]: cur.execute("select * from testbool;")
>
>    In [14]: cur.fetchall()
>    Out[14]: [(True,), (False,), (None,)]
>
> Un cast in postgres c'è, ma non è "implicito". Non saprei perché.
>
>
> > Al momento risolvo la cosa con un dizionario:
> > dbool = {0:False,1:True,None:None}
> > (nota che bool(None) --> False, che per i db non va bene)
> > e rimappando i campi boolean prima di inserirli...
>
> Mi sembra una buona soluzione. Quella analoga al caso dei bytea
> consisterebbe nel wrappare i bool (e non tutti gli interi)... anche se
> esistesse questo adapter (sarebbe facile da scrivere) non darebbe nessun
> vantaggio rispetto al mapping.
>
> Una soluzione alternativa sarebbe quella di identificare quali sono i
> campi booleani e usare dei cast dopo i segnaposto come nella [12]. Puoi
> addirittura chiedere automaticamente a postgres quali siano i campi bool
> nella tua tabella:
>
>    In [21]: cur.execute("create table stuff (foo int, bar bool, baz
> text);")
>
>    In [22]: cur.execute("select * from stuff limit 0")
>
>    In [23]: cur.description
>    Out[23]:
>    (('foo', 23, None, 4, None, None, None),
>     ('bar', 16, None, 1, None, None, None),
>     ('baz', 25, None, -1, None, None, None))
>
> I campi di tipo 16 sono i bool: puoi generare placeholder col cast da
> questa informazione:
>
>    In [25]: ",".join(t[1] == 16 and "%s::bool" or "%s" for t in
> cur.description)
>    Out[25]: '%s,%s::bool,%s'
>
>
> > Versioni + recenti di psycopg2 si comportano diversamente in questo
> caso?
>
> No: il cast in sql viene scelto in base al tipo: se mysql passa un integer
> sia per interi che per bool, python non fa distinzione di tipo tra i due e
> psycopg usa lo stesso mapping per entrambi.
>
>
> --
> Daniele Varrazzo - Develer S.r.l.
> http://www.develer.com
> _______________________________________________
> Python mailing list
> Python a lists.python.it
> http://lists.python.it/mailman/listinfo/python
>
-------------- parte successiva --------------
Un allegato HTML è stato rimosso...
URL: <http://lists.python.it/pipermail/python/attachments/20110216/01264bb7/attachment.html>


Maggiori informazioni sulla lista Python