Bon, j'ai trouvé une réponse. Dans PostgreSQL, vous pouvez écrire des fonctions en utilisant Python. Afin d'activer l'utilisation de Python, vous devez installer la version spécifique de Python requise par votre installation de PostgreSQL et l'avoir disponible dans la variable d'environnement PATH. Vous pouvez trouver la version de Python dont votre installation de PostgreSQL a besoin en consultant les notes d'installation. J'utilise actuellement PostgreSQL 9.6.5 sous Windows et il appelle Python 3.3. J'ai d'abord essayé le dernier Python 3.6, mais cela ne fonctionnait pas. Je me suis installé avec le dernier Python 3.3 pour Windows, qui est 3.3.5.
Après avoir installé Python, vous l'activez dans PostgreSQL en exécutant CREATE EXTENSION plpython3u;
sur votre base de données comme documenté ici https://www.postgresql.org/docs /current/static/plpython.html
. À partir de là, vous pouvez écrire n'importe quelle fonction avec des corps Python.
Pour mon cas spécifique à convertir à partir de bytea
en double precision[]
et retour, j'ai écrit les fonctions suivantes :
CREATE FUNCTION bytea_to_double_array(b bytea)
RETURNS double precision[]
LANGUAGE 'plpython3u'
AS $BODY$
if 'struct' in GD:
struct = GD['struct']
else:
import struct
GD['struct'] = struct
return struct.unpack('<' + str(int(len(b) / 8)) + 'd', b)
$BODY$;
CREATE FUNCTION double_array_to_bytea(dblarray double precision[])
RETURNS bytea
LANGUAGE 'plpython3u'
AS $BODY$
if 'struct' in GD:
struct = GD['struct']
else:
import struct
GD['struct'] = struct
# dblarray here is really a list.
# PostgreSQL passes SQL arrays as Python lists
return struct.pack('<' + str(int(len(dblarray))) + 'd', *dblarray)
$BODY$;
Dans mon cas, tous les doubles sont stockés en petit boutiste, j'utilise donc <
. Je mets également en cache l'import de la struct
module dans le dictionnaire global comme décrit dans https://stackoverflow.com/a/15025425/5274457 . J'ai utilisé GD au lieu de SD parce que je veux que l'importation soit disponible dans d'autres fonctions que je peux écrire. Pour plus d'informations sur GD et SD, voir https://www.postgresql .org/docs/current/static/plpython-sharing.html
.
Pour le voir en action sachant que les blobs de ma base de données sont stockés en tant que little endian,
SELECT bytea_to_double_array(decode('efbeaddeefbeadde', 'hex')), encode(double_array_to_bytea(array[-1.1885959257070704E148]), 'hex');
Et la réponse que j'obtiens est
bytea_to_double_array | encode
double precision[] | text
-------------------------+------------------
{-1.18859592570707e+148} | efbeaddeefbeadde
où 'efbeaddeefbeadde'
est 'deadbeefdeadbeef'
en petit boutien.