Вот пример кода, показывающий, как это сделать с помощью Perl на стороне сервера. К сожалению, упаковка / распаковка PG считаются недоверенными операциями, поэтому суперпользователь должен создать ее с помощью plperlu, а затем предоставить доступ с GRANT EXECUTE не суперпользователю.
С другой стороны, этот выбор языка облегчает работу с более сложными упакованными структурами, что является значительным преимуществом по сравнению с кодом, основанным на функциях SQL get_bytes () / set_bytes (). Смотрите Особенности пакета Perl .
1) первый шаг: определить составной тип SQL, представляющий неупакованную запись.
create type comp as (a smallint, b smallint, c int);
2) сделать функцию для упаковки значения записи в bytea:
create function pack_comp(comp) returns bytea
as $body$
my $arg=shift;
my $retval = pack("CCL", $arg->{a},$arg->{b},$arg->{c});
# encode bytea according to PG doc. For PG>=9.0, use encode_bytea() instead
$retval =~ s!(\\|[^ -~])!sprintf("\\%03o",ord($1))!ge; # from PG doc
return $retval;
$body$ language plperlu;
3) сделать функцию для распаковки байтов в составной тип:
create or replace function unpack_comp(bytea) returns comp
as $body$
my $arg=shift;
# decode bytea according to PG doc. For PG>=9.0, use decode_bytea() instead
$arg =~ s!\\(?:\\|(\d{3}))!$1 ? chr(oct($1)) : "\\"!ge;
my ($v,$i,$e)= unpack("CCL", $arg);
return {"a"=>$v, "b"=>$i, "c"=>$e};
$body$ language plperlu;
4) использование:
# select encode(pack_comp((254,14,1000000)::comp), 'hex');
encode
--------------
fe0e40420f00
# select unpack_comp(decode('fe0e40420f00','hex'));
unpack_comp
------------------
(254,14,1000000)
# select * from unpack_comp(decode('fe0e40420f00','hex'));
a | b | c
-----+----+---------
254 | 14 | 1000000