PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Konvertieren Sie bytea in PostgreSQL in doppelte Genauigkeit

Ok, ich habe eine Antwort gefunden. In PostgreSQL können Sie Funktionen mit Python schreiben. Um die Verwendung von Python zu ermöglichen, müssen Sie die spezifische Version von Python installieren, die von Ihrer Installation von PostgreSQL benötigt wird, und sie in der PATH-Umgebungsvariable verfügbar haben. Welche Python-Version Ihre Installation von PostgreSQL benötigt, können Sie den Installationshinweisen entnehmen. Ich verwende derzeit PostgreSQL 9.6.5 unter Windows und es fordert Python 3.3. Ich habe zunächst das neueste Python 3.6 ausprobiert, aber es würde nicht funktionieren. Ich entschied mich für das neueste Python 3.3 für Windows, das 3.3.5 ist.

Nach der Installation von Python aktivieren Sie es in PostgreSQL, indem Sie CREATE EXTENSION plpython3u; ausführen in Ihrer Datenbank, wie hier dokumentiert https://www.postgresql.org/docs /current/static/plpython.html . Von dort aus können Sie jede Funktion mit Python-Körpern schreiben.

Für meinen speziellen Fall zum Konvertieren von bytea auf double precision[] und zurück habe ich folgende Funktionen geschrieben:

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$;

In meinem Fall werden alle Doubles in Little Endian gespeichert, also verwende ich < . Ich cache auch den Import der struct Modul im globalen Wörterbuch, wie beschrieben in https://stackoverflow.com/a/15025425/5274457 . Ich habe GD anstelle von SD verwendet, weil ich möchte, dass der Import in anderen Funktionen verfügbar ist, die ich möglicherweise schreibe. Informationen zu GD und SD finden Sie unter https://www.postgresql .org/docs/current/static/plpython-sharing.html .

Um es in Aktion zu sehen und zu wissen, dass die Blobs in meiner Datenbank als Little Endian gespeichert sind,

SELECT bytea_to_double_array(decode('efbeaddeefbeadde', 'hex')), encode(double_array_to_bytea(array[-1.1885959257070704E148]), 'hex');

Und die Antwort, die ich bekomme, ist

bytea_to_double_array    | encode
double precision[]       | text
-------------------------+------------------
{-1.18859592570707e+148} | efbeaddeefbeadde

wo 'efbeaddeefbeadde' ist 'deadbeefdeadbeef' in Little-Endian.