On Wed, 16 Feb 2011 16:13:16 +0100, Stefano Dal Pra <s.dal...@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. 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@lists.python.it http://lists.python.it/mailman/listinfo/python