サーバー側の Perl でそれを行う方法を示すサンプル コードを次に示します。厄介なことに、パック/アンパックは PG によって信頼できない操作と見なされるため、スーパーユーザーが plperlu を使用して作成し、GRANT EXECUTE を使用してスーパーユーザー以外にアクセスを許可する必要があります。
一方、この言語の選択により、より複雑なパック構造を簡単に処理できるようになります。これは、SQL の get_bytes()/set_bytes() 関数に基づくコードよりも大きな利点です。Perl の pack() 機能を参照してください。
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) bytea を複合型に展開する関数を作成します。
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