Добре, намерих отговор. В PostgreSQL можете да пишете функции с помощта на Python. За да разрешите използването на Python, трябва да инсталирате конкретната версия на Python, необходима за вашата инсталация на PostgreSQL, и да я имате достъпна в променливата на средата PATH. Можете да намерите от коя версия на Python се нуждае вашата инсталация на PostgreSQL, като разгледате бележките за инсталиране. В момента използвам PostgreSQL 9.6.5 на Windows и изисква Python 3.3. Първоначално опитах най-новия Python 3.6, но нямаше да работи. Спрях се на най-новия Python 3.3 за Windows, който е 3.3.5.
След като инсталирате Python, вие го активирате в PostgreSQL, като изпълните CREATE EXTENSION plpython3u;
във вашата база данни, както е документирано тук https://www.postgresql.org/docs /current/static/plpython.html
. Оттам можете да пишете всяка функция с тела на Python.
За моя конкретен случай за конвертиране от bytea
към double precision[]
и обратно, написах следните функции:
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$;
В моя случай всички удвоявания се съхраняват в little endian, така че използвам <
. Също така кеширам импортирането на struct
модул в глобалния речник, както е описано в https://stackoverflow.com/a/15025425/5274457 . Използвах GD вместо SD, защото искам импортирането да е налично в други функции, които може да напиша. За информация относно GD и SD вижте https://www.postgresql .org/docs/current/static/plpython-sharing.html
.
За да го видя в действие, като знам, че петната в моята база данни се съхраняват като little endian,
SELECT bytea_to_double_array(decode('efbeaddeefbeadde', 'hex')), encode(double_array_to_bytea(array[-1.1885959257070704E148]), 'hex');
И отговорът, който получавам е
bytea_to_double_array | encode
double precision[] | text
-------------------------+------------------
{-1.18859592570707e+148} | efbeaddeefbeadde
където 'efbeaddeefbeadde'
е 'deadbeefdeadbeef'
в Little Endian.