PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Convertir bytea en double précision dans PostgreSQL

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

'efbeaddeefbeadde' est 'deadbeefdeadbeef' en petit boutien.