第 38章PL/Perl - Perl手続き言語

目次
38.1. PL/Perl関数と引数
38.2. PL/Perlからのデータベースアクセス
38.3. PL/Perlにおけるデータ値
38.4. PL/Perlにおけるグローバル変数
38.5. 信頼されたPL/Perlおよび信頼されないPL/Perl
38.6. PL/Perlトリガ
38.7. 制限および存在しない機能

PL/PerlはPerlプログラミング言語を使用してPostgreSQL関数を作成することができる、ロード可能な手続き言語です。

PL/Perlを特定のデータベースにインストールするには、createlang plperl dbnameを使用してください。

ティップ: 言語をtemplate1にインストールすると、その後に作成されるデータベース全てにその言語は自動的にインストールされます。

注意: ソースパッケージを使用するユーザは、インストール作業時にPL/Perlを特別に使用可能にする必要があります (詳細については、項14.1を参照してください)。 バイナリパッケージを使用する場合は、別個のサブパッケージにPL/Perlが入っている可能性があります。

38.1. PL/Perl関数と引数

PL/Perl言語で関数を作成するには、以下の標準的なCREATE FUNCTION構文を使用してください。

CREATE FUNCTION funcname (argument-types) RETURNS return-type AS $$
    # PL/Perl関数本体
$$ LANGUAGE plperl;

関数本体は通常のPerlのコードです。 実際、PL/Perlの糊付けコードは、これをPerlのサブルーチンの内部に格納します。 PL/Perl関数は常にスカラ値を返さなければなりません。 後述の通り、参照を使用して複雑な構造(配列、レコード、集合)を返すことができます。 リストを返してはなりません。

注意: Perl、特にその閉ざされたスコープで局所変数を参照するような場合では、名前付きの入れ子状サブルーチンの使用は危険です。 PL/Perl関数はサブルーチン内に格納されますので、名前付きのサブルーチンはすべて入れ子にされます。 一般的に、コード参照を介して呼び出す匿名サブルーチンを作成する方がかなり安全です。 詳細はperldiagマニュアルページを参照してください。

CREATE FUNCTIONコマンドの構文では、関数本体は文字列定数として記述されることを必須としています。 通常、文字列定数にはドル引用符付け(項4.1.2.2を参照)を使用することが最も便利です。 通常の単一引用符による文字列定数構文の使用を選択したとすると、通常、関数本体で使用される単一引用符(')とバックスラッシュ(\)を二重にすることによってエスケープする必要があります(項4.1.2.1を参照)。

引数と結果は他のPerlサブルーチンと同様に扱われます。 引数は@_の中に渡され、結果値はreturn、または、その関数で最後に評価された式として返されます。

例えば、2つの整数のうち大きな方を返す関数は以下のように定義できます。

CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS $$
    if ($_[0] > $_[1]) { return $_[0]; }
    return $_[1];
$$ LANGUAGE plperl;

SQLのNULL値が関数に渡された場合、その引数値はPerlにおける"未定義"として現れます。 上の関数定義では、NULL値が入力された場合うまく動作しないでしょう(実際はそれがゼロであるかのように動作するでしょう)。 STRICTを関数定義に加えることで、PostgreSQLの動作をより合理的にすることができます。 NULL値が渡された場合、関数はまったく呼び出されず、単にNULLという結果が自動的に返されます。 他の方法として、関数本体で未定義な入力をチェックすることもできます。 例えば、perl_maxの引数の片方がNULL、もう片方が非NULLの場合に、NULL値ではなく非NULLの引数を返すようにするとします。

CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS $$
    my ($x,$y) = @_;
    if (! defined $x) {
        if (! defined $y) { return undef; }
        return $y;
    }
    if (! defined $y) { return $x; }
    if ($x > $y) { return $x; }
    return $y;
$$ LANGUAGE plperl;

上で示した通り、PL/Perl関数からSQLのNULL値を返すためには、未定義値を返すようにしてください。 これは、関数が厳密かどうかに関係なく、実行することができます。

Perlは、PostgreSQLの配列をPerl配列への参照として返すことができます。 以下に例を示します。

CREATE OR REPLACE function returns_array()
RETURNS text[][] AS $$
    return [['a"b','c,d'],['e\\f','g']];
$$ LANGUAGE plperl;

select returns_array();

複合型の引数はハッシュへの参照として関数に渡されます。 ハッシュのキーは複合型の属性名です。 以下に例を示します。

CREATE TABLE employee (
    name text,
    basesalary integer,
    bonus integer
);

CREATE FUNCTION empcomp(employee) RETURNS integer AS $$
    my ($emp) = @_;
    return $emp->{basesalary} + $emp->{bonus};
$$ LANGUAGE plperl;

SELECT name, empcomp(employee.*) FROM employee;

必要な属性を持つハッシュの参照を返すという同じ方法で、PL/Perl関数は複合型の結果を返すことができます。 以下に例を示します。

CREATE TYPE testrowperl AS (f1 integer, f2 text, f3 text);

CREATE OR REPLACE FUNCTION perl_row() RETURNS testrowperl AS $$
    return {f2 => 'hello', f1 => 1, f3 => 'world'};
$$ LANGUAGE plperl;

SELECT * FROM perl_row();

宣言されたデータ型の任意の列のうち、ハッシュ内に存在しないものはNULLとして返されます。

また、PL/Perl関数はスカラ型の配列や複合型の配列を返すこともできます。 通常ならば、起動処理の高速化とメモリ内の結果セット全体を待ち行列に保持できることから、1度に1行を返す方がよいでしょう。 以下に示すreturn_nextを使用して、これを行うことができます。 最後のreturn_nextの後で、returnまたはreturn undef(推奨)を記述しなければならないことに注意してください。

CREATE OR REPLACE FUNCTION perl_set_int(int)
RETURNS SETOF INTEGER AS $$
    foreach (0..$_[0]) {
        return_next($_);
    }
    return undef;
$$ LANGUAGE plperl;

SELECT * FROM perl_set_int(5);

CREATE OR REPLACE FUNCTION perl_set()
RETURNS SETOF testrowperl AS $$
    return_next({ f1 => 1, f2 => 'Hello', f3 => 'World' });
    return_next({ f1 => 2, f2 => 'Hello', f3 => 'PostgreSQL' });
    return_next({ f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' });
    return undef;
$$ LANGUAGE plperl;

小規模な結果セットでは、それぞれ単純な型、配列型、複合型に対応する、スカラ、配列への参照、ハッシュへの参照を含む配列への参照を返すことができます。 以下に、配列への参照として結果セット全体を返す単純な例をいくつか示します。

CREATE OR REPLACE FUNCTION perl_set_int(int) RETURNS SETOF INTEGER AS $$
    return [0..$_[0]];
$$ LANGUAGE plperl;

SELECT * FROM perl_set_int(5);

CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$
    return [
        { f1 => 1, f2 => 'Hello', f3 => 'World' },
        { f1 => 2, f2 => 'Hello', f3 => 'PostgreSQL' },
        { f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' }
    ];
$$ LANGUAGE plperl;

SELECT * FROM perl_set();

今のところPL/Perlはドメイン型を完全にサポートしていません。 ドメインをその背後にあるスカラ型と同様に扱います。 これは、ドメインに関連する制約が強制されないことを意味しています。 これは関数の引数では問題ありませんが、PL/Perl関数をドメイン型を返すように宣言した場合は危険です。

コード内でstrictプラグマを使用したいのであれば、SET plperl.use_strictを真とすることがもっとも簡単な方法です。 このパラメータは、その後のPL/Perl関数のコンパイルに影響します。 現在のセッションでコンパイル済みの関数には影響しません。 PL/Perlをロードする前にこのパラメータを設定するには、postgresql.conf内のcustom_variable_classes一覧に"plperl"を追加しなければなりません。

strictプラグマを使用するための他の方法は、以下を関数本体に記載することです。

use strict;

しかし、これはPL/PerlU関数でしか動作しません。 useが信頼できる操作ではないからです。 PL/Perl関数では代わりに以下のようにしてください。

BEGIN { strict->import(); }