Ok, jeg fandt et svar. I PostgreSQL kan du skrive funktioner ved hjælp af Python. For at aktivere brugen af Python, skal du installere den specifikke version af Python, der er nødvendig for din installation af PostgreSQL, og have den tilgængelig i PATH-miljøvariablen. Du kan finde ud af, hvilken version af Python din installation af PostgreSQL har brug for, ved at se på installationsnoterne. Jeg bruger i øjeblikket PostgreSQL 9.6.5 på Windows, og det kræver Python 3.3. Jeg prøvede i første omgang den nyeste Python 3.6, men det virkede ikke. Jeg nøjedes med den seneste Python 3.3 til Windows, som er 3.3.5.
Efter installation af Python, aktiverer du det i PostgreSQL ved at udføre CREATE EXTENSION plpython3u;
på din database som dokumenteret her https://www.postgresql.org/docs /current/static/plpython.html
. Derfra kan du skrive enhver funktion med Python-kroppe.
For mit specifikke tilfælde at konvertere fra bytea
til double precision[]
og tilbage skrev jeg følgende funktioner:
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$;
I mit tilfælde er alle doublerne gemt i little endian, så jeg bruger <
. Jeg cacher også importen af struct
modul i den globale ordbog som beskrevet i https://stackoverflow.com/a/15025425/5274457 . Jeg brugte GD i stedet for SD, fordi jeg vil have importen tilgængelig i andre funktioner, jeg kan skrive. For information om GD og SD, se https://www.postgresql .org/docs/current/static/plpython-sharing.html
.
For at se det i aktion vel vidende, at klatterne i min database er gemt som little endian,
SELECT bytea_to_double_array(decode('efbeaddeefbeadde', 'hex')), encode(double_array_to_bytea(array[-1.1885959257070704E148]), 'hex');
Og det svar jeg får er
bytea_to_double_array | encode
double precision[] | text
-------------------------+------------------
{-1.18859592570707e+148} | efbeaddeefbeadde
hvor 'efbeaddeefbeadde'
er 'deadbeefdeadbeef'
i lille endian.