Okej, jag hittade ett svar. I PostgreSQL kan du skriva funktioner med Python. För att möjliggöra användningen av Python måste du installera den specifika version av Python som behövs för din installation av PostgreSQL och ha den tillgänglig i miljövariabeln PATH. Du kan hitta vilken version av Python din installation av PostgreSQL behöver genom att titta på installationsanteckningarna. Jag använder för närvarande PostgreSQL 9.6.5 på Windows och det kräver Python 3.3. Jag provade först den senaste Python 3.6, men det fungerade inte. Jag nöjde mig med den senaste Python 3.3 för Windows, vilket är 3.3.5.
Efter installation av Python aktiverar du det i PostgreSQL genom att köra CREATE EXTENSION plpython3u;
på din databas som dokumenterats här https://www.postgresql.org/docs /current/static/plpython.html
. Därifrån kan du skriva vilken funktion som helst med Python-kroppar.
För mitt specifika fall att konvertera från bytea
till double precision[]
och tillbaka skrev jag följande 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 mitt fall lagras alla dubblar i little endian, så jag använder <
. Jag cachelagrar också importen av struct
modul i den globala ordboken som beskrivs i https://stackoverflow.com/a/15025425/5274457 . Jag använde GD istället för SD eftersom jag vill ha importen tillgänglig i andra funktioner jag kan skriva. För information om GD och SD, se https://www.postgresql .org/docs/current/static/plpython-sharing.html
.
För att se det i aktion med att veta att blobbarna i min databas lagras som little endian,
SELECT bytea_to_double_array(decode('efbeaddeefbeadde', 'hex')), encode(double_array_to_bytea(array[-1.1885959257070704E148]), 'hex');
Och svaret jag får är
bytea_to_double_array | encode
double precision[] | text
-------------------------+------------------
{-1.18859592570707e+148} | efbeaddeefbeadde
där 'efbeaddeefbeadde'
är 'deadbeefdeadbeef'
i little endian.