Oké, ik heb een antwoord gevonden. In PostgreSQL kun je functies schrijven met Python. Om het gebruik van Python mogelijk te maken, moet u de specifieke versie van Python installeren die nodig is voor uw installatie van PostgreSQL en deze beschikbaar hebben in de omgevingsvariabele PATH. U kunt vinden welke versie van Python uw installatie van PostgreSQL nodig heeft door de installatie-opmerkingen te bekijken. Ik gebruik momenteel PostgreSQL 9.6.5 op Windows en het vraagt om Python 3.3. Ik heb aanvankelijk de nieuwste Python 3.6 geprobeerd, maar het zou niet werken. Ik heb genoegen genomen met de nieuwste Python 3.3 voor Windows, namelijk 3.3.5.
Nadat je Python hebt geïnstalleerd, schakel je het in PostgreSQL in door CREATE EXTENSION plpython3u;
uit te voeren. op uw database zoals hier gedocumenteerd https://www.postgresql.org/docs /current/static/plpython.html
. Van daaruit kun je elke functie schrijven met Python-lichamen.
Voor mijn specifieke geval om te converteren van bytea
tot double precision[]
en terug schreef ik de volgende functies:
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 mijn geval worden alle dubbels opgeslagen in little endian, dus ik gebruik <
. Ik cache ook de import van de struct
module in het globale woordenboek zoals beschreven in https://stackoverflow.com/a/15025425/5274457 . Ik heb GD gebruikt in plaats van SD omdat ik de import beschikbaar wil hebben in andere functies die ik kan schrijven. Voor informatie over GD en SD, zie https://www.postgresql .org/docs/current/static/plpython-sharing.html
.
Om het in actie te zien wetende dat de blobs in mijn database zijn opgeslagen als little endian,
SELECT bytea_to_double_array(decode('efbeaddeefbeadde', 'hex')), encode(double_array_to_bytea(array[-1.1885959257070704E148]), 'hex');
En het antwoord dat ik krijg is
bytea_to_double_array | encode
double precision[] | text
-------------------------+------------------
{-1.18859592570707e+148} | efbeaddeefbeadde
waar 'efbeaddeefbeadde'
is 'deadbeefdeadbeef'
in little endian.