Comment puis-je retourner une chaîne binaire (bytea) dans une routine PL / Python PostgreSQL?
-
22-10-2019 - |
Question
Je suis actuellement en train d'écrire une procédure en PL / Python pour effectuer une conversion de certaines données, puis retourner le résultat en tant que bytea
. (Il est assez moche, en fait:? Marshalling les données OCaml truand en Python et OCaml à la fois, dois-je obtenir une médaille)
Voici à quoi il ressemble:
CREATE OR REPLACE FUNCTION ml_marshal(data varchar) RETURNS bytea as $$
import tempfile, os
fn = tempfile.mktemp()
f = open(fn, 'w')
dest_fn = tempfile.mktemp()
f.write("let outch = open_out_bin \"" + dest_fn + "\" in " +
"Marshal.to_channel outch (" + data + ") [Marshal.No_sharing]; " +
"close_out outch")
f.close()
os.system("ocaml " + fn)
os.unlink(fn)
f = open(dest_fn, 'r')
res = f.read()
f.close()
os.unlink(dest_fn)
return res
$$ LANGUAGE plpythonu;
En bref, il écrit un petit programme OCaml à un tempfile qui crée une autre tempfile avec les données que nous voulons. On lit alors que tempfile dans Extermine les deux, et de retourner le résultat.
Seulement il ne pas tout à fait le travail:
meidi=# select * from tblmodel;
modelid | polies
---------+------------------
1 | \204\225\246\276
2 | \204\225\246\276
Il y a quatre octets dans chacune (il devrait y avoir ~ 130). Si je l'arrête dissociant les fichiers, il devient évident pourquoi; il y a quatre non NUL octets, suivi par un couple de NUL, et il semble ces NUL sont traités comme terminateurs à un certain moment par la conversion de Python à Postgres!
Quelqu'un sait pourquoi cela se produit, ou comment l'arrêter? Docs ne sont pas éclairantes.
Merci!
Modifier : J'ai trouvé quelqu'un d'autre avec le même problème , mais la solution est assez peu satisfaisante.
La solution
Ceci a été corrigé avec la version 9.0. J'ai eu le même problème donc je mis à jour. Des notes de version de:
Improve bytea support in PL/Python (Caleb Welton)
Bytea values passed into PL/Python are now represented as binary, rather than the PostgreSQL bytea text format. Bytea values containing null bytes are now also output properly from PL/Python. Passing of boolean, integer, and float values was also improved.
Je ne pense pas qu'il y ait une solution très élégante pour ce problème dans les versions précédentes de PostgreSQL.
Autres conseils
Vous pourriez appliquer un autre encode bodge- la valeur de retour de python en base64, et utiliser la fonction de décodage de PostgreSQL pour le décoder, à savoir. decode(ml_marshal(xxx), 'base64')
.
ou mise à jour 9.0 comme indiqué par Adrian:)