【JPUG主催】PostgreSQLカンファレンス2020【11月13日開催】
他のバージョンの文書 12 | 11 | 10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

25.3. 説明

25.3.1. PL/Perl 関数と引数

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

CREATE FUNCTION funcname (argument-types) RETURNS return-type AS '
    # PL/Perl function body
' LANGUAGE plperl;

PL/PerlU の場合は、その言語として plperlu を指定しなければならない点を除き、同じです。

関数本体は通常の Perl のコードです。引数と結果は他の Perl サブルーチンと同様に扱われます。引数は @_ の中に渡され、結果値は return を使用、または、その関数で最後に評価された式として返されます。例えば、2つの整数値の内大きい数を返す関数は以下のように定義できます。

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

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

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

上で示した通り、PL/Perl 関数から NULL を返すためには、未定義値を返して下さい。これは、関数が厳密(strict)かどうかにかかわらず行うことができます。

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

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;

現在、複合型を結果値として返すことはできません。

Tip: 関数本体は、CREATE FUNCTION にSQL 文字リテラルとして渡されますので、Perl ソース内の単一引用符やバックスラッシュをエスケープしなければなりません。通常は上の例のようにそれらを二重にします。他の方法はPerl の拡張引用関数 (q[]qq[]qw[]) を使用して、単一引用符を使用しないようにすることです。

セキュリティ上の理由により許されていないファイルシステム操作を行うため、うまく動作しない関数の例を以下に示します。

CREATE FUNCTION badfunc() RETURNS integer AS '
    open(TEMP, ">/tmp/badfile");
    print TEMP "Gotcha!\n";
    return 1;
' LANGUAGE plperl;

関数を作成することは成功しますが、実行させることはできません。

スーパユーザによって同じ名前の関数がplperlu言語で作成された場合、実行することができることに注意して下さい。

25.3.2. PL/Perl におけるデータ値

PL/Perl 関数スクリプトに与えられる引数の値は、(SELECT 文によって表示されるものと同じ)テキスト形式に変換された単なる入力引数です。反対に、return は関数宣言における戻り値型用の入力関数で受け付けることができる、任意の文字列を受け付けます。ですから、PL/Perl のプログラマはあたかも単なるテキストかのようにデータ値を扱うことができます。

25.3.3. PL/Perlからのデータベースアクセス

Perl 関数からのデータベースアクセスを、 DBD::PgSPI という実験段階のモジュール経由で行うことができます(これも CPAN ミラーサイト から入手できます)。このモジュールにより、DBI互換の$pg_dbh データベースハンドルを使用することができます。このハンドルを使用して、通常のDBI構文を使用した問い合わせを行うことができます。

現在、PL/Perl 自体は以下の補助的な Perl コマンドのみを提供します。

elog level, msg

ログまたはエラーメッセージを発行します。使用できるレベルは DEBUGNOTICEおよびERROR です。DEBUGNOTICE は単に指定されたメッセージを postmaster のログに発行します(そして、NOTICE の場合はクライアントにもそのメッセージを送信します)。 ERROR はエラー状態を発生し、以降のその関数の実行は停止され、現在のトランザクションは中断します。

25.3.4. 存在しない機能

PL/Perl 関数は互いに直接呼び出すことができません(Perl の内部では匿名のサブルーチンであるからです)。現在、関数間でグローバル変数を共有する方法はありません。

PL/Perl は現在トリガ関数を作成することに使用できません。

DBD::PgSPI や似たような能力は、標準 PostgreSQL 配布物内に統合されるべきです。